summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scintilla/License.txt20
-rw-r--r--scintilla/README74
-rw-r--r--scintilla/bin/empty.txt1
-rw-r--r--scintilla/cocoa/Framework.mk85
-rw-r--r--scintilla/cocoa/InfoBar.h55
-rw-r--r--scintilla/cocoa/InfoBar.mm448
-rw-r--r--scintilla/cocoa/InfoBarCommunicator.h35
-rw-r--r--scintilla/cocoa/PlatCocoa.h119
-rw-r--r--scintilla/cocoa/PlatCocoa.mm2124
-rw-r--r--scintilla/cocoa/QuartzTextLayout.h141
-rw-r--r--scintilla/cocoa/QuartzTextStyle.h90
-rw-r--r--scintilla/cocoa/QuartzTextStyleAttribute.h142
-rw-r--r--scintilla/cocoa/SciTest.mk54
-rw-r--r--scintilla/cocoa/ScintillaCallTip.h63
-rw-r--r--scintilla/cocoa/ScintillaCallTip.mm117
-rw-r--r--scintilla/cocoa/ScintillaCocoa.h211
-rw-r--r--scintilla/cocoa/ScintillaCocoa.mm1471
-rw-r--r--scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.stringsbin0 -> 94 bytes
-rw-r--r--scintilla/cocoa/ScintillaFramework/Info.plist26
-rw-r--r--scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj969
-rw-r--r--scintilla/cocoa/ScintillaFramework/Scintilla_Prefix.pch7
-rw-r--r--scintilla/cocoa/ScintillaListBox.h64
-rw-r--r--scintilla/cocoa/ScintillaListBox.mm110
-rw-r--r--scintilla/cocoa/ScintillaTest/AppController.h23
-rw-r--r--scintilla/cocoa/ScintillaTest/AppController.mm215
-rw-r--r--scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.stringsbin0 -> 94 bytes
-rw-r--r--scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib3185
-rw-r--r--scintilla/cocoa/ScintillaTest/Info.plist28
-rw-r--r--scintilla/cocoa/ScintillaTest/Scintilla-Info.plist20
-rw-r--r--scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj381
-rw-r--r--scintilla/cocoa/ScintillaTest/ScintillaTest_Prefix.pch7
-rw-r--r--scintilla/cocoa/ScintillaTest/TestData.sql215
-rw-r--r--scintilla/cocoa/ScintillaTest/main.m15
-rw-r--r--scintilla/cocoa/ScintillaView.h120
-rw-r--r--scintilla/cocoa/ScintillaView.mm1376
-rw-r--r--scintilla/cocoa/res/info_bar_bg.pngbin0 -> 3081 bytes
-rw-r--r--scintilla/cocoa/res/mac_cursor_busy.pngbin0 -> 1191 bytes
-rw-r--r--scintilla/cocoa/res/mac_cursor_flipped.pngbin0 -> 446 bytes
-rw-r--r--scintilla/delbin.bat1
-rw-r--r--scintilla/delcvs.bat1
-rw-r--r--scintilla/doc/Design.html249
-rw-r--r--scintilla/doc/Icons.html56
-rw-r--r--scintilla/doc/Lexer.txt226
-rw-r--r--scintilla/doc/SciBreak.jpgbin0 -> 33592 bytes
-rw-r--r--scintilla/doc/SciCoding.html261
-rw-r--r--scintilla/doc/SciRest.jpgbin0 -> 16680 bytes
-rw-r--r--scintilla/doc/SciTEIco.pngbin0 -> 10091 bytes
-rw-r--r--scintilla/doc/SciWord.jpgbin0 -> 6164 bytes
-rw-r--r--scintilla/doc/ScintillaDoc.html6247
-rw-r--r--scintilla/doc/ScintillaDownload.html70
-rw-r--r--scintilla/doc/ScintillaHistory.html6780
-rw-r--r--scintilla/doc/ScintillaRelated.html495
-rw-r--r--scintilla/doc/ScintillaToDo.html157
-rw-r--r--scintilla/doc/ScintillaUsage.html375
-rw-r--r--scintilla/doc/Steps.html142
-rw-r--r--scintilla/doc/annotations.pngbin0 -> 33549 bytes
-rw-r--r--scintilla/doc/index.html190
-rw-r--r--scintilla/doc/styledmargin.pngbin0 -> 17138 bytes
-rw-r--r--scintilla/gtk/Converter.h70
-rw-r--r--scintilla/gtk/PlatGTK.cxx2577
-rw-r--r--scintilla/gtk/ScintillaGTK.cxx2536
-rw-r--r--scintilla/gtk/deps.mak337
-rw-r--r--scintilla/gtk/makefile89
-rw-r--r--scintilla/gtk/scintilla-marshal.c86
-rw-r--r--scintilla/gtk/scintilla-marshal.h21
-rw-r--r--scintilla/gtk/scintilla-marshal.list1
-rw-r--r--scintilla/include/Accessor.h79
-rw-r--r--scintilla/include/Face.py110
-rw-r--r--scintilla/include/HFacer.py75
-rw-r--r--scintilla/include/KeyWords.h113
-rw-r--r--scintilla/include/Platform.h556
-rw-r--r--scintilla/include/PropSet.h26
-rw-r--r--scintilla/include/SciLexer.h1390
-rw-r--r--scintilla/include/Scintilla.h965
-rw-r--r--scintilla/include/Scintilla.iface3784
-rw-r--r--scintilla/include/ScintillaWidget.h51
-rw-r--r--scintilla/include/WindowAccessor.h67
-rw-r--r--scintilla/macosx/ExtInput.cxx608
-rw-r--r--scintilla/macosx/ExtInput.h64
-rw-r--r--scintilla/macosx/PlatMacOSX.cxx1852
-rw-r--r--scintilla/macosx/PlatMacOSX.h99
-rw-r--r--scintilla/macosx/QuartzTextLayout.h141
-rw-r--r--scintilla/macosx/QuartzTextStyle.h94
-rw-r--r--scintilla/macosx/QuartzTextStyleAttribute.h144
-rw-r--r--scintilla/macosx/SciTest/English.lproj/InfoPlist.stringsbin0 -> 260 bytes
-rw-r--r--scintilla/macosx/SciTest/English.lproj/main.nib/classes.nib4
-rw-r--r--scintilla/macosx/SciTest/English.lproj/main.nib/info.nib19
-rw-r--r--scintilla/macosx/SciTest/English.lproj/main.nib/objects.xib271
-rw-r--r--scintilla/macosx/SciTest/Info.plist24
-rw-r--r--scintilla/macosx/SciTest/SciTest.xcode/project.pbxproj289
-rw-r--r--scintilla/macosx/SciTest/SciTest_Prefix.pch5
-rw-r--r--scintilla/macosx/SciTest/main.cpp255
-rw-r--r--scintilla/macosx/SciTest/version.plist16
-rw-r--r--scintilla/macosx/ScintillaCallTip.cxx117
-rw-r--r--scintilla/macosx/ScintillaCallTip.h64
-rw-r--r--scintilla/macosx/ScintillaListBox.cxx103
-rw-r--r--scintilla/macosx/ScintillaListBox.h63
-rw-r--r--scintilla/macosx/ScintillaMacOSX.cxx2242
-rw-r--r--scintilla/macosx/ScintillaMacOSX.h234
-rw-r--r--scintilla/macosx/TCarbonEvent.cxx519
-rw-r--r--scintilla/macosx/TCarbonEvent.h230
-rw-r--r--scintilla/macosx/TRect.h496
-rw-r--r--scintilla/macosx/TView.cxx1442
-rw-r--r--scintilla/macosx/TView.h286
-rw-r--r--scintilla/macosx/deps.mak375
-rw-r--r--scintilla/macosx/makefile115
-rw-r--r--scintilla/src/AutoComplete.cxx178
-rw-r--r--scintilla/src/AutoComplete.h78
-rw-r--r--scintilla/src/CallTip.cxx327
-rw-r--r--scintilla/src/CallTip.h87
-rw-r--r--scintilla/src/CellBuffer.cxx656
-rw-r--r--scintilla/src/CellBuffer.h208
-rw-r--r--scintilla/src/CharClassify.cxx78
-rw-r--r--scintilla/src/CharClassify.h37
-rw-r--r--scintilla/src/CharacterSet.h59
-rw-r--r--scintilla/src/ContractionState.cxx251
-rw-r--r--scintilla/src/ContractionState.h66
-rw-r--r--scintilla/src/Decoration.cxx188
-rw-r--r--scintilla/src/Decoration.h64
-rw-r--r--scintilla/src/Document.cxx1920
-rw-r--r--scintilla/src/Document.h426
-rw-r--r--scintilla/src/DocumentAccessor.cxx199
-rw-r--r--scintilla/src/DocumentAccessor.h77
-rw-r--r--scintilla/src/Editor.cxx8694
-rw-r--r--scintilla/src/Editor.h586
-rw-r--r--scintilla/src/ExternalLexer.cxx262
-rw-r--r--scintilla/src/ExternalLexer.h104
-rw-r--r--scintilla/src/FontQuality.h12
-rw-r--r--scintilla/src/Indicator.cxx81
-rw-r--r--scintilla/src/Indicator.h32
-rw-r--r--scintilla/src/KeyMap.cxx152
-rw-r--r--scintilla/src/KeyMap.h51
-rw-r--r--scintilla/src/KeyWords.cxx429
-rw-r--r--scintilla/src/LexAPDL.cxx256
-rw-r--r--scintilla/src/LexASY.cxx270
-rw-r--r--scintilla/src/LexAU3.cxx907
-rw-r--r--scintilla/src/LexAVE.cxx228
-rw-r--r--scintilla/src/LexAbaqus.cxx617
-rw-r--r--scintilla/src/LexAda.cxx525
-rw-r--r--scintilla/src/LexAsm.cxx180
-rw-r--r--scintilla/src/LexAsn1.cxx185
-rw-r--r--scintilla/src/LexBaan.cxx193
-rw-r--r--scintilla/src/LexBash.cxx521
-rw-r--r--scintilla/src/LexBasic.cxx373
-rw-r--r--scintilla/src/LexBullant.cxx229
-rw-r--r--scintilla/src/LexCLW.cxx679
-rw-r--r--scintilla/src/LexCOBOL.cxx368
-rw-r--r--scintilla/src/LexCPP.cxx506
-rw-r--r--scintilla/src/LexCSS.cxx371
-rw-r--r--scintilla/src/LexCaml.cxx449
-rw-r--r--scintilla/src/LexCmake.cxx457
-rw-r--r--scintilla/src/LexConf.cxx188
-rw-r--r--scintilla/src/LexCrontab.cxx222
-rw-r--r--scintilla/src/LexCsound.cxx210
-rw-r--r--scintilla/src/LexD.cxx399
-rw-r--r--scintilla/src/LexEScript.cxx273
-rw-r--r--scintilla/src/LexEiffel.cxx238
-rw-r--r--scintilla/src/LexErlang.cxx619
-rw-r--r--scintilla/src/LexFlagship.cxx352
-rw-r--r--scintilla/src/LexForth.cxx176
-rw-r--r--scintilla/src/LexFortran.cxx466
-rw-r--r--scintilla/src/LexGAP.cxx263
-rw-r--r--scintilla/src/LexGen.py287
-rw-r--r--scintilla/src/LexGui4Cli.cxx313
-rw-r--r--scintilla/src/LexHTML.cxx2131
-rw-r--r--scintilla/src/LexHaskell.cxx275
-rw-r--r--scintilla/src/LexInno.cxx279
-rw-r--r--scintilla/src/LexKix.cxx126
-rw-r--r--scintilla/src/LexLisp.cxx282
-rw-r--r--scintilla/src/LexLout.cxx212
-rw-r--r--scintilla/src/LexLua.cxx358
-rw-r--r--scintilla/src/LexMMIXAL.cxx186
-rw-r--r--scintilla/src/LexMPT.cxx188
-rw-r--r--scintilla/src/LexMSSQL.cxx363
-rw-r--r--scintilla/src/LexMagik.cxx445
-rw-r--r--scintilla/src/LexMarkdown.cxx412
-rw-r--r--scintilla/src/LexMatlab.cxx236
-rw-r--r--scintilla/src/LexMetapost.cxx399
-rw-r--r--scintilla/src/LexMySQL.cxx518
-rw-r--r--scintilla/src/LexNimrod.cxx430
-rw-r--r--scintilla/src/LexNsis.cxx655
-rw-r--r--scintilla/src/LexOpal.cxx522
-rw-r--r--scintilla/src/LexOthers.cxx1286
-rw-r--r--scintilla/src/LexPB.cxx362
-rw-r--r--scintilla/src/LexPLM.cxx198
-rw-r--r--scintilla/src/LexPOV.cxx316
-rw-r--r--scintilla/src/LexPS.cxx347
-rw-r--r--scintilla/src/LexPascal.cxx592
-rw-r--r--scintilla/src/LexPerl.cxx1305
-rw-r--r--scintilla/src/LexPowerPro.cxx600
-rw-r--r--scintilla/src/LexPowerShell.cxx175
-rw-r--r--scintilla/src/LexProgress.cxx279
-rw-r--r--scintilla/src/LexPython.cxx569
-rw-r--r--scintilla/src/LexR.cxx213
-rw-r--r--scintilla/src/LexRebol.cxx322
-rw-r--r--scintilla/src/LexRuby.cxx1715
-rw-r--r--scintilla/src/LexSML.cxx221
-rw-r--r--scintilla/src/LexSQL.cxx357
-rw-r--r--scintilla/src/LexScriptol.cxx408
-rw-r--r--scintilla/src/LexSmalltalk.cxx321
-rw-r--r--scintilla/src/LexSorcus.cxx205
-rw-r--r--scintilla/src/LexSpecman.cxx289
-rw-r--r--scintilla/src/LexSpice.cxx226
-rw-r--r--scintilla/src/LexTACL.cxx397
-rw-r--r--scintilla/src/LexTADS3.cxx904
-rw-r--r--scintilla/src/LexTAL.cxx396
-rw-r--r--scintilla/src/LexTCL.cxx366
-rw-r--r--scintilla/src/LexTeX.cxx494
-rw-r--r--scintilla/src/LexVB.cxx316
-rw-r--r--scintilla/src/LexVHDL.cxx476
-rw-r--r--scintilla/src/LexVerilog.cxx330
-rw-r--r--scintilla/src/LexYAML.cxx314
-rw-r--r--scintilla/src/LineMarker.cxx310
-rw-r--r--scintilla/src/LineMarker.h62
-rw-r--r--scintilla/src/Partitioning.h184
-rw-r--r--scintilla/src/PerLine.cxx486
-rw-r--r--scintilla/src/PerLine.h120
-rw-r--r--scintilla/src/PositionCache.cxx659
-rw-r--r--scintilla/src/PositionCache.h168
-rw-r--r--scintilla/src/PropSet.cxx176
-rw-r--r--scintilla/src/PropSetSimple.h33
-rw-r--r--scintilla/src/RESearch.cxx987
-rw-r--r--scintilla/src/RESearch.h75
-rw-r--r--scintilla/src/RunStyles.cxx216
-rw-r--r--scintilla/src/RunStyles.h46
-rw-r--r--scintilla/src/SVector.h123
-rw-r--r--scintilla/src/SciTE.properties6
-rw-r--r--scintilla/src/ScintillaBase.cxx774
-rw-r--r--scintilla/src/ScintillaBase.h100
-rw-r--r--scintilla/src/Selection.cxx366
-rw-r--r--scintilla/src/Selection.h187
-rw-r--r--scintilla/src/SplitVector.h249
-rw-r--r--scintilla/src/Style.cxx165
-rw-r--r--scintilla/src/Style.h64
-rw-r--r--scintilla/src/StyleContext.cxx55
-rw-r--r--scintilla/src/StyleContext.h177
-rw-r--r--scintilla/src/UniConversion.cxx131
-rw-r--r--scintilla/src/UniConversion.h13
-rw-r--r--scintilla/src/ViewStyle.cxx389
-rw-r--r--scintilla/src/ViewStyle.h135
-rw-r--r--scintilla/src/WindowAccessor.cxx191
-rw-r--r--scintilla/src/XPM.cxx326
-rw-r--r--scintilla/src/XPM.h80
-rw-r--r--scintilla/test/MessageNumbers.py63
-rw-r--r--scintilla/test/README31
-rw-r--r--scintilla/test/XiteMenu.py26
-rw-r--r--scintilla/test/XiteWin.py651
-rw-r--r--scintilla/test/examples/x.asp12
-rw-r--r--scintilla/test/examples/x.asp.styled12
-rw-r--r--scintilla/test/examples/x.cxx4
-rw-r--r--scintilla/test/examples/x.cxx.styled4
-rw-r--r--scintilla/test/examples/x.d47
-rw-r--r--scintilla/test/examples/x.d.styled47
-rw-r--r--scintilla/test/examples/x.html7
-rw-r--r--scintilla/test/examples/x.html.styled7
-rw-r--r--scintilla/test/examples/x.php6
-rw-r--r--scintilla/test/examples/x.php.styled6
-rw-r--r--scintilla/test/examples/x.py11
-rw-r--r--scintilla/test/examples/x.py.styled11
-rw-r--r--scintilla/test/examples/x.vb9
-rw-r--r--scintilla/test/examples/x.vb.styled9
-rw-r--r--scintilla/test/lexTests.py113
-rw-r--r--scintilla/test/performanceTests.py83
-rw-r--r--scintilla/test/simpleTests.py1309
-rw-r--r--scintilla/test/xite.py6
-rw-r--r--scintilla/tgzsrc4
-rw-r--r--scintilla/vcbuild/SciLexer.dsp549
-rw-r--r--scintilla/version.txt1
-rw-r--r--scintilla/win32/Margin.curbin0 -> 326 bytes
-rw-r--r--scintilla/win32/PlatWin.cxx2293
-rw-r--r--scintilla/win32/PlatformRes.h8
-rw-r--r--scintilla/win32/SciTE.properties21
-rw-r--r--scintilla/win32/ScintRes.rc40
-rw-r--r--scintilla/win32/Scintilla.def2
-rw-r--r--scintilla/win32/ScintillaWin.cxx2722
-rw-r--r--scintilla/win32/deps.mak282
-rw-r--r--scintilla/win32/makefile108
-rw-r--r--scintilla/win32/scintilla.mak553
-rw-r--r--scintilla/win32/scintilla_vc6.mak555
-rw-r--r--scintilla/zipsrc.bat4
280 files changed, 115972 insertions, 0 deletions
diff --git a/scintilla/License.txt b/scintilla/License.txt
new file mode 100644
index 0000000..8d28612
--- /dev/null
+++ b/scintilla/License.txt
@@ -0,0 +1,20 @@
+License for Scintilla and SciTE
+
+Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation.
+
+NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file
diff --git a/scintilla/README b/scintilla/README
new file mode 100644
index 0000000..7ab2146
--- /dev/null
+++ b/scintilla/README
@@ -0,0 +1,74 @@
+README for building of Scintilla and SciTE
+
+Scintilla can be built by itself.
+To build SciTE, Scintilla must first be built.
+
+
+*** GTK+/Linux version ***
+
+You must first have GTK+ 2.0 or later and GCC (4.1 or better) installed.
+GTK+ 1.x will not work.
+Other C++ compilers may work but may require tweaking the make file.
+
+To build Scintilla, use the makefile located in the scintilla/gtk directory
+ cd scintilla/gtk
+ make
+ cd ../..
+
+To build and install SciTE, use the makefile located in the scite/gtk directory
+ cd scite/gtk
+ make
+ make install
+
+This installs SciTE into $prefix/bin. The value of $prefix is determined from
+the location of Gnome if it is installed. This is usually /usr if installed
+with Linux or /usr/local if built from source. If Gnome is not installed
+/usr/bin is used as the prefix. The prefix can be overridden on the command
+line like "make prefix=/opt" but the same value should be used for both make
+and make install as this location is compiled into the executable. The global
+properties file is installed at $prefix/share/scite/SciTEGlobal.properties.
+The language specific properties files are also installed into this directory.
+
+To remove SciTE
+ make uninstall
+
+To clean the object files which may be needed to change $prefix
+ make clean
+
+The current make file only supports static linking between SciTE and Scintilla.
+
+
+*** Windows version ***
+
+A C++ compiler is required. Visual Studio .NET 2008 is the development system
+used for most development although TDM Mingw32 4.4.1 is also supported.
+For older versions of Borland C++ such as version 5.02, add the -l option.
+
+To build Scintilla, make in the scintilla/win32 directory
+ cd scintilla\win32
+GCC: mingw32-make
+VS .NET: nmake -f scintilla.mak
+VC++ 6: nmake -f scintilla_vc6.mak
+Borland: make -fscintilla.mak
+ cd ..\..
+
+To build SciTE, use the makefiles located in the scite/win32 directory
+ cd scite\win32
+GCC: mingw32-make
+VS .NET: nmake -f scite.mak
+Borland: make -fscite.mak
+
+An executable SciTE will now be in scite\bin.
+
+The Visual C++ 6.0 project (.dsp) files are no longer supported but are left
+in the download for people that are prepared to update them.
+
+*** GTK+/Windows version ***
+
+Mingw32 is known to work. Other compilers will probably not work.
+
+Only Scintilla will build with GTK+ on Windows. SciTE will not work.
+
+To build Scintilla, make in the scintilla/gtk directory
+ cd scintilla\gtk
+ mingw32-make
diff --git a/scintilla/bin/empty.txt b/scintilla/bin/empty.txt
new file mode 100644
index 0000000..6618385
--- /dev/null
+++ b/scintilla/bin/empty.txt
@@ -0,0 +1 @@
+This empty files ensures that the directory is created. \ No newline at end of file
diff --git a/scintilla/cocoa/Framework.mk b/scintilla/cocoa/Framework.mk
new file mode 100644
index 0000000..88358ac
--- /dev/null
+++ b/scintilla/cocoa/Framework.mk
@@ -0,0 +1,85 @@
+### start defines ###
+
+ARCH=-arch i386
+CC=gcc -x c++ $(ARCH)
+CO=gcc -x objective-c++ $(ARCH)
+
+INST_NAME=-install_name @executable_path/../Frameworks/Sci.framework/Versions/A/Sci
+LD=gcc $(ARCH) -dynamiclib -framework Cocoa $(INST_NAME)
+
+gDEFs=-DSCI_NAMESPACE -DSCI_LEXER
+
+INCS=-I../src/ -I../include/ -I.
+CCX=$(CC) $(gDEFs) $(INCS)
+CCO=$(CO) $(gDEFs) $(INCS)
+
+BLD=build/framebuild
+
+SCI_LEXERS=LexAPDL.o LexASY.o LexAU3.o LexAVE.o LexAbaqus.o LexAda.o LexAsm.o LexAsn1.o \
+ LexBaan.o LexBash.o LexBasic.o LexBullant.o LexCLW.o LexCOBOL.o LexCPP.o LexCSS.o \
+ LexCaml.o LexCmake.o LexConf.o LexCrontab.o LexCsound.o LexD.o LexEScript.o LexEiffel.o \
+ LexErlang.o LexFlagship.o LexForth.o LexFortran.o LexGAP.o LexGui4Cli.o LexHTML.o \
+ LexHaskell.o LexInno.o LexKix.o LexLisp.o LexLout.o LexLua.o LexMMIXAL.o LexMPT.o \
+ LexMSSQL.o LexMagik.o LexMarkdown.o LexMatlab.o LexMetapost.o LexMySQL.o LexNimrod.o \
+ LexNsis.o LexOpal.o LexOthers.o LexPB.o LexPLM.o LexPOV.o LexPS.o LexPascal.o LexPerl.o \
+ LexPowerPro.o LexPowerShell.o LexProgress.o LexPython.o LexR.o LexRebol.o LexRuby.o \
+ LexSML.o LexSQL.o LexScriptol.o LexSmalltalk.o LexSorcus.o LexSpecman.o LexSpice.o \
+ LexTACL.o LexTADS3.o LexTAL.o LexTCL.o LexTeX.o LexVB.o LexVHDL.o LexVerilog.o LexYAML.o
+
+SCI_OBJ=AutoComplete.o CallTip.o CellBuffer.o CharClassify.o ContractionState.o Decoration.o \
+ Document.o DocumentAccessor.o Editor.o ExternalLexer.o Indicator.o KeyMap.o KeyWords.o \
+ LineMarker.o PerLine.o PositionCache.o PropSet.o RESearch.o RunStyles.o ScintillaBase.o \
+ Style.o StyleContext.o UniConversion.o ViewStyle.o WindowAccessor.o XPM.o Selection.o $(SCI_LEXERS)
+COC_OBJ=PlatCocoa.o ScintillaCocoa.o ScintillaView.o InfoBar.o
+
+OBJ=$(SCI_OBJ) $(COC_OBJ)
+OBJS=$(addprefix $(BLD)/,$(OBJ))
+
+TARG=$(APP)/Versions/A/Sci
+APP=$(BLD)/Sci.framework
+### end defines ###
+
+### start targets ###
+
+all: $(BLD) $(TARG)
+
+$(APP): $(BLD)
+ -rm -rf $(APP)
+ -mkdir $(APP)
+ -mkdir $(APP)/Versions
+ -mkdir $(APP)/Versions/A
+ -mkdir $(APP)/Versions/A/Headers
+ -mkdir $(APP)/Versions/A/Resources
+ -ln -sf `pwd`/$(APP)/Versions/A `pwd`/$(APP)/Versions/Current
+ -ln -sf `pwd`/$(APP)/Versions/A/Headers `pwd`/$(APP)/Headers
+ -ln -sf `pwd`/$(APP)/Versions/A/Resources `pwd`/$(APP)/Resources
+ -cp *.h $(APP)/Headers/
+ -cp ../src/*.h $(APP)/Headers/
+ -cp ../include/*.h $(APP)/Headers/
+ -cp -R ScintillaFramework/English.lproj $(APP)/Resources
+ -cp res/*.png $(APP)/Resources
+ -cp ScintillaFramework/Info.plist $(APP)/Resources
+
+$(TARG) : $(OBJS) $(APP)
+ $(LD) $(OBJS) $(gDEFs) -o $(TARG) -lstdc++
+ -ln `pwd`/$(TARG) `pwd`/$(APP)/Sci
+
+$(BLD):
+ -mkdir build
+ -mkdir $(BLD)
+
+clean:
+ -rm -rf $(BLD)
+
+$(BLD)/%.o : ../src/%.cxx
+ $(CCX) -c ../src/$< -o $@
+
+$(BLD)/%.o : %.mm
+ $(CCO) -c $< -o $@
+
+### get around to filling out the real dependencies later ###
+$(BLD)/AutoComplete.o : ../src/AutoComplete.cxx ../src/AutoComplete.h ../include/Platform.h
+
+$(BLD)/CallTip.o : ../src/CallTip.cxx ../src/CallTip.h ../include/Platform.h
+
+### end targets ### \ No newline at end of file
diff --git a/scintilla/cocoa/InfoBar.h b/scintilla/cocoa/InfoBar.h
new file mode 100644
index 0000000..9624811
--- /dev/null
+++ b/scintilla/cocoa/InfoBar.h
@@ -0,0 +1,55 @@
+
+/**
+ * Scintilla source code edit control
+ * InfoBar.h - Implements special info bar with zoom info, caret position etc. to be used with
+ * ScintillaView.
+ *
+ * Mike Lischke <mlischke@sun.com>
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "InfoBarCommunicator.h"
+
+/**
+ * Extended text cell for vertically aligned text.
+ */
+@interface VerticallyCenteredTextFieldCell : NSTextFieldCell
+{
+ BOOL mIsEditingOrSelecting;
+}
+
+@end
+
+@interface InfoBar : NSView <InfoBarCommunicator>
+{
+@private
+ NSImage* mBackground;
+ IBDisplay mDisplayMask;
+
+ float mScaleFactor;
+ NSPopUpButton* mZoomPopup;
+
+ int mCurrentCaretX;
+ int mCurrentCaretY;
+ NSTextField* mCaretPositionLabel;
+ NSTextField* mStatusTextLabel;
+
+ id <InfoBarCommunicator> mCallback;
+}
+
+- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
+ value: (float) value;
+- (void) setCallback: (id <InfoBarCommunicator>) callback;
+
+- (void) createItems;
+- (void) layout;
+- (void) setDisplay: (IBDisplay) display;
+- (void) zoomItemAction: (id) sender;
+- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag;
+- (void) setCaretPosition: (NSPoint) position;
+- (void) sizeToFit;
+
+@end
diff --git a/scintilla/cocoa/InfoBar.mm b/scintilla/cocoa/InfoBar.mm
new file mode 100644
index 0000000..27b9aa1
--- /dev/null
+++ b/scintilla/cocoa/InfoBar.mm
@@ -0,0 +1,448 @@
+
+/**
+ * Scintilla source code edit control
+ * InfoBar.mm - Implements special info bar with zoom info, caret position etc. to be used with
+ * ScintillaView.
+ *
+ * Mike Lischke <mlischke@sun.com>
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import "InfoBar.h"
+
+//--------------------------------------------------------------------------------------------------
+
+@implementation VerticallyCenteredTextFieldCell
+
+// Inspired by code from Daniel Jalkut, Red Sweater Software.
+
+- (NSRect) drawingRectForBounds: (NSRect) theRect
+{
+ // Get the parent's idea of where we should draw
+ NSRect newRect = [super drawingRectForBounds: theRect];
+
+ // When the text field is being edited or selected, we have to turn off the magic because it
+ // screws up the configuration of the field editor. We sneak around this by intercepting
+ // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute.
+ if (mIsEditingOrSelecting == NO)
+ {
+ // Get our ideal size for current text
+ NSSize textSize = [self cellSizeForBounds: theRect];
+
+ // Center that in the proposed rect
+ float heightDelta = newRect.size.height - textSize.height;
+ if (heightDelta > 0)
+ {
+ newRect.size.height -= heightDelta;
+ newRect.origin.y += ceil(heightDelta / 2);
+ }
+ }
+
+ return newRect;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) selectWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj
+ delegate:(id) anObject start: (int) selStart length: (int) selLength
+{
+ aRect = [self drawingRectForBounds: aRect];
+ mIsEditingOrSelecting = YES;
+ [super selectWithFrame: aRect
+ inView: controlView
+ editor: textObj
+ delegate: anObject
+ start: selStart
+ length: selLength];
+ mIsEditingOrSelecting = NO;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) editWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj
+ delegate: (id) anObject event: (NSEvent*) theEvent
+{
+ aRect = [self drawingRectForBounds: aRect];
+ mIsEditingOrSelecting = YES;
+ [super editWithFrame: aRect
+ inView: controlView
+ editor: textObj
+ delegate: anObject
+ event: theEvent];
+ mIsEditingOrSelecting = NO;
+}
+
+@end
+
+//--------------------------------------------------------------------------------------------------
+
+@implementation InfoBar
+
+- (id) initWithFrame: (NSRect) frame
+{
+ self = [super initWithFrame: frame];
+ if (self)
+ {
+ NSBundle* bundle = [NSBundle bundleForClass: [InfoBar class]];
+
+ NSString* path = [bundle pathForResource: @"info_bar_bg" ofType: @"png" inDirectory: nil];
+ mBackground = [[[NSImage alloc] initWithContentsOfFile: path] retain];
+ if (![mBackground isValid])
+ NSLog(@"Background image for info bar is invalid.");
+
+ mScaleFactor = 1.0;
+ mCurrentCaretX = 0;
+ mCurrentCaretY = 0;
+ [self createItems];
+ }
+ return self;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by a connected compontent (usually the info bar) if something changed there.
+ *
+ * @param type The type of the notification.
+ * @param message Carries the new status message if the type is a status message change.
+ * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type.
+ * @param location Carries the new zoom value if the type is a zoom change.
+ */
+- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
+ value: (float) value
+{
+ switch (type)
+ {
+ case IBNZoomChanged:
+ [self setScaleFactor: value adjustPopup: YES];
+ break;
+ case IBNCaretChanged:
+ [self setCaretPosition: location];
+ break;
+ case IBNStatusChanged:
+ [mStatusTextLabel setStringValue: message];
+ break;
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to set a protocol object we can use to send change notifications to.
+ */
+- (void) setCallback: (id <InfoBarCommunicator>) callback
+{
+ mCallback = callback;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+static NSString *DefaultScaleMenuLabels[] = {
+ @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%"
+};
+static float DefaultScaleMenuFactors[] = {
+ 0.2, 0.3, 0.5, 0.75, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0
+};
+static unsigned DefaultScaleMenuSelectedItemIndex = 4;
+static float BarFontSize = 10.0;
+
+- (void) createItems
+{
+ // 1) The zoom popup.
+ unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *);
+
+ // Create the popup button.
+ mZoomPopup = [[NSPopUpButton allocWithZone:[self zone]] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO];
+
+ // No border or background please.
+ [[mZoomPopup cell] setBordered: NO];
+ [[mZoomPopup cell] setArrowPosition: NSPopUpArrowAtBottom];
+
+ // Fill it.
+ for (unsigned count = 0; count < numberOfDefaultItems; count++)
+ {
+ [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)];
+ id currentItem = [mZoomPopup itemAtIndex: count];
+ if (DefaultScaleMenuFactors[count] != 0.0)
+ [currentItem setRepresentedObject: [NSNumber numberWithFloat: DefaultScaleMenuFactors[count]]];
+ }
+ [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex];
+
+ // Hook it up.
+ [mZoomPopup setTarget: self];
+ [mZoomPopup setAction: @selector(zoomItemAction:)];
+
+ // Set a suitable font.
+ [mZoomPopup setFont: [NSFont menuBarFontOfSize: BarFontSize]];
+
+ // Make sure the popup is big enough to fit the cells.
+ [mZoomPopup sizeToFit];
+
+ // Don't let it become first responder
+ [mZoomPopup setRefusesFirstResponder: YES];
+
+ // put it in the scrollview.
+ [self addSubview: mZoomPopup];
+ [mZoomPopup release];
+
+ // 2) The caret position label.
+ Class oldCellClass = [NSTextField cellClass];
+ [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]];
+
+ mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)];
+ [mCaretPositionLabel setBezeled: NO];
+ [mCaretPositionLabel setBordered: NO];
+ [mCaretPositionLabel setEditable: NO];
+ [mCaretPositionLabel setSelectable: NO];
+ [mCaretPositionLabel setDrawsBackground: NO];
+ [mCaretPositionLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]];
+
+ NSTextFieldCell* cell = [mCaretPositionLabel cell];
+ [cell setPlaceholderString: @"0:0"];
+ [cell setAlignment: NSCenterTextAlignment];
+
+ [self addSubview: mCaretPositionLabel];
+ [mCaretPositionLabel release];
+
+ // 3) The status text.
+ mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)];
+ [mStatusTextLabel setBezeled: NO];
+ [mStatusTextLabel setBordered: NO];
+ [mStatusTextLabel setEditable: NO];
+ [mStatusTextLabel setSelectable: NO];
+ [mStatusTextLabel setDrawsBackground: NO];
+ [mStatusTextLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]];
+
+ cell = [mStatusTextLabel cell];
+ [cell setPlaceholderString: @""];
+
+ [self addSubview: mStatusTextLabel];
+ [mStatusTextLabel release];
+
+ // Restore original cell class so that everything else doesn't get broken
+ [NSTextField setCellClass: oldCellClass];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) dealloc
+{
+ [mBackground release];
+ [super dealloc];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Fill the background.
+ */
+- (void) drawRect: (NSRect) rect
+{
+ // Since the background is seamless, we don't need to take care for the proper offset.
+ // Simply tile the background over the invalid rectangle.
+ NSPoint target = {rect.origin.x, 0};
+ while (target.x < rect.origin.x + rect.size.width)
+ {
+ [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1];
+ target.x += mBackground.size.width;
+ }
+
+ // Draw separator lines between items.
+ NSRect verticalLineRect;
+ float component = 190.0 / 255.0;
+ NSColor* lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1];
+
+ if (mDisplayMask & IBShowZoom)
+ {
+ verticalLineRect = [mZoomPopup frame];
+ verticalLineRect.origin.x += verticalLineRect.size.width + 1.0;
+ verticalLineRect.size.width = 1.0;
+ if (NSIntersectsRect(rect, verticalLineRect))
+ {
+ [lineColor set];
+ NSRectFill(verticalLineRect);
+ }
+ }
+
+ if (mDisplayMask & IBShowCaretPosition)
+ {
+ verticalLineRect = [mCaretPositionLabel frame];
+ verticalLineRect.origin.x += verticalLineRect.size.width + 1.0;
+ verticalLineRect.size.width = 1.0;
+ if (NSIntersectsRect(rect, verticalLineRect))
+ {
+ [lineColor set];
+ NSRectFill(verticalLineRect);
+ }
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) isOpaque
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to reposition our content depending on the size of the view.
+ */
+- (void) setFrame: (NSRect) newFrame
+{
+ [super setFrame: newFrame];
+ [self layout];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) layout
+{
+ NSRect currentBounds = {0, 0, 0, [self frame].size.height};
+ if (mDisplayMask & IBShowZoom)
+ {
+ [mZoomPopup setHidden: NO];
+ currentBounds.size.width = [mZoomPopup frame].size.width;
+ [mZoomPopup setFrame: currentBounds];
+ currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator.
+ }
+ else
+ [mZoomPopup setHidden: YES];
+
+ if (mDisplayMask & IBShowCaretPosition)
+ {
+ [mCaretPositionLabel setHidden: NO];
+ currentBounds.size.width = [mCaretPositionLabel frame].size.width;
+ [mCaretPositionLabel setFrame: currentBounds];
+ currentBounds.origin.x += currentBounds.size.width + 1;
+ }
+ else
+ [mCaretPositionLabel setHidden: YES];
+
+ if (mDisplayMask & IBShowStatusText)
+ {
+ // The status text always takes the rest of the available space.
+ [mStatusTextLabel setHidden: NO];
+ currentBounds.size.width = [self frame].size.width - currentBounds.origin.x;
+ [mStatusTextLabel setFrame: currentBounds];
+ }
+ else
+ [mStatusTextLabel setHidden: YES];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to switch the visible parts of the info bar.
+ *
+ * @param display Bitwise ORed IBDisplay values which determine what to show on the bar.
+ */
+- (void) setDisplay: (IBDisplay) display
+{
+ if (mDisplayMask != display)
+ {
+ mDisplayMask = display;
+ [self layout];
+ [self needsDisplay];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Handler for selection changes in the zoom menu.
+ */
+- (void) zoomItemAction: (id) sender
+{
+ NSNumber* selectedFactorObject = [[sender selectedCell] representedObject];
+
+ if (selectedFactorObject == nil)
+ {
+ NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported.");
+ return;
+ }
+ else
+ {
+ [self setScaleFactor: [selectedFactorObject floatValue] adjustPopup: NO];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag
+{
+ if (mScaleFactor != newScaleFactor)
+ {
+ mScaleFactor = newScaleFactor;
+ if (flag)
+ {
+ unsigned count = 0;
+ unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float);
+
+ // We only work with some preset zoom values. If the given value does not correspond
+ // to one then show no selection.
+ while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07))
+ count++;
+ if (count == numberOfDefaultItems)
+ [mZoomPopup selectItemAtIndex: -1];
+ else
+ {
+ [mZoomPopup selectItemAtIndex: count];
+
+ // Set scale factor to found preset value if it comes close.
+ mScaleFactor = DefaultScaleMenuFactors[count];
+ }
+ }
+ else
+ {
+ // Internally set. Notify owner.
+ [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor];
+ }
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called from the notification method to update the caret position display.
+ */
+- (void) setCaretPosition: (NSPoint) position
+{
+ // Make the position one-based.
+ int newX = (int) position.x + 1;
+ int newY = (int) position.y + 1;
+
+ if (mCurrentCaretX != newX || mCurrentCaretY != newY)
+ {
+ mCurrentCaretX = newX;
+ mCurrentCaretY = newY;
+
+ [mCaretPositionLabel setStringValue: [NSString stringWithFormat: @"%d:%d", newX, newY]];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Makes the bar resize to the smallest width that can accomodate the currently enabled items.
+ */
+- (void) sizeToFit
+{
+ NSRect frame = [self frame];
+ frame.size.width = 0;
+ if (mDisplayMask & IBShowZoom)
+ frame.size.width += [mZoomPopup frame].size.width;
+
+ if (mDisplayMask & IBShowCaretPosition)
+ frame.size.width += [mCaretPositionLabel frame].size.width;
+
+ if (mDisplayMask & IBShowStatusText)
+ frame.size.width += [mStatusTextLabel frame].size.width;
+
+ [self setFrame: frame];
+}
+
+@end
diff --git a/scintilla/cocoa/InfoBarCommunicator.h b/scintilla/cocoa/InfoBarCommunicator.h
new file mode 100644
index 0000000..ba8ae7a
--- /dev/null
+++ b/scintilla/cocoa/InfoBarCommunicator.h
@@ -0,0 +1,35 @@
+/*
+ * InfoBarCommunicator.h - Definitions of a communication protocol and other data types used for
+ * the info bar implementation.
+ *
+ * Mike Lischke <mlischke@sun.com>
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+enum IBDisplay {
+ IBShowZoom = 0x01,
+ IBShowCaretPosition = 0x02,
+ IBShowStatusText = 0x04,
+ IBShowAll = 0xFF
+};
+
+/**
+ * The info bar communicator protocol is used for communication between ScintillaView and its
+ * information bar component. Using this protocol decouples any potential info target from the main
+ * ScintillaView implementation. The protocol is used two-way.
+ */
+
+enum NotificationType {
+ IBNZoomChanged, // The user selected another zoom value.
+ IBNCaretChanged, // The caret in the editor changed.
+ IBNStatusChanged, // The application set a new status message.
+};
+
+@protocol InfoBarCommunicator
+- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
+ value: (float) value;
+- (void) setCallback: (id <InfoBarCommunicator>) callback;
+@end
+
diff --git a/scintilla/cocoa/PlatCocoa.h b/scintilla/cocoa/PlatCocoa.h
new file mode 100644
index 0000000..a85462e
--- /dev/null
+++ b/scintilla/cocoa/PlatCocoa.h
@@ -0,0 +1,119 @@
+
+/**
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#ifndef PLATCOCOA_H
+#define PLATCOCOA_H
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+
+#include <assert.h>
+
+#include <sys/time.h>
+
+#include <Cocoa/Cocoa.h>
+#include "QuartzTextLayout.h"
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+NSRect PRectangleToNSRect(Scintilla::PRectangle& rc);
+Scintilla::PRectangle NSRectToPRectangle(NSRect& rc);
+
+@interface ScintillaContextMenu : NSMenu
+{
+ Scintilla::ScintillaCocoa* owner;
+}
+- (void) handleCommand: (NSMenuItem*) sender;
+- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner;
+
+@end
+
+namespace Scintilla {
+
+// A class to do the actual text rendering for us using Quartz 2D.
+class SurfaceImpl : public Surface
+{
+private:
+ bool unicodeMode;
+ float x;
+ float y;
+
+ CGContextRef gc;
+
+ /** The text layout instance */
+ QuartzTextLayout* textLayout;
+ /** If the surface is a bitmap context, contains a reference to the bitmap data. */
+ uint8_t* bitmapData;
+ /** If the surface is a bitmap context, stores the dimensions of the bitmap. */
+ int bitmapWidth;
+ int bitmapHeight;
+
+ /** Set the CGContext's fill colour to the specified allocated colour. */
+ void FillColour( const ColourAllocated& back );
+
+
+ // 24-bit RGB+A bitmap data constants
+ static const int BITS_PER_COMPONENT = 8;
+ static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4;
+ static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8;
+public:
+ SurfaceImpl();
+ ~SurfaceImpl();
+
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+ CGContextRef GetContext() { return gc; }
+
+ void Release();
+ bool Initialised();
+ void PenColour(ColourAllocated fore);
+
+ /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */
+ CGImageRef GetImage();
+ void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect);
+
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource);
+ void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore,
+ ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore,
+ ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, int *positions);
+ int WidthText(Font &font_, const char *s, int len);
+ int WidthChar(Font &font_, char ch);
+ int Ascent(Font &font_);
+ int Descent(Font &font_);
+ int InternalLeading(Font &font_);
+ int ExternalLeading(Font &font_);
+ int Height(Font &font_);
+ int AverageCharWidth(Font &font_);
+
+ int SetPalette(Scintilla::Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage);
+}; // SurfaceImpl class
+
+} // Scintilla namespace
+
+#endif
diff --git a/scintilla/cocoa/PlatCocoa.mm b/scintilla/cocoa/PlatCocoa.mm
new file mode 100644
index 0000000..09591c2
--- /dev/null
+++ b/scintilla/cocoa/PlatCocoa.mm
@@ -0,0 +1,2124 @@
+/**
+ * Scintilla source code edit control
+ * PlatCocoa.mm - implementation of platform facilities on MacOS X/Cocoa
+ *
+ * Written by Mike Lischke
+ * Based on PlatMacOSX.cxx
+ * Based on work by Evan Jones (c) 2002 <ejones@uwaterloo.ca>
+ * Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+ * The License.txt file describes the conditions under which this software may be distributed.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <ScintillaView.h>
+
+#include "PlatCocoa.h"
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <assert.h>
+#include <sys/time.h>
+#include <stdexcept>
+
+#include "XPM.h"
+
+#import <Foundation/NSGeometry.h>
+
+#import <Carbon/Carbon.h> // Temporary
+
+using namespace Scintilla;
+
+extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts a PRectangle as used by Scintilla to standard Obj-C NSRect structure .
+ */
+NSRect PRectangleToNSRect(PRectangle& rc)
+{
+ return NSMakeRect(rc.left, rc.top, rc.Width(), rc.Height());
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts an NSRect as used by the system to a native Scintilla rectangle.
+ */
+PRectangle NSRectToPRectangle(NSRect& rc)
+{
+ return PRectangle(rc.origin.x, rc.origin.y, rc.size.width + rc.origin.x, rc.size.height + rc.origin.y);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts a PRctangle as used by Scintilla to a Quartz-style rectangle.
+ */
+inline CGRect PRectangleToCGRect(PRectangle& rc)
+{
+ return CGRectMake(rc.left, rc.top, rc.Width(), rc.Height());
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts a Quartz-style rectangle to a PRectangle structure as used by Scintilla.
+ */
+inline PRectangle CGRectToPRectangle(const CGRect& rect)
+{
+ PRectangle rc;
+ rc.left = (int)(rect.origin.x + 0.5);
+ rc.top = (int)(rect.origin.y + 0.5);
+ rc.right = (int)(rect.origin.x + rect.size.width + 0.5);
+ rc.bottom = (int)(rect.origin.y + rect.size.height + 0.5);
+ return rc;
+}
+
+//----------------- Point --------------------------------------------------------------------------
+
+/**
+ * Converts a point given as a long into a native Point structure.
+ */
+Scintilla::Point Scintilla::Point::FromLong(long lpoint)
+{
+ return Scintilla::Point(
+ Platform::LowShortFromLong(lpoint),
+ Platform::HighShortFromLong(lpoint)
+ );
+}
+
+//----------------- Palette ------------------------------------------------------------------------
+
+// The Palette implementation is only here because we would get linker errors if not.
+// We don't use indexed colors in ScintillaCocoa.
+
+Scintilla::Palette::Palette()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+Scintilla::Palette::~Palette()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Scintilla::Palette::Release()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to transform a given color, if needed. If the caller tries to find a color that matches the
+ * desired color then we simply pass it on, as we support the full color space.
+ */
+void Scintilla::Palette::WantFind(ColourPair &cp, bool want)
+{
+ if (!want)
+ cp.allocated.Set(cp.desired.AsLong());
+
+ // Don't do anything if the caller wants the color it has already set.
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Scintilla::Palette::Allocate(Window& w)
+{
+ // Nothing to allocate as we don't use palettes.
+}
+
+//----------------- Font ---------------------------------------------------------------------------
+
+Font::Font(): fid(0)
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+Font::~Font()
+{
+ Release();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Creates a Quartz 2D font with the given properties.
+ * TODO: rewrite to use NSFont.
+ */
+void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic,
+ int extraFontFlag)
+{
+ // TODO: How should I handle the characterSet request?
+ Release();
+
+ QuartzTextStyle* style = new QuartzTextStyle();
+ fid = style;
+
+ // Find the font
+ QuartzFont font(faceName, strlen(faceName));
+
+ // We set Font, Size, Bold, Italic
+ QuartzTextSize textSize(size);
+ QuartzTextBold isBold(bold);
+ QuartzTextItalic isItalic(italic);
+
+ // Actually set the attributes
+ QuartzTextStyleAttribute* attributes[] = { &font, &textSize, &isBold, &isItalic };
+ style->setAttributes(attributes, sizeof(attributes) / sizeof(*attributes));
+ style->setFontFeature(kLigaturesType, kCommonLigaturesOffSelector);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Font::Release()
+{
+ if (fid)
+ delete reinterpret_cast<QuartzTextStyle*>( fid );
+ fid = 0;
+}
+
+//----------------- SurfaceImpl --------------------------------------------------------------------
+
+SurfaceImpl::SurfaceImpl()
+{
+ bitmapData = NULL; // Release will try and delete bitmapData if != NULL
+ gc = NULL;
+ textLayout = new QuartzTextLayout(NULL);
+ Release();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+SurfaceImpl::~SurfaceImpl()
+{
+ Release();
+ delete textLayout;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::Release()
+{
+ textLayout->setContext (NULL);
+ if ( bitmapData != NULL )
+ {
+ delete[] bitmapData;
+ // We only "own" the graphics context if we are a bitmap context
+ if (gc != NULL)
+ CGContextRelease(gc);
+ }
+ bitmapData = NULL;
+ gc = NULL;
+
+ bitmapWidth = 0;
+ bitmapHeight = 0;
+ x = 0;
+ y = 0;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool SurfaceImpl::Initialised()
+{
+ // We are initalised if the graphics context is not null
+ return gc != NULL;// || port != NULL;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::Init(WindowID wid)
+{
+ // To be able to draw, the surface must get a CGContext handle. We save the graphics port,
+ // then aquire/release the context on an as-need basis (see above).
+ // XXX Docs on QDBeginCGContext are light, a better way to do this would be good.
+ // AFAIK we should not hold onto a context retrieved this way, thus the need for
+ // aquire/release of the context.
+
+ Release();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::Init(SurfaceID sid, WindowID wid)
+{
+ Release();
+ gc = reinterpret_cast<CGContextRef>(sid);
+ CGContextSetLineWidth(gc, 1.0);
+ textLayout->setContext(gc);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::InitPixMap(int width, int height, Surface* surface_, WindowID wid)
+{
+ Release();
+
+ // Create a new bitmap context, along with the RAM for the bitmap itself
+ bitmapWidth = width;
+ bitmapHeight = height;
+
+ const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL);
+ const int bitmapByteCount = (bitmapBytesPerRow * height);
+
+ // Create an RGB color space.
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ if (colorSpace == NULL)
+ return;
+
+ // Create the bitmap.
+ bitmapData = new uint8_t[bitmapByteCount];
+ if (bitmapData != NULL)
+ {
+ // create the context
+ gc = CGBitmapContextCreate(bitmapData,
+ width,
+ height,
+ BITS_PER_COMPONENT,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast);
+
+ if (gc == NULL)
+ {
+ // the context couldn't be created for some reason,
+ // and we have no use for the bitmap without the context
+ delete[] bitmapData;
+ bitmapData = NULL;
+ }
+ textLayout->setContext (gc);
+ }
+
+ // the context retains the color space, so we can release it
+ CGColorSpaceRelease(colorSpace);
+
+ if (gc != NULL && bitmapData != NULL)
+ {
+ // "Erase" to white.
+ CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) );
+ CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 );
+ CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) );
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::PenColour(ColourAllocated fore)
+{
+ if (gc)
+ {
+ ColourDesired colour(fore.AsLong());
+
+ // Set the Stroke color to match
+ CGContextSetRGBStrokeColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0,
+ colour.GetBlue() / 255.0, 1.0 );
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::FillColour(const ColourAllocated& back)
+{
+ if (gc)
+ {
+ ColourDesired colour(back.AsLong());
+
+ // Set the Fill color to match
+ CGContextSetRGBFillColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0,
+ colour.GetBlue() / 255.0, 1.0 );
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+CGImageRef SurfaceImpl::GetImage()
+{
+ // For now, assume that GetImage can only be called on PixMap surfaces.
+ if (bitmapData == NULL)
+ return NULL;
+
+ CGContextFlush(gc);
+
+ // Create an RGB color space.
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ if( colorSpace == NULL )
+ return NULL;
+
+ const int bitmapBytesPerRow = ((int) bitmapWidth * BYTES_PER_PIXEL);
+ const int bitmapByteCount = (bitmapBytesPerRow * (int) bitmapHeight);
+
+ // Create a data provider.
+ CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, bitmapData, bitmapByteCount,
+ NULL);
+ CGImageRef image = NULL;
+ if (dataProvider != NULL)
+ {
+ // Create the CGImage.
+ image = CGImageCreate(bitmapWidth,
+ bitmapHeight,
+ BITS_PER_COMPONENT,
+ BITS_PER_PIXEL,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast,
+ dataProvider,
+ NULL,
+ 0,
+ kCGRenderingIntentDefault);
+ }
+
+ // The image retains the color space, so we can release it.
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+
+ // Done with the data provider.
+ CGDataProviderRelease(dataProvider);
+ dataProvider = NULL;
+
+ return image;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Returns the vertical logical device resolution of the main monitor.
+ */
+int SurfaceImpl::LogPixelsY()
+{
+ NSSize deviceResolution = [[[[NSScreen mainScreen] deviceDescription]
+ objectForKey: NSDeviceResolution] sizeValue];
+ return (int) deviceResolution.height;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts the logical font height (in dpi) into a pixel height for the current main screen.
+ */
+int SurfaceImpl::DeviceHeightFont(int points)
+{
+ int logPix = LogPixelsY();
+ return (points * logPix + logPix / 2) / 72;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::MoveTo(int x_, int y_)
+{
+ x = x_;
+ y = y_;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::LineTo(int x_, int y_)
+{
+ CGContextBeginPath( gc );
+
+ // Because Quartz is based on floating point, lines are drawn with half their colour
+ // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel
+ // divison lines. If you specify exact pixel values, you get a line that
+ // is twice as thick but half as intense. To get pixel aligned rendering,
+ // we render the "middle" of the pixels by adding 0.5 to the coordinates.
+ CGContextMoveToPoint( gc, x + 0.5, y + 0.5 );
+ CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 );
+ CGContextStrokePath( gc );
+ x = x_;
+ y = y_;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore,
+ ColourAllocated back)
+{
+ // Allocate memory for the array of points.
+ CGPoint *points = new CGPoint[npts];
+
+ for (int i = 0;i < npts;i++)
+ {
+ // Quartz floating point issues: plot the MIDDLE of the pixels
+ points[i].x = pts[i].x + 0.5;
+ points[i].y = pts[i].y + 0.5;
+ }
+
+ CGContextBeginPath(gc);
+
+ // Set colours
+ FillColour(back);
+ PenColour(fore);
+
+ // Draw the polygon
+ CGContextAddLines(gc, points, npts);
+
+ // TODO: Should the path be automatically closed, or is that the caller's responsability?
+ // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only)
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+
+ // Deallocate memory.
+ delete points;
+ points = NULL;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back)
+{
+ if (gc)
+ {
+ CGContextBeginPath( gc );
+ FillColour(back);
+ PenColour(fore);
+
+ // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo)
+ // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined
+ // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom.
+ // TODO: Create some version of PRectangleToCGRect to do this conversion for us?
+ CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back)
+{
+ if (gc)
+ {
+ FillColour(back);
+ CGRect rect = PRectangleToCGRect(rc);
+ CGContextFillRect(gc, rect);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void drawImageRefCallback(CGImageRef pattern, CGContextRef gc)
+{
+ CGContextDrawImage(gc, CGRectMake(0, 0, CGImageGetWidth(pattern), CGImageGetHeight(pattern)), pattern);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern)
+{
+ SurfaceImpl& patternSurface = static_cast<SurfaceImpl &>(surfacePattern);
+
+ // For now, assume that copy can only be called on PixMap surfaces. Shows up black.
+ CGImageRef image = patternSurface.GetImage();
+ if (image == NULL)
+ {
+ FillRectangle(rc, ColourAllocated(0));
+ return;
+ }
+
+ const CGPatternCallbacks drawImageCallbacks = { 0,
+ reinterpret_cast<CGPatternDrawPatternCallback>(drawImageRefCallback), NULL };
+
+ CGPatternRef pattern = CGPatternCreate(image,
+ CGRectMake(0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight),
+ CGAffineTransformIdentity,
+ patternSurface.bitmapWidth,
+ patternSurface.bitmapHeight,
+ kCGPatternTilingNoDistortion,
+ true,
+ &drawImageCallbacks
+ );
+ if (pattern != NULL)
+ {
+ // Create a pattern color space
+ CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL );
+ if( colorSpace != NULL ) {
+
+ CGContextSaveGState( gc );
+ CGContextSetFillColorSpace( gc, colorSpace );
+
+ // Unlike the documentation, you MUST pass in a "components" parameter:
+ // For coloured patterns it is the alpha value.
+ const float alpha = 1.0;
+ CGContextSetFillPattern( gc, pattern, &alpha );
+ CGContextFillRect( gc, PRectangleToCGRect( rc ) );
+ CGContextRestoreGState( gc );
+ // Free the color space, the pattern and image
+ CGColorSpaceRelease( colorSpace );
+ } /* colorSpace != NULL */
+ colorSpace = NULL;
+ CGPatternRelease( pattern );
+ pattern = NULL;
+ CGImageRelease( image );
+ image = NULL;
+ } /* pattern != NULL */
+}
+
+void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ // TODO: Look at the Win32 API to determine what this is supposed to do:
+ // ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 );
+
+ // Create a rectangle with semicircles at the corners
+ const int MAX_RADIUS = 4;
+ int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 );
+ radius = Platform::Minimum( radius, rc.Width()/2 );
+
+ // Points go clockwise, starting from just below the top left
+ // Corners are kept together, so we can easily create arcs to connect them
+ CGPoint corners[4][3] =
+ {
+ {
+ { rc.left, rc.top + radius },
+ { rc.left, rc.top },
+ { rc.left + radius, rc.top },
+ },
+ {
+ { rc.right - radius - 1, rc.top },
+ { rc.right - 1, rc.top },
+ { rc.right - 1, rc.top + radius },
+ },
+ {
+ { rc.right - 1, rc.bottom - radius - 1 },
+ { rc.right - 1, rc.bottom - 1 },
+ { rc.right - radius - 1, rc.bottom - 1 },
+ },
+ {
+ { rc.left + radius, rc.bottom - 1 },
+ { rc.left, rc.bottom - 1 },
+ { rc.left, rc.bottom - radius - 1 },
+ },
+ };
+
+ // Align the points in the middle of the pixels
+ // TODO: Should I include these +0.5 in the array creation code above?
+ for( int i = 0; i < 4*3; ++ i )
+ {
+ CGPoint* c = (CGPoint*) corners;
+ c[i].x += 0.5;
+ c[i].y += 0.5;
+ }
+
+ PenColour( fore );
+ FillColour( back );
+
+ // Move to the last point to begin the path
+ CGContextBeginPath( gc );
+ CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y );
+
+ for ( int i = 0; i < 4; ++ i )
+ {
+ CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y );
+ CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius );
+ }
+
+ // Close the path to enclose it for stroking and for filling, then draw it
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+}
+
+void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourAllocated fill, int alphaFill,
+ ColourAllocated /*outline*/, int /*alphaOutline*/, int /*flags*/)
+{
+ if ( gc ) {
+ ColourDesired colour( fill.AsLong() );
+
+ // Set the Fill color to match
+ CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 100.0 );
+ CGRect rect = PRectangleToCGRect( rc );
+ CGContextFillRect( gc, rect );
+ }
+}
+
+void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ // Drawing an ellipse with bezier curves. Code modified from:
+ // http://www.codeguru.com/gdi/ellipse.shtml
+ // MAGICAL CONSTANT to map ellipse to beziers 2/3*(sqrt(2)-1)
+ const double EToBConst = 0.2761423749154;
+
+ CGSize offset = CGSizeMake((int)(rc.Width() * EToBConst), (int)(rc.Height() * EToBConst));
+ CGPoint centre = CGPointMake((rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2);
+
+ // The control point array
+ CGPoint cCtlPt[13];
+
+ // Assign values to all the control points
+ cCtlPt[0].x =
+ cCtlPt[1].x =
+ cCtlPt[11].x =
+ cCtlPt[12].x = rc.left + 0.5;
+ cCtlPt[5].x =
+ cCtlPt[6].x =
+ cCtlPt[7].x = rc.right - 0.5;
+ cCtlPt[2].x =
+ cCtlPt[10].x = centre.x - offset.width + 0.5;
+ cCtlPt[4].x =
+ cCtlPt[8].x = centre.x + offset.width + 0.5;
+ cCtlPt[3].x =
+ cCtlPt[9].x = centre.x + 0.5;
+
+ cCtlPt[2].y =
+ cCtlPt[3].y =
+ cCtlPt[4].y = rc.top + 0.5;
+ cCtlPt[8].y =
+ cCtlPt[9].y =
+ cCtlPt[10].y = rc.bottom - 0.5;
+ cCtlPt[7].y =
+ cCtlPt[11].y = centre.y + offset.height + 0.5;
+ cCtlPt[1].y =
+ cCtlPt[5].y = centre.y - offset.height + 0.5;
+ cCtlPt[0].y =
+ cCtlPt[12].y =
+ cCtlPt[6].y = centre.y + 0.5;
+
+ FillColour(back);
+ PenColour(fore);
+
+ CGContextBeginPath( gc );
+ CGContextMoveToPoint( gc, cCtlPt[0].x, cCtlPt[0].y );
+
+ for ( int i = 1; i < 13; i += 3 )
+ {
+ CGContextAddCurveToPoint( gc, cCtlPt[i].x, cCtlPt[i].y, cCtlPt[i+1].x, cCtlPt[i+1].y, cCtlPt[i+2].x, cCtlPt[i+2].y );
+ }
+
+ // Close the path to enclose it for stroking and for filling, then draw it
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+}
+
+void SurfaceImpl::CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect)
+{
+ SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
+ CGImageRef image = source.GetImage();
+
+ CGRect src = PRectangleToCGRect(srcRect);
+ CGRect dst = PRectangleToCGRect(dstRect);
+
+ /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */
+ float w = (float) CGImageGetWidth(image);
+ float h = (float) CGImageGetHeight(image);
+ CGRect drawRect = CGRectMake (0, 0, w, h);
+ if (!CGRectEqualToRect (src, dst))
+ {
+ float sx = CGRectGetWidth(dst) / CGRectGetWidth(src);
+ float sy = CGRectGetHeight(dst) / CGRectGetHeight(src);
+ float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx);
+ float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy);
+ drawRect = CGRectMake (dx, dy, w*sx, h*sy);
+ }
+ CGContextSaveGState (gc);
+ CGContextClipToRect (gc, dst);
+ CGContextDrawImage (gc, drawRect, image);
+ CGContextRestoreGState (gc);
+}
+
+void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) {
+ // Maybe we have to make the Surface two contexts:
+ // a bitmap context which we do all the drawing on, and then a "real" context
+ // which we copy the output to when we call "Synchronize". Ugh! Gross and slow!
+
+ // For now, assume that copy can only be called on PixMap surfaces
+ SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
+
+ // Get the CGImageRef
+ CGImageRef image = source.GetImage();
+ // If we could not get an image reference, fill the rectangle black
+ if ( image == NULL )
+ {
+ FillRectangle( rc, ColourAllocated( 0 ) );
+ return;
+ }
+
+ // Now draw the image on the surface
+
+ // Some fancy clipping work is required here: draw only inside of rc
+ CGContextSaveGState( gc );
+ CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
+
+ //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight );
+ CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image );
+
+ // Undo the clipping fun
+ CGContextRestoreGState( gc );
+
+ // Done with the image
+ CGImageRelease( image );
+ image = NULL;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back)
+{
+ FillRectangle(rc, back);
+ DrawTextTransparent(rc, font_, ybase, s, len, fore);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back)
+{
+ CGContextSaveGState(gc);
+ CGContextClipToRect(gc, PRectangleToCGRect(rc));
+ DrawTextNoClip(rc, font_, ybase, s, len, fore, back);
+ CGContextRestoreGState(gc);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore)
+{
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // The Quartz RGB fill color influences the ATSUI color
+ FillColour(fore);
+
+ // Draw text vertically flipped as OS X uses a coordinate system where +Y is upwards.
+ textLayout->draw(rc.left, ybase, true);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions)
+{
+ // sample at http://developer.apple.com/samplecode/ATSUICurveAccessDemo/listing1.html
+ // sample includes use of ATSUGetGlyphInfo which would be better for older
+ // OSX systems. We should expand to using that on older systems as well.
+ for (int i = 0; i < len; i++)
+ positions [i] = 0;
+
+ // We need the right X coords, so we have to append a char to get the left coord of thast extra char
+ char* buf = (char*) malloc (len+1);
+ if (!buf)
+ return;
+
+ memcpy (buf, s, len);
+ buf [len] = '.';
+
+ textLayout->setText (reinterpret_cast<const UInt8*>(buf), len+1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ ATSUGlyphInfoArray* theGlyphInfoArrayPtr;
+ ByteCount theArraySize;
+
+ // Get the GlyphInfoArray
+ ATSUTextLayout layout = textLayout->getLayout();
+ if ( noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, NULL))
+ {
+ theGlyphInfoArrayPtr = (ATSUGlyphInfoArray *) malloc (theArraySize + sizeof(ItemCount) + sizeof(ATSUTextLayout));
+ if (theGlyphInfoArrayPtr)
+ {
+ if (noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, theGlyphInfoArrayPtr))
+ {
+ // do not count the first item, which is at the beginning of the line
+ for ( UniCharCount unicodePosition = 1, i = 0; i < len && unicodePosition < theGlyphInfoArrayPtr->numGlyphs; unicodePosition ++ )
+ {
+ // The ideal position is the x coordinate of the glyph, relative to the beginning of the line
+ int position = (int)( theGlyphInfoArrayPtr->glyphs[unicodePosition].idealX + 0.5 ); // These older APIs return float values
+ unsigned char uch = s[i];
+ positions[i++] = position;
+
+ // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters,
+ // as 1 unicode character can map to multiple UTF8 characters.
+ // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF
+ // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html
+ if ( unicodeMode )
+ {
+ unsigned char mask = 0xc0;
+ int count = 1;
+ // Add one additonal byte for each extra high order one in the byte
+ while ( uch >= mask && count < 8 )
+ {
+ positions[i++] = position;
+ count ++;
+ mask = mask >> 1 | 0x80; // add an additional one in the highest order position
+ }
+ }
+ }
+ }
+
+ // Free the GlyphInfoArray
+ free (theGlyphInfoArrayPtr);
+ }
+ }
+ free (buf);
+}
+
+int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+ if (font_.GetID())
+ {
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
+ unsigned long actualNumberOfBounds = 0;
+ ATSTrapezoid glyphBounds;
+
+ // We get a single bound, since the text should only require one. If it requires more, there is an issue
+ if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
+ {
+ Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthText" );
+ return 0;
+ }
+
+ //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) );
+ return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ }
+ return 1;
+}
+
+int SurfaceImpl::WidthChar(Font &font_, char ch) {
+ char str[2] = { ch, '\0' };
+ if (font_.GetID())
+ {
+ textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
+ unsigned long actualNumberOfBounds = 0;
+ ATSTrapezoid glyphBounds;
+
+ // We get a single bound, since the text should only require one. If it requires more, there is an issue
+ if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
+ {
+ Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthChar" );
+ return 0;
+ }
+
+ return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ }
+ else
+ return 1;
+}
+
+// Three possible strategies for determining ascent and descent of font:
+// 1) Call ATSUGetGlyphBounds with string containing all letters, numbers and punctuation.
+// 2) Use the ascent and descent fields of the font.
+// 3) Call ATSUGetGlyphBounds with string as 1 but also including accented capitals.
+// Smallest values given by 1 and largest by 3 with 2 in between.
+// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and
+// descenders but are mostly OK except for accented characters which are
+// rarely used in code.
+
+// This string contains a good range of characters to test for size.
+const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+int SurfaceImpl::Ascent(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUAscentTag );
+ return Fix2Long( ascent );
+}
+
+int SurfaceImpl::Descent(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUDescentTag );
+ return Fix2Long( descent );
+}
+
+int SurfaceImpl::InternalLeading(Font &) {
+ // TODO: How do we get EM_Size?
+ // internal leading = ascent - descent - EM_size
+ return 0;
+}
+
+int SurfaceImpl::ExternalLeading(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement lineGap = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSULeadingTag );
+ return Fix2Long( lineGap );
+}
+
+int SurfaceImpl::Height(Font &font_) {
+ return Ascent(font_) + Descent(font_);
+}
+
+int SurfaceImpl::AverageCharWidth(Font &font_) {
+
+ if (!font_.GetID())
+ return 1;
+
+ const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1);
+ int width = WidthText( font_, sizeString, sizeStringLength );
+
+ return (int) ((width / (float) sizeStringLength) + 0.5);
+
+ /*
+ ATSUStyle textStyle = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getATSUStyle();
+ ATSUFontID fontID;
+
+ ByteCount actualSize = 0;
+ if ( ATSUGetAttribute( textStyle, kATSUFontTag, sizeof( fontID ), &fontID, &actualSize ) != noErr )
+ {
+ Platform::DebugDisplay( "ATSUGetAttribute failed" );
+ return 1;
+ }
+
+ ATSFontMetrics metrics;
+ memset( &metrics, 0, sizeof( metrics ) );
+ if ( ATSFontGetHorizontalMetrics( fontID, kATSOptionFlagsDefault, &metrics ) != noErr )
+ {
+ Platform::DebugDisplay( "ATSFontGetHorizontalMetrics failed in AverageCharWidth" );
+ return 1;
+ }
+
+ printf( "%f %f %f\n", metrics.avgAdvanceWidth * 32, metrics.ascent * 32, metrics.descent * 32 );
+
+ return (int) (metrics.avgAdvanceWidth + 0.5);*/
+}
+
+int SurfaceImpl::SetPalette(Scintilla::Palette *, bool) {
+ // Mac OS X is always true colour (I think) so this doesn't matter
+ return 0;
+}
+
+void SurfaceImpl::SetClip(PRectangle rc) {
+ CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
+}
+
+void SurfaceImpl::FlushCachedState() {
+ CGContextSynchronize( gc );
+}
+
+void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+ unicodeMode = unicodeMode_;
+}
+
+void SurfaceImpl::SetDBCSMode(int codePage) {
+ // TODO: Implement this for code pages != UTF-8
+}
+
+Surface *Surface::Allocate()
+{
+ return new SurfaceImpl();
+}
+
+//----------------- Window -------------------------------------------------------------------------
+
+Window::~Window() {
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::Destroy()
+{
+ if (windowRef)
+ {
+ // not used
+ }
+ wid = 0;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool Window::HasFocus()
+{
+ NSView* container = reinterpret_cast<NSView*>(wid);
+ return [[container window] firstResponder] == container;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+PRectangle Window::GetPosition()
+{
+ NSRect rect= [reinterpret_cast<NSView*>(wid) frame];
+
+ return PRectangle(NSMinX(rect), NSMinY(rect), NSMaxX(rect), NSMaxY(rect));
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::SetPosition(PRectangle rc)
+{
+ // Moves this view inside the parent view
+ if ( wid )
+ {
+ // Set the frame on the view, the function handles the rest
+ // CGRect r = PRectangleToCGRect( rc );
+ // HIViewSetFrame( reinterpret_cast<HIViewRef>( wid ), &r );
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::SetPositionRelative(PRectangle rc, Window window) {
+ // // used to actually move child windows (ie. listbox/calltip) so we have to move
+ // // the window, not the hiview
+ // if (windowRef) {
+ // // we go through some contortions here to get an accurate location for our
+ // // child windows. This is necessary due to the multiple ways an embedding
+ // // app may be setup. See SciTest/main.c (GOOD && BAD) for test case.
+ // WindowRef relativeWindow = GetControlOwner(reinterpret_cast<HIViewRef>( window.GetID() ));
+ // WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef );
+ //
+ // Rect portBounds;
+ // ::GetWindowBounds(relativeWindow, kWindowStructureRgn, &portBounds);
+ // //fprintf(stderr, "portBounds %d %d %d %d\n", portBounds.left, portBounds.top, portBounds.right, portBounds.bottom);
+ // PRectangle hbounds = window.GetPosition();
+ // //fprintf(stderr, "hbounds %d %d %d %d\n", hbounds.left, hbounds.top, hbounds.right, hbounds.bottom);
+ // HIViewRef parent = HIViewGetSuperview(reinterpret_cast<HIViewRef>( window.GetID() ));
+ // Rect pbounds;
+ // GetControlBounds(parent, &pbounds);
+ // //fprintf(stderr, "pbounds %d %d %d %d\n", pbounds.left, pbounds.top, pbounds.right, pbounds.bottom);
+ //
+ // PRectangle bounds;
+ // bounds.top = portBounds.top + pbounds.top + hbounds.top + rc.top;
+ // bounds.bottom = bounds.top + rc.Height();
+ // bounds.left = portBounds.left + pbounds.left + hbounds.left + rc.left;
+ // bounds.right = bounds.left + rc.Width();
+ // //fprintf(stderr, "bounds %d %d %d %d\n", bounds.left, bounds.top, bounds.right, bounds.bottom);
+ //
+ // MoveWindow(thisWindow, bounds.left, bounds.top, false);
+ // SizeWindow(thisWindow, bounds.Width(), bounds.Height(), true);
+ //
+ // SetPosition(PRectangle(0,0,rc.Width(),rc.Height()));
+ // } else {
+ // SetPosition(rc);
+ // }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+PRectangle Window::GetClientPosition()
+{
+ // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32.
+ return GetPosition();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::Show(bool show)
+{
+ // if ( wid ) {
+ // HIViewSetVisible( reinterpret_cast<HIViewRef>( wid ), show );
+ // }
+ // // this is necessary for calltip/listbox
+ // if (windowRef) {
+ // WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef );
+ // if (show) {
+ // ShowWindow( thisWindow );
+ // DrawControls( thisWindow );
+ // } else
+ // HideWindow( thisWindow );
+ // }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Invalidates the entire window (here an NSView) so it is completely redrawn.
+ */
+void Window::InvalidateAll()
+{
+ if (wid)
+ {
+ NSView* container = reinterpret_cast<NSView*>(wid);
+ container.needsDisplay = YES;
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Invalidates part of the window (here an NSView) so only this part redrawn.
+ */
+void Window::InvalidateRectangle(PRectangle rc)
+{
+ if (wid)
+ {
+ NSView* container = reinterpret_cast<NSView*>(wid);
+ [container setNeedsDisplayInRect: PRectangleToNSRect(rc)];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::SetFont(Font &)
+{
+ // TODO: Do I need to implement this? MSDN: specifies the font that a control is to use when drawing text.
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts the Scintilla cursor enum into an NSCursor and stores it in the associated NSView,
+ * which then will take care to set up a new mouse tracking rectangle.
+ */
+void Window::SetCursor(Cursor curs)
+{
+ if (wid)
+ {
+ InnerView* container = reinterpret_cast<InnerView*>(wid);
+ [container setCursor: curs];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Window::SetTitle(const char *s)
+{
+ // WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>( wid ));
+ // CFStringRef title = CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingMacRoman);
+ // SetWindowTitleWithCFString(window, title);
+ // CFRelease(title);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+PRectangle Window::GetMonitorRect(Point)
+{
+ return PRectangle();
+}
+
+//----------------- ListBox ------------------------------------------------------------------------
+
+ListBox::ListBox()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+ListBox::~ListBox()
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+static const OSType scintillaListBoxType = 'sclb';
+
+enum {
+ kItemsPerContainer = 1,
+ kIconColumn = 'icon',
+ kTextColumn = 'text'
+};
+static SInt32 kScrollBarWidth = 0;
+
+class LineData {
+ int *types;
+ CFStringRef *strings;
+ int len;
+ int maximum;
+public:
+ LineData() :types(0), strings(0), len(0), maximum(0) {}
+ ~LineData() {
+ Clear();
+ }
+ void Clear() {
+ delete []types;
+ types = 0;
+ for (int i=0; i<maximum; i++) {
+ if (strings[i]) CFRelease(strings[i]);
+ }
+ delete []strings;
+ strings = 0;
+ len = 0;
+ maximum = 0;
+ }
+ void Add(int index, int type, CFStringRef str ) {
+ if (index >= maximum) {
+ if (index >= len) {
+ int lenNew = (index+1) * 2;
+ int *typesNew = new int[lenNew];
+ CFStringRef *stringsNew = new CFStringRef[lenNew];
+ for (int i=0; i<maximum; i++) {
+ typesNew[i] = types[i];
+ stringsNew[i] = strings[i];
+ }
+ delete []types;
+ delete []strings;
+ types = typesNew;
+ strings = stringsNew;
+ len = lenNew;
+ }
+ while (maximum < index) {
+ types[maximum] = 0;
+ strings[maximum] = 0;
+ maximum++;
+ }
+ }
+ types[index] = type;
+ strings[index] = str;
+ if (index == maximum) {
+ maximum++;
+ }
+ }
+ int GetType(int index) {
+ if (index < maximum) {
+ return types[index];
+ } else {
+ return 0;
+ }
+ }
+ CFStringRef GetString(int index) {
+ if (index < maximum) {
+ return strings[index];
+ } else {
+ return 0;
+ }
+ }
+};
+
+//----------------- ListBoxImpl --------------------------------------------------------------------
+
+class ListBoxImpl : public ListBox
+{
+private:
+ ControlRef lb;
+ XPMSet xset;
+ int lineHeight;
+ bool unicodeMode;
+ int desiredVisibleRows;
+ unsigned int maxItemWidth;
+ unsigned int aveCharWidth;
+ Font font;
+ int maxWidth;
+
+ void InstallDataBrowserCustomCallbacks();
+ void ConfigureDataBrowser();
+
+ static pascal OSStatus WindowEventHandler(EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void *inUserData );
+ EventHandlerRef eventHandler;
+
+protected:
+ WindowRef windowRef;
+
+public:
+ LineData ld;
+ CallBackAction doubleClickAction;
+ void *doubleClickActionData;
+
+ ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false),
+ desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8),
+ doubleClickAction(NULL), doubleClickActionData(NULL)
+ {
+ if (kScrollBarWidth == 0)
+ ;//GetThemeMetric(kThemeMetricScrollBarWidth, &kScrollBarWidth);
+ }
+
+ ~ListBoxImpl() {};
+ void SetFont(Font &font);
+ void Create(Window &parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_);
+ void SetAverageCharWidth(int width);
+ void SetVisibleRows(int rows);
+ int GetVisibleRows() const;
+ PRectangle GetDesiredRect();
+ int CaretFromEdge();
+ void Clear();
+ void Append(char *s, int type = -1);
+ int Length();
+ void Select(int n);
+ int GetSelection();
+ int Find(const char *prefix);
+ void GetValue(int n, char *value, int len);
+ void Sort();
+ void RegisterImage(int type, const char *xpm_data);
+ void ClearRegisteredImages();
+ void SetDoubleClickAction(CallBackAction action, void *data) {
+ doubleClickAction = action;
+ doubleClickActionData = data;
+ }
+
+ int IconWidth();
+ void ShowHideScrollbar();
+#ifdef DB_TABLE_ROW_HEIGHT
+ void SetRowHeight(DataBrowserItemID itemID);
+#endif
+
+ void DrawRow(DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect);
+
+ void SetList(const char* list, char separator, char typesep);
+};
+
+ListBox *ListBox::Allocate() {
+ ListBoxImpl *lb = new ListBoxImpl();
+ return lb;
+}
+
+void ListBoxImpl::Create(Window &/*parent*/, int /*ctrlID*/, Scintilla::Point /*pt*/,
+ int lineHeight_, bool unicodeMode_) {
+ lineHeight = lineHeight_;
+ unicodeMode = unicodeMode_;
+ maxWidth = 2000;
+
+ //WindowClass windowClass = kHelpWindowClass;
+ //WindowAttributes attributes = kWindowNoAttributes;
+ Rect contentBounds;
+ WindowRef outWindow;
+
+ contentBounds.top = contentBounds.left = 0;
+ contentBounds.right = 100;
+ contentBounds.bottom = lineHeight * desiredVisibleRows;
+
+ //CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow);
+
+ //InstallStandardEventHandler(GetWindowEventTarget(outWindow));
+
+ //ControlRef root;
+ //CreateRootControl(outWindow, &root);
+
+ //CreateDataBrowserControl(outWindow, &contentBounds, kDataBrowserListView, &lb);
+
+#ifdef DB_TABLE_ROW_HEIGHT
+ // TODO: does not seem to have any effect
+ //SetDataBrowserTableViewRowHeight(lb, lineHeight);
+#endif
+
+ // get rid of the frame, forces databrowser to the full size
+ // of the window
+ //Boolean frameAndFocus = false;
+ //SetControlData(lb, kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag,
+ // sizeof(frameAndFocus), &frameAndFocus);
+
+ //ListBoxImpl* lbThis = this;
+ //SetControlProperty( lb, scintillaListBoxType, 0, sizeof( this ), &lbThis );
+
+ ConfigureDataBrowser();
+ InstallDataBrowserCustomCallbacks();
+
+ // install event handlers
+ /*
+ static const EventTypeSpec kWindowEvents[] =
+ {
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseMoved },
+ };
+ */
+
+ eventHandler = NULL;
+ //InstallWindowEventHandler( outWindow, WindowEventHandler,
+ // GetEventTypeCount( kWindowEvents ),
+ // kWindowEvents, this, &eventHandler );
+
+ wid = lb;
+ //SetControlVisibility(lb, true, true);
+ SetControl(lb);
+ SetWindow(outWindow);
+}
+
+pascal OSStatus ListBoxImpl::WindowEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+
+ switch (kEventClassMouse /* GetEventClass(inEvent) */) {
+ case kEventClassMouse:
+ switch (kEventMouseDown /* GetEventKind(inEvent) */ )
+ {
+ case kEventMouseMoved:
+ {
+ //SetThemeCursor( kThemeArrowCursor );
+ break;
+ }
+ case kEventMouseDown:
+ {
+ // we cannot handle the double click from the databrowser notify callback as
+ // calling doubleClickAction causes the listbox to be destroyed. It is
+ // safe to do it from this event handler since the destroy event will be queued
+ // until we're done here.
+ /*
+ TCarbonEvent event( inEvent );
+ EventMouseButton inMouseButton;
+ event.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton );
+
+ UInt32 inClickCount;
+ event.GetParameter( kEventParamClickCount, &inClickCount );
+ if (inMouseButton == kEventMouseButtonPrimary && inClickCount == 2) {
+ // handle our single mouse click now
+ ListBoxImpl* listbox = reinterpret_cast<ListBoxImpl*>( inUserData );
+ const WindowRef window = GetControlOwner(listbox->lb);
+ const HIViewRef rootView = HIViewGetRoot( window );
+ HIViewRef targetView = NULL;
+ HIViewGetViewForMouseEvent( rootView, inEvent, &targetView );
+ if ( targetView == listbox->lb )
+ {
+ if (listbox->doubleClickAction != NULL) {
+ listbox->doubleClickAction(listbox->doubleClickActionData);
+ }
+ }
+ }
+ */
+ }
+ }
+ }
+ return eventNotHandledErr;
+}
+
+#ifdef DB_TABLE_ROW_HEIGHT
+void ListBoxImpl::SetRowHeight(DataBrowserItemID itemID)
+{
+ // XXX does not seem to have any effect
+ //SetDataBrowserTableViewItemRowHeight(lb, itemID, lineHeight);
+}
+#endif
+
+void ListBoxImpl::DrawRow(DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect)
+{
+ Rect row = *theRect;
+ row.left = 0;
+
+ ColourPair fore;
+
+ if (itemState == kDataBrowserItemIsSelected) {
+ long systemVersion;
+ Gestalt( gestaltSystemVersion, &systemVersion );
+ // Panther DB starts using kThemeBrushSecondaryHighlightColor for inactive browser hilighting
+ if ( (systemVersion >= 0x00001030) )//&& (IsControlActive( lb ) == false) )
+ ;//SetThemePen( kThemeBrushSecondaryHighlightColor, 32, true );
+ else
+ ; //SetThemePen( kThemeBrushAlternatePrimaryHighlightColor, 32, true );
+
+ PaintRect(&row);
+ fore = ColourDesired(0xff,0xff,0xff);
+ }
+
+ int widthPix = xset.GetWidth() + 2;
+ int pixId = ld.GetType(item - 1);
+ XPM *pxpm = xset.Get(pixId);
+
+ char s[255];
+ GetValue(item - 1, s, 255);
+
+ Surface *surfaceItem = Surface::Allocate();
+ if (surfaceItem) {
+ CGContextRef cgContext;
+ GrafPtr port;
+ Rect bounds;
+
+ //GetControlBounds(lb, &bounds);
+ GetPort( &port );
+ QDBeginCGContext( port, &cgContext );
+
+ CGContextSaveGState( cgContext );
+ CGContextTranslateCTM(cgContext, 0, bounds.bottom - bounds.top);
+ CGContextScaleCTM(cgContext, 1.0, -1.0);
+
+ surfaceItem->Init(cgContext, NULL);
+
+ int left = row.left;
+ if (pxpm) {
+ PRectangle rc(left + 1, row.top,
+ left + 1 + widthPix, row.bottom);
+ pxpm->Draw(surfaceItem, rc);
+ }
+
+ // draw the text
+ PRectangle trc(left + 2 + widthPix, row.top, row.right, row.bottom);
+ int ascent = surfaceItem->Ascent(font) - surfaceItem->InternalLeading(font);
+ int ytext = trc.top + ascent + 1;
+ trc.bottom = ytext + surfaceItem->Descent(font) + 1;
+ surfaceItem->DrawTextTransparent( trc, font, ytext, s, strlen(s), fore.allocated );
+
+ CGContextRestoreGState( cgContext );
+ QDEndCGContext( port, &cgContext );
+ delete surfaceItem;
+ }
+}
+
+
+pascal void ListBoxDrawItemCallback(ControlRef browser, DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect, SInt16 gdDepth,
+ Boolean colorDevice)
+{
+ if (property != kIconColumn) return;
+ ListBoxImpl* lbThis = NULL;
+ //OSStatus err;
+ //err = GetControlProperty( browser, scintillaListBoxType, 0, sizeof( lbThis ), NULL, &lbThis );
+ // adjust our rect
+ lbThis->DrawRow(item, property, itemState, theRect);
+
+}
+
+void ListBoxImpl::ConfigureDataBrowser()
+{
+ DataBrowserViewStyle viewStyle;
+ //DataBrowserSelectionFlags selectionFlags;
+ //GetDataBrowserViewStyle(lb, &viewStyle);
+
+ //SetDataBrowserHasScrollBars(lb, false, true);
+ //SetDataBrowserListViewHeaderBtnHeight(lb, 0);
+ //GetDataBrowserSelectionFlags(lb, &selectionFlags);
+ //SetDataBrowserSelectionFlags(lb, selectionFlags |= kDataBrowserSelectOnlyOne);
+ // if you change the hilite style, also change the style in ListBoxDrawItemCallback
+ //SetDataBrowserTableViewHiliteStyle(lb, kDataBrowserTableViewFillHilite);
+
+ Rect insetRect;
+ //GetDataBrowserScrollBarInset(lb, &insetRect);
+
+ insetRect.right = kScrollBarWidth - 1;
+ //SetDataBrowserScrollBarInset(lb, &insetRect);
+
+ switch (viewStyle)
+ {
+ case kDataBrowserListView:
+ {
+ DataBrowserListViewColumnDesc iconCol;
+ iconCol.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
+ iconCol.headerBtnDesc.minimumWidth = 0;
+ iconCol.headerBtnDesc.maximumWidth = maxWidth;
+ iconCol.headerBtnDesc.titleOffset = 0;
+ iconCol.headerBtnDesc.titleString = NULL;
+ iconCol.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
+
+ iconCol.headerBtnDesc.btnFontStyle.flags = kControlUseJustMask;
+ iconCol.headerBtnDesc.btnFontStyle.just = teFlushLeft;
+
+ iconCol.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
+
+ iconCol.propertyDesc.propertyID = kIconColumn;
+ iconCol.propertyDesc.propertyType = kDataBrowserCustomType;
+ iconCol.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn;
+
+ //AddDataBrowserListViewColumn(lb, &iconCol, kDataBrowserListViewAppendColumn);
+ } break;
+
+ }
+}
+
+void ListBoxImpl::InstallDataBrowserCustomCallbacks()
+{
+ /*
+ DataBrowserCustomCallbacks callbacks;
+
+ callbacks.version = kDataBrowserLatestCustomCallbacks;
+ verify_noerr(InitDataBrowserCustomCallbacks(&callbacks));
+ callbacks.u.v1.drawItemCallback = NewDataBrowserDrawItemUPP(ListBoxDrawItemCallback);
+ callbacks.u.v1.hitTestCallback = NULL;//NewDataBrowserHitTestUPP(ListBoxHitTestCallback);
+ callbacks.u.v1.trackingCallback = NULL;//NewDataBrowserTrackingUPP(ListBoxTrackingCallback);
+ callbacks.u.v1.editTextCallback = NULL;
+ callbacks.u.v1.dragRegionCallback = NULL;
+ callbacks.u.v1.acceptDragCallback = NULL;
+ callbacks.u.v1.receiveDragCallback = NULL;
+
+ SetDataBrowserCustomCallbacks(lb, &callbacks);
+ */
+}
+
+void ListBoxImpl::SetFont(Font &font_) {
+ // Having to do this conversion is LAME
+ QuartzTextStyle *ts = reinterpret_cast<QuartzTextStyle*>( font_.GetID() );
+ ControlFontStyleRec style;
+ ATSUAttributeValuePtr value;
+ ATSUFontID fontID;
+ style.flags = kControlUseFontMask | kControlUseSizeMask | kControlAddToMetaFontMask;
+ ts->getAttribute( kATSUFontTag, sizeof(fontID), &fontID, NULL );
+ ATSUFontIDtoFOND(fontID, &style.font, NULL);
+ ts->getAttribute( kATSUSizeTag, sizeof(Fixed), &value, NULL );
+ style.size = ((SInt16)FixRound((SInt32)value));
+ //SetControlFontStyle(lb, &style);
+
+#ifdef DB_TABLE_ROW_HEIGHT
+ // XXX this doesn't *stick*
+ ATSUTextMeasurement ascent = ts->getAttribute<ATSUTextMeasurement>( kATSUAscentTag );
+ ATSUTextMeasurement descent = ts->getAttribute<ATSUTextMeasurement>( kATSUDescentTag );
+ lineHeight = Fix2Long( ascent ) + Fix2Long( descent );
+ //SetDataBrowserTableViewRowHeight(lb, lineHeight + lineLeading);
+#endif
+
+ // !@&^#%$ we cant copy Font, but we need one for our custom drawing
+ Str255 fontName255;
+ char fontName[256];
+ FMGetFontFamilyName(style.font, fontName255);
+
+ CFStringRef fontNameCF = ::CFStringCreateWithPascalString( kCFAllocatorDefault, fontName255, kCFStringEncodingMacRoman );
+ ::CFStringGetCString( fontNameCF, fontName, (CFIndex)255, kCFStringEncodingMacRoman );
+
+ font.Create((const char *)fontName, 0, style.size, false, false);
+}
+
+void ListBoxImpl::SetAverageCharWidth(int width) {
+ aveCharWidth = width;
+}
+
+void ListBoxImpl::SetVisibleRows(int rows) {
+ desiredVisibleRows = rows;
+}
+
+int ListBoxImpl::GetVisibleRows() const {
+ // XXX Windows & GTK do this, but it seems incorrect to me. Other logic
+ // to do with visible rows is essentially the same across platforms.
+ return desiredVisibleRows;
+ /*
+ // This would be more correct
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+ return rows;
+ */
+}
+
+PRectangle ListBoxImpl::GetDesiredRect() {
+ PRectangle rcDesired = GetPosition();
+
+ // XXX because setting the line height on the table doesnt
+ // *stick*, we'll have to suffer and just use whatever
+ // the table desides is the correct height.
+ UInt16 itemHeight;// = lineHeight;
+ //GetDataBrowserTableViewRowHeight(lb, &itemHeight);
+
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+
+ rcDesired.bottom = itemHeight * rows;
+ rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth;
+
+ if (Length() > rows)
+ rcDesired.right += kScrollBarWidth;
+ rcDesired.right += IconWidth();
+
+ // Set the column width
+ //SetDataBrowserTableViewColumnWidth (lb, UInt16 (rcDesired.right - rcDesired.left));
+ return rcDesired;
+}
+
+void ListBoxImpl::ShowHideScrollbar() {
+ int rows = Length();
+ if (rows > desiredVisibleRows) {
+ //SetDataBrowserHasScrollBars(lb, false, true);
+ } else {
+ //SetDataBrowserHasScrollBars(lb, false, false);
+ }
+}
+
+int ListBoxImpl::IconWidth() {
+ return xset.GetWidth() + 2;
+}
+
+int ListBoxImpl::CaretFromEdge() {
+ return 0;
+}
+
+void ListBoxImpl::Clear() {
+ // passing NULL to "items" arg 4 clears the list
+ maxItemWidth = 0;
+ ld.Clear();
+ //AddDataBrowserItems (lb, kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty);
+}
+
+void ListBoxImpl::Append(char *s, int type) {
+ int count = Length();
+ CFStringRef r = CFStringCreateWithCString(NULL, s, kTextEncodingMacRoman);
+ ld.Add(count, type, r);
+
+ Scintilla::SurfaceImpl surface;
+ unsigned int width = surface.WidthText (font, s, strlen (s));
+ if (width > maxItemWidth)
+ maxItemWidth = width;
+
+ DataBrowserItemID items[1];
+ items[0] = count + 1;
+ //AddDataBrowserItems (lb, kDataBrowserNoItem, 1, items, kDataBrowserItemNoProperty);
+ ShowHideScrollbar();
+}
+
+void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
+ // XXX copied from PlatGTK, should be in base class
+ Clear();
+ int count = strlen(list) + 1;
+ char *words = new char[count];
+ if (words) {
+ memcpy(words, list, count);
+ char *startword = words;
+ char *numword = NULL;
+ int i = 0;
+ for (; words[i]; i++) {
+ if (words[i] == separator) {
+ words[i] = '\0';
+ if (numword)
+ *numword = '\0';
+ 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';
+ Append(startword, numword?atoi(numword + 1):-1);
+ }
+ delete []words;
+ }
+}
+
+int ListBoxImpl::Length() {
+ UInt32 numItems = 0;
+ //GetDataBrowserItemCount(lb, kDataBrowserNoItem, false, kDataBrowserItemAnyState, &numItems);
+ return (int)numItems;
+}
+
+void ListBoxImpl::Select(int n) {
+ DataBrowserItemID items[1];
+ items[0] = n + 1;
+ //SetDataBrowserSelectedItems(lb, 1, items, kDataBrowserItemsAssign);
+ //RevealDataBrowserItem(lb, items[0], kIconColumn, kDataBrowserRevealOnly);
+ // force update on selection
+ //Draw1Control(lb);
+}
+
+int ListBoxImpl::GetSelection() {
+ Handle selectedItems = NewHandle(0);
+ //GetDataBrowserItems(lb, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems);
+ UInt32 numSelectedItems = GetHandleSize(selectedItems)/sizeof(DataBrowserItemID);
+ if (numSelectedItems == 0) {
+ return -1;
+ }
+ HLock( selectedItems );
+ DataBrowserItemID *individualItem = (DataBrowserItemID*)( *selectedItems );
+ DataBrowserItemID selected[numSelectedItems];
+ selected[0] = *individualItem;
+ HUnlock( selectedItems );
+ return selected[0] - 1;
+}
+
+int ListBoxImpl::Find(const char *prefix) {
+ int count = Length();
+ char s[255];
+ for (int i = 0; i < count; i++) {
+ GetValue(i, s, 255);
+ if ((s[0] != '\0') && (0 == strncmp(prefix, s, strlen(prefix)))) {
+ return i;
+ }
+ }
+ return - 1;
+}
+
+void ListBoxImpl::GetValue(int n, char *value, int len) {
+ CFStringRef textString = ld.GetString(n);
+ if (textString == NULL) {
+ value[0] = '\0';
+ return;
+ }
+ CFIndex numUniChars = CFStringGetLength( textString );
+
+ // XXX how do we know the encoding of the listbox?
+ CFStringEncoding encoding = kCFStringEncodingUTF8; //( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII);
+ CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1;
+ char* text = new char[maximumByteLength];
+ CFIndex usedBufferLength = 0;
+ CFStringGetBytes( textString, CFRangeMake( 0, numUniChars ), encoding,
+ '?', false, reinterpret_cast<UInt8*>( text ),
+ maximumByteLength, &usedBufferLength );
+ text[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string
+
+ if (text && len > 0) {
+ strncpy(value, text, len);
+ value[len - 1] = '\0';
+ } else {
+ value[0] = '\0';
+ }
+ delete text;
+}
+
+void ListBoxImpl::Sort() {
+ // TODO: Implement this
+ fprintf(stderr, "ListBox::Sort\n");
+}
+
+void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
+ xset.Add(type, xpm_data);
+}
+
+void ListBoxImpl::ClearRegisteredImages() {
+ xset.Clear();
+}
+
+//----------------- ScintillaContextMenu -----------------------------------------------------------
+
+@implementation ScintillaContextMenu : NSMenu
+
+// This NSMenu subclass serves also as target for menu commands and forwards them as
+// notfication messages to the front end.
+
+- (void) handleCommand: (NSMenuItem*) sender
+{
+ owner->HandleCommand([sender tag]);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner
+{
+ owner = newOwner;
+}
+
+@end
+
+//----------------- Menu ---------------------------------------------------------------------------
+
+Menu::Menu()
+ : mid(0)
+{
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Menu::CreatePopUp()
+{
+ Destroy();
+ mid = [[ScintillaContextMenu alloc] initWithTitle: @""];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Menu::Destroy()
+{
+ ScintillaContextMenu* menu = reinterpret_cast<ScintillaContextMenu*>(mid);
+ [menu release];
+ mid = NULL;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Menu::Show(Point pt, Window &)
+{
+ // Cocoa menus are handled a bit differently. We only create the menu. The framework
+ // takes care to show it properly.
+}
+
+//----------------- ElapsedTime --------------------------------------------------------------------
+
+// TODO: Consider if I should be using GetCurrentEventTime instead of gettimeoday
+ElapsedTime::ElapsedTime() {
+ struct timeval curTime;
+ int retVal;
+ retVal = gettimeofday( &curTime, NULL );
+
+ bigBit = curTime.tv_sec;
+ littleBit = curTime.tv_usec;
+}
+
+double ElapsedTime::Duration(bool reset) {
+ struct timeval curTime;
+ int retVal;
+ retVal = gettimeofday( &curTime, NULL );
+ long endBigBit = curTime.tv_sec;
+ long endLittleBit = curTime.tv_usec;
+ double result = 1000000.0 * (endBigBit - bigBit);
+ result += endLittleBit - littleBit;
+ result /= 1000000.0;
+ if (reset) {
+ bigBit = endBigBit;
+ littleBit = endLittleBit;
+ }
+ return result;
+}
+
+//----------------- Platform -----------------------------------------------------------------------
+
+ColourDesired Platform::Chrome()
+{
+ return ColourDesired(0xE0, 0xE0, 0xE0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+ColourDesired Platform::ChromeHighlight()
+{
+ return ColourDesired(0xFF, 0xFF, 0xFF);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Returns the currently set system font for the user.
+ */
+const char *Platform::DefaultFont()
+{
+ NSString* name = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSFixedPitchFont"];
+ return [name UTF8String];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Returns the currently set system font size for the user.
+ */
+int Platform::DefaultFontSize()
+{
+ return [[NSUserDefaults standardUserDefaults] integerForKey: @"NSFixedPitchFontSize"];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Returns the time span in which two consequtive mouse clicks must occur to be considered as
+ * double click.
+ *
+ * @return
+ */
+unsigned int Platform::DoubleClickTime()
+{
+ float threshold = [[NSUserDefaults standardUserDefaults] floatForKey:
+ @"com.apple.mouse.doubleClickThreshold"];
+ if (threshold == 0)
+ threshold = 0.5;
+ return static_cast<unsigned int>(threshold / kEventDurationMillisecond);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool Platform::MouseButtonBounce()
+{
+ return false;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper method for the backend to reach through to the scintiall window.
+ */
+long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam)
+{
+ return scintilla_send_message(w, msg, wParam, lParam);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper method for the backend to reach through to the scintiall window.
+ */
+long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam)
+{
+ return scintilla_send_message(w, msg, wParam, (long) lParam);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool Platform::IsDBCSLeadByte(int codePage, char ch)
+{
+ // No support for DBCS.
+ return false;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+int Platform::DBCSCharLength(int codePage, const char* s)
+{
+ // No support for DBCS.
+ return 1;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+int Platform::DBCSCharMaxLength()
+{
+ // No support for DBCS.
+ return 2;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+int Platform::Minimum(int a, int b)
+{
+ return (a < b) ? a : b;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+int Platform::Maximum(int a, int b) {
+ return (a > b) ? a : b;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+//#define TRACE
+#ifdef TRACE
+
+void Platform::DebugDisplay(const char *s)
+{
+ fprintf( stderr, s );
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Platform::DebugPrintf(const char *format, ...)
+{
+ const int BUF_SIZE = 2000;
+ char buffer[BUF_SIZE];
+
+ va_list pArguments;
+ va_start(pArguments, format);
+ vsnprintf(buffer, BUF_SIZE, format, pArguments);
+ va_end(pArguments);
+ Platform::DebugDisplay(buffer);
+}
+
+#else
+
+void Platform::DebugDisplay(const char *) {}
+
+void Platform::DebugPrintf(const char *, ...) {}
+
+#endif
+
+//--------------------------------------------------------------------------------------------------
+
+static bool assertionPopUps = true;
+
+bool Platform::ShowAssertionPopUps(bool assertionPopUps_)
+{
+ bool ret = assertionPopUps;
+ assertionPopUps = assertionPopUps_;
+ return ret;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void Platform::Assert(const char *c, const char *file, int line)
+{
+ char buffer[2000];
+ sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
+ strcat(buffer, "\r\n");
+ Platform::DebugDisplay(buffer);
+#ifdef DEBUG
+ // Jump into debugger in assert on Mac (CL269835)
+ ::Debugger();
+#endif
+}
+
+//--------------------------------------------------------------------------------------------------
+
+int Platform::Clamp(int val, int minVal, int maxVal)
+{
+ if (val > maxVal)
+ val = maxVal;
+ if (val < minVal)
+ val = minVal;
+ return val;
+}
+
+//----------------- DynamicLibrary -----------------------------------------------------------------
+
+/**
+ * Implements the platform specific part of library loading.
+ *
+ * @param modulePath The path to the module to load.
+ * @return A library instance or NULL if the module could not be found or another problem occured.
+ */
+DynamicLibrary* DynamicLibrary::Load(const char* modulePath)
+{
+ return NULL;
+}
+
+//--------------------------------------------------------------------------------------------------
+
diff --git a/scintilla/cocoa/QuartzTextLayout.h b/scintilla/cocoa/QuartzTextLayout.h
new file mode 100644
index 0000000..c032da9
--- /dev/null
+++ b/scintilla/cocoa/QuartzTextLayout.h
@@ -0,0 +1,141 @@
+/*
+ * QuartzTextLayout.h
+ *
+ * Original Code by Evan Jones on Wed Oct 02 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ */
+
+#ifndef _QUARTZ_TEXT_LAYOUT_H
+#define _QUARTZ_TEXT_LAYOUT_H
+
+#include <Cocoa/Cocoa.h>
+
+#include "QuartzTextStyle.h"
+
+class QuartzTextLayout
+{
+public:
+ /** Create a text layout for drawing on the specified context. */
+ QuartzTextLayout( CGContextRef context ) : layout( NULL ), unicode_string( NULL ), unicode_length( 0 )
+ {
+ OSStatus err = ATSUCreateTextLayout( &layout );
+ if (0 != err)
+ layout = NULL;
+
+ setContext(context);
+
+ ATSUAttributeTag tag = kATSULineLayoutOptionsTag;
+ ByteCount size = sizeof( ATSLineLayoutOptions );
+ ATSLineLayoutOptions rendering = kATSLineUseDeviceMetrics; //| kATSLineFractDisable | kATSLineUseQDRendering
+ ATSUAttributeValuePtr valuePtr = &rendering;
+ err = ATSUSetLayoutControls( layout, 1, &tag, &size, &valuePtr );
+ }
+
+ ~QuartzTextLayout()
+ {
+ if (NULL != layout)
+ ATSUDisposeTextLayout( layout );
+ layout = NULL;
+
+ if ( unicode_string != NULL )
+ {
+ delete[] unicode_string;
+ unicode_string = NULL;
+ unicode_length = 0;
+ }
+ }
+
+ /** Assign a string to the text layout object. */
+ // TODO: Create a UTF8 version
+ // TODO: Optimise the ASCII version by not copying so much
+ OSStatus setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding )
+ {
+ if (NULL == layout)
+ return -1;
+ CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false );
+ if (!str)
+ return -1;
+
+ unicode_length = CFStringGetLength( str );
+ if (unicode_string)
+ delete[] unicode_string;
+ unicode_string = new UniChar[ unicode_length ];
+ CFStringGetCharacters( str, CFRangeMake( 0, unicode_length ), unicode_string );
+
+ CFRelease( str );
+ str = NULL;
+
+ OSStatus err;
+ err = ATSUSetTextPointerLocation( layout, unicode_string, kATSUFromTextBeginning, kATSUToTextEnd, unicode_length );
+ if( err != noErr ) return err;
+
+ // Turn on the default font fallbacks
+ return ATSUSetTransientFontMatching( layout, true );
+ }
+
+ inline void setText( const UInt8* buffer, size_t byteLength, const QuartzTextStyle& r )
+ {
+ this->setText( buffer, byteLength, kCFStringEncodingUTF8 );
+ ATSUSetRunStyle( layout, r.getATSUStyle(), 0, unicode_length );
+ }
+
+ /** Apply the specified text style on the entire range of text. */
+ void setStyle( const QuartzTextStyle& style )
+ {
+ ATSUSetRunStyle( layout, style.getATSUStyle(), kATSUFromTextBeginning, kATSUToTextEnd );
+ }
+
+ /** Draw the text layout into the current CGContext at the specified position, flipping the CGContext's Y axis if required.
+ * @param x The x axis position to draw the baseline in the current CGContext.
+ * @param y The y axis position to draw the baseline in the current CGContext.
+ * @param flipTextYAxis If true, the CGContext's Y axis will be flipped before drawing the text, and restored afterwards. Use this when drawing in an HIView's CGContext, where the origin is the top left corner. */
+ void draw( float x, float y, bool flipTextYAxis = false )
+ {
+ if (NULL == layout || 0 == unicode_length)
+ return;
+ if ( flipTextYAxis )
+ {
+ CGContextSaveGState( gc );
+ CGContextScaleCTM( gc, 1.0, -1.0 );
+ y = -y;
+ }
+
+ OSStatus err;
+ err = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) );
+
+ if ( flipTextYAxis ) CGContextRestoreGState( gc );
+ }
+
+ /** Sets a single text layout control on the ATSUTextLayout object.
+ * @param tag The control to set.
+ * @param size The size of the parameter pointed to by value.
+ * @param value A pointer to the new value for the control.
+ */
+ void setControl( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
+ {
+ ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
+ }
+
+ ATSUTextLayout getLayout() {
+ return layout;
+ }
+
+ inline CFIndex getLength() const { return unicode_length; }
+ inline void setContext (CGContextRef context)
+ {
+ gc = context;
+ if (NULL != layout)
+ setControl( kATSUCGContextTag, sizeof( gc ), &gc );
+ }
+
+private:
+ ATSUTextLayout layout;
+ UniChar* unicode_string;
+ int unicode_length;
+ CGContextRef gc;
+};
+
+#endif
diff --git a/scintilla/cocoa/QuartzTextStyle.h b/scintilla/cocoa/QuartzTextStyle.h
new file mode 100644
index 0000000..58f0849
--- /dev/null
+++ b/scintilla/cocoa/QuartzTextStyle.h
@@ -0,0 +1,90 @@
+/*
+ * QuartzTextStyle.h
+ *
+ * Created by Evan Jones on Wed Oct 02 2002.
+ *
+ */
+
+#ifndef _QUARTZ_TEXT_STYLE_H
+#define _QUARTZ_TEXT_STYLE_H
+
+#include "QuartzTextStyleAttribute.h"
+
+class QuartzTextStyle
+{
+public:
+ QuartzTextStyle()
+ {
+ ATSUCreateStyle( &style );
+ }
+
+ ~QuartzTextStyle()
+ {
+ if ( style != NULL )
+ ATSUDisposeStyle( style );
+ style = NULL;
+ }
+
+ void setAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
+ {
+ ATSUSetAttributes( style, 1, &tag, &size, &value );
+ }
+
+ void setAttribute( QuartzTextStyleAttribute& attribute )
+ {
+ setAttribute( attribute.getTag(), attribute.getSize(), attribute.getValuePtr() );
+ }
+
+ void getAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value, ByteCount* actualSize )
+ {
+ ATSUGetAttribute( style, tag, size, value, actualSize );
+ }
+
+ template <class T>
+ T getAttribute( ATSUAttributeTag tag )
+ {
+ T value;
+ ByteCount actualSize;
+ ATSUGetAttribute( style, tag, sizeof( T ), &value, &actualSize );
+ return value;
+ }
+
+ // TODO: Is calling this actually faster than calling setAttribute multiple times?
+ void setAttributes( QuartzTextStyleAttribute* attributes[], int number )
+ {
+ // Create the parallel arrays and initialize them properly
+ ATSUAttributeTag* tags = new ATSUAttributeTag[ number ];
+ ByteCount* sizes = new ByteCount[ number ];
+ ATSUAttributeValuePtr* values = new ATSUAttributeValuePtr[ number ];
+
+ for ( int i = 0; i < number; ++ i )
+ {
+ tags[i] = attributes[i]->getTag();
+ sizes[i] = attributes[i]->getSize();
+ values[i] = attributes[i]->getValuePtr();
+ }
+
+ ATSUSetAttributes( style, number, tags, sizes, values );
+
+ // Free the arrays that were allocated
+ delete[] tags;
+ delete[] sizes;
+ delete[] values;
+ }
+
+ void setFontFeature( ATSUFontFeatureType featureType, ATSUFontFeatureSelector selector )
+ {
+ ATSUSetFontFeatures( style, 1, &featureType, &selector );
+ }
+
+ const ATSUStyle& getATSUStyle() const
+ {
+ return style;
+ }
+
+private:
+ ATSUStyle style;
+};
+
+#endif
+
diff --git a/scintilla/cocoa/QuartzTextStyleAttribute.h b/scintilla/cocoa/QuartzTextStyleAttribute.h
new file mode 100644
index 0000000..21f6abc
--- /dev/null
+++ b/scintilla/cocoa/QuartzTextStyleAttribute.h
@@ -0,0 +1,142 @@
+/**
+ * QuartzTextStyleAttribute.h
+ *
+ * Original Code by Evan Jones on Wed Oct 02 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ */
+
+
+#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
+#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
+
+class QuartzTextStyleAttribute
+{
+public:
+ QuartzTextStyleAttribute() {}
+ virtual ~QuartzTextStyleAttribute() {}
+ virtual ByteCount getSize() const = 0;
+ virtual ATSUAttributeValuePtr getValuePtr() = 0;
+ virtual ATSUAttributeTag getTag() const = 0;
+};
+
+class QuartzTextSize : public QuartzTextStyleAttribute
+{
+public:
+ QuartzTextSize( float points )
+ {
+ size = X2Fix( points );
+ }
+
+ ByteCount getSize() const
+ {
+ return sizeof( size );
+ }
+
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &size;
+ }
+
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUSizeTag;
+ }
+
+private:
+ Fixed size;
+};
+
+class QuartzTextStyleAttributeBoolean : public QuartzTextStyleAttribute
+{
+public:
+ QuartzTextStyleAttributeBoolean( bool newVal ) : value( newVal ) {}
+
+ ByteCount getSize() const
+ {
+ return sizeof( value );
+ }
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &value;
+ }
+
+ virtual ATSUAttributeTag getTag() const = 0;
+
+private:
+ Boolean value;
+};
+
+class QuartzTextBold : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextBold( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUQDBoldfaceTag;
+ }
+};
+
+class QuartzTextItalic : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextItalic( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUQDItalicTag;
+ }
+};
+
+class QuartzTextUnderline : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextUnderline( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const {
+ return kATSUQDUnderlineTag;
+ }
+};
+
+class QuartzFont : public QuartzTextStyleAttribute
+{
+public:
+ /** Create a font style from a name. */
+ QuartzFont( const char* name, int length )
+ {
+ assert( name != NULL && length > 0 && name[length] == '\0' );
+ // try to create font
+ OSStatus err = ATSUFindFontFromName( const_cast<char*>( name ), length, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
+
+ // need a fallback if font isn't installed
+ if( err != noErr || fontid == kATSUInvalidFontID )
+ ::ATSUFindFontFromName( "Lucida Grande", 13, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
+ }
+
+ ByteCount getSize() const
+ {
+ return sizeof( fontid );
+ }
+
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &fontid;
+ }
+
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUFontTag;
+ }
+
+ ATSUFontID getFontID() const
+ {
+ return fontid;
+ }
+
+private:
+ ATSUFontID fontid;
+};
+
+
+#endif
+
diff --git a/scintilla/cocoa/SciTest.mk b/scintilla/cocoa/SciTest.mk
new file mode 100644
index 0000000..9023def
--- /dev/null
+++ b/scintilla/cocoa/SciTest.mk
@@ -0,0 +1,54 @@
+### start defines ###
+NAME=Editor
+
+ARCH=-arch i386
+CC=gcc -x c++ $(ARCH)
+CO=gcc -x objective-c++ $(ARCH)
+LD=gcc $(ARCH) -framework Cocoa
+
+gDEFs=-DSCI_NAMESPACE -DSCI_LEXER
+
+INCS=-I../src/ -I../include/ -I.
+CCX=$(CC) $(gDEFs) $(INCS)
+CCO=$(CO) $(gDEFs) $(INCS)
+
+BLD=build/SciAppBuild
+TARG=$(APP)/Contents/MacOS/$(NAME)
+APP=$(BLD)/$(NAME).app
+
+all: $(BLD) $(TARG)
+
+clean:
+ -rm -rf $(BLD)
+
+$(APP):
+ -rm -rf $(APP)
+ -mkdir $(APP)
+ -mkdir $(APP)/Contents/
+ -mkdir $(APP)/Contents/Frameworks/
+ -mkdir $(APP)/Contents/MacOS/
+ -mkdir $(APP)/Contents/Resources/
+ -cp ScintillaTest/Info.plist $(APP)/Contents/Info.plist.bak
+ -sed "s/\$${EXECUTABLE_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak > $(APP)/Contents/Info.plist.bak2
+ -sed "s/\$${PRODUCT_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak2 > $(APP)/Contents/Info.plist
+ -rm $(APP)/Contents/Info.plist.bak $(APP)/Contents/Info.plist.bak2
+ -cp -r ScintillaTest/English.lproj $(APP)/Contents/Resources/
+ /Developer/usr/bin/ibtool --errors --warnings --notices --output-format human-readable-text \
+ --compile $(APP)/Contents/Resources/English.lproj/MainMenu.nib ScintillaTest/English.lproj/MainMenu.xib
+ -cp ScintillaTest/TestData.sql $(APP)/Contents/Resources/
+ -make -f Framework.mk all
+
+$(TARG) : $(BLD)/main.o $(BLD)/AppController.o $(APP)
+ -cp -R build/framebuild/Sci.framework $(APP)/Contents/Frameworks/
+ $(LD) $(BLD)/main.o $(BLD)/AppController.o $(APP)/Contents/Frameworks/Sci.framework/Sci -o $(TARG) -lstdc++
+
+
+$(BLD) :
+ -mkdir build
+ -mkdir $(BLD)
+
+$(BLD)/%.o : ScintillaTest/%.mm
+ $(CCO) -c $< -o $@
+
+$(BLD)/%.o : ScintillaTest/%.m
+ $(CCO) -c $< -o $@
diff --git a/scintilla/cocoa/ScintillaCallTip.h b/scintilla/cocoa/ScintillaCallTip.h
new file mode 100644
index 0000000..74c551a
--- /dev/null
+++ b/scintilla/cocoa/ScintillaCallTip.h
@@ -0,0 +1,63 @@
+/*
+ * ScintillaMacOSX.h
+ * tutorial
+ *
+ * Created by Evan Jones on Sun Sep 01 2002.
+ *
+ */
+#ifndef SCINTILLA_CALLTIP_H
+#define SCINTILLA_CALLTIP_H
+
+#include "TView.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+static const OSType scintillaCallTipType = 'Scct';
+
+namespace Scintilla {
+
+class ScintillaCallTip : public TView
+{
+public:
+ // Private so ScintillaCallTip objects can not be copied
+ ScintillaCallTip(const ScintillaCallTip &) : TView( NULL ) {}
+ ScintillaCallTip &operator=(const ScintillaCallTip &) { return * this; }
+ ~ScintillaCallTip() {};
+
+public:
+ /** This is the class ID that we've assigned to Scintilla. */
+ static const CFStringRef kScintillaCallTipClassID;
+ static const ControlKind kScintillaCallTipKind;
+
+ ScintillaCallTip( void* windowid );
+
+ /** Returns the HIView object kind, needed to subclass TView. */
+ virtual ControlKind GetKind() { return kScintillaCallTipKind; }
+
+private:
+
+ virtual ControlPartCode HitTest( const HIPoint& where );
+ virtual void Draw( RgnHandle rgn, CGContextRef gc );
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+
+public:
+ static HIViewRef Create();
+private:
+ static OSStatus Construct( HIViewRef inControl, TView** outView );
+
+};
+
+
+}
+
+
+#endif
diff --git a/scintilla/cocoa/ScintillaCallTip.mm b/scintilla/cocoa/ScintillaCallTip.mm
new file mode 100644
index 0000000..db72ee1
--- /dev/null
+++ b/scintilla/cocoa/ScintillaCallTip.mm
@@ -0,0 +1,117 @@
+
+#include "ScintillaCocoa.h"
+#include "ScintillaCallTip.h"
+#include "CallTip.h"
+
+using namespace Scintilla;
+
+const CFStringRef ScintillaCallTip::kScintillaCallTipClassID = CFSTR( "org.scintilla.calltip" );
+const ControlKind ScintillaCallTip::kScintillaCallTipKind = { 'ejon', 'Scct' };
+
+ScintillaCallTip::ScintillaCallTip( void* windowid ) :
+ TView( reinterpret_cast<HIViewRef>( windowid ) )
+{
+ ActivateInterface( kMouse );
+ // debugPrint = true;
+}
+
+void ScintillaCallTip::Draw(
+ RgnHandle /*inLimitRgn*/,
+ CGContextRef inContext )
+{
+ // Get a reference to the Scintilla C++ object
+ CallTip* ctip = NULL;
+ OSStatus err;
+ err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip );
+ assert(err == noErr);
+ if (ctip == NULL) return;
+
+ Rect contentBounds;
+ GetControlBounds(GetViewRef(), &contentBounds);
+
+ HIRect controlFrame;
+ HIViewGetFrame( GetViewRef(), &controlFrame );
+
+ // what is the global pos?
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(inContext, GetViewRef());
+ ctip->PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+
+}
+
+ControlPartCode ScintillaCallTip::HitTest( const HIPoint& where )
+{
+ if ( CGRectContainsPoint( Bounds(), where ) )
+ return 1;
+ else
+ return kControlNoPart;
+}
+
+OSStatus ScintillaCallTip::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ CallTip* ctip = NULL;
+ ScintillaCocoa *sciThis = NULL;
+ OSStatus err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip );
+ err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis );
+ ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ));
+ sciThis->CallTipClick();
+ return noErr;
+}
+
+OSStatus ScintillaCallTip::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ return noErr;
+}
+
+OSStatus ScintillaCallTip::MouseDragged( HIPoint& location, UInt32 /*modifiers*/, EventMouseButton /*button*/, UInt32 /*clickCount*/ )
+{
+ SetThemeCursor( kThemeArrowCursor );
+ return noErr;
+}
+
+HIViewRef ScintillaCallTip::Create()
+{
+ // Register the HIView, if needed
+ static bool registered = false;
+
+ if ( not registered )
+ {
+ TView::RegisterSubclass( kScintillaCallTipClassID, Construct );
+ registered = true;
+ }
+
+ OSStatus err = noErr;
+ EventRef event = CreateInitializationEvent();
+ assert( event != NULL );
+
+ HIViewRef control = NULL;
+ err = HIObjectCreate( kScintillaCallTipClassID, event, reinterpret_cast<HIObjectRef*>( &control ) );
+ ReleaseEvent( event );
+ if ( err == noErr ) {
+ Platform::DebugPrintf("ScintillaCallTip::Create control %08X\n",control);
+ return control;
+ }
+ return NULL;
+}
+
+OSStatus ScintillaCallTip::Construct( HIViewRef inControl, TView** outView )
+{
+ *outView = new ScintillaCallTip( inControl );
+ Platform::DebugPrintf("ScintillaCallTip::Construct scintilla %08X\n",*outView);
+ if ( *outView != NULL )
+ return noErr;
+ else
+ return memFullErr;
+}
+
+extern "C" {
+HIViewRef scintilla_calltip_new() {
+ return ScintillaCallTip::Create();
+}
+}
diff --git a/scintilla/cocoa/ScintillaCocoa.h b/scintilla/cocoa/ScintillaCocoa.h
new file mode 100644
index 0000000..03b239c
--- /dev/null
+++ b/scintilla/cocoa/ScintillaCocoa.h
@@ -0,0 +1,211 @@
+/*
+ * ScintillaCocoa.h
+ *
+ * Mike Lischke <mlischke@sun.com>
+ *
+ * Based on ScintillaMacOSX.h
+ * Original code by Evan Jones on Sun Sep 01 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <vector>
+
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "PropSetSimple.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+
+#include "SVector.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "AutoComplete.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+//#include "ScintillaCallTip.h"
+
+#include "ScintillaBase.h"
+
+extern "C" NSString* ScintillaRecPboardType;
+
+@class ScintillaView;
+
+/**
+ * Helper class to be used as timer target (NSTimer).
+ */
+@interface TimerTarget : NSObject
+{
+ void* mTarget;
+ NSNotificationQueue* notificationQueue;
+}
+- (id) init: (void*) target;
+- (void) timerFired: (NSTimer*) timer;
+- (void) idleTimerFired: (NSTimer*) timer;
+- (void) idleTriggered: (NSNotification*) notification;
+@end
+
+namespace Scintilla {
+
+/**
+ * On the Mac, there is no WM_COMMAND or WM_NOTIFY message that can be sent
+ * back to the parent. Therefore, there must be a callback handler that acts
+ * like a Windows WndProc, where Scintilla can send notifications to. Use
+ * ScintillaCocoa::RegisterNotifyHandler() to register such a handler.
+ * Message format is:
+ * <br>
+ * WM_COMMAND: HIWORD (wParam) = notification code, LOWORD (wParam) = 0 (no control ID), lParam = ScintillaCocoa*
+ * <br>
+ * WM_NOTIFY: wParam = 0 (no control ID), lParam = ptr to SCNotification structure, with hwndFrom set to ScintillaCocoa*
+ */
+typedef void(*SciNotifyFunc) (intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam);
+
+/**
+ * Scintilla sends these two messages to the nofity handler. Please refer
+ * to the Windows API doc for details about the message format.
+ */
+#define WM_COMMAND 1001
+#define WM_NOTIFY 1002
+
+/**
+ * Main scintilla class, implemented for OS X (Cocoa).
+ */
+class ScintillaCocoa : public ScintillaBase
+{
+private:
+ TimerTarget* timerTarget;
+ NSEvent* lastMouseEvent;
+
+ SciNotifyFunc notifyProc;
+ intptr_t notifyObj;
+
+ bool capturedMouse;
+
+ // Private so ScintillaCocoa objects can not be copied
+ ScintillaCocoa(const ScintillaCocoa &) : ScintillaBase() {}
+ ScintillaCocoa &operator=(const ScintillaCocoa &) { return * this; }
+
+ bool GetPasteboardData(NSPasteboard* board, SelectionText* selectedText);
+ void SetPasteboardData(NSPasteboard* board, const SelectionText& selectedText);
+
+ int scrollSpeed;
+ int scrollTicks;
+protected:
+ NSView* ContentView();
+ PRectangle GetClientRectangle();
+ Point ConvertPoint(NSPoint point);
+
+ virtual void Initialise();
+ virtual void Finalise();
+public:
+ ScintillaCocoa(NSView* view);
+ virtual ~ScintillaCocoa();
+
+ void RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback);
+ sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ ScintillaView* TopContainer();
+
+ void SyncPaint(void* gc, PRectangle rc);
+ void Draw(NSRect rect, CGContextRef gc);
+
+ virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ void SetTicking(bool on);
+ bool SetIdle(bool on);
+ void SetMouseCapture(bool on);
+ bool HaveMouseCapture();
+ void SetVerticalScrollPos();
+ void SetHorizontalScrollPos();
+ bool ModifyScrollBars(int nMax, int nPage);
+ void Resize();
+ void DoScroll(float position, NSScrollerPart part, bool horizontal);
+
+ // Notifications for the owner.
+ void NotifyChange();
+ void NotifyFocus(bool focus);
+ void NotifyParent(SCNotification scn);
+ void NotifyURIDropped(const char *uri);
+
+ bool HasSelection();
+ bool CanUndo();
+ bool CanRedo();
+ virtual void CopyToClipboard(const SelectionText &selectedText);
+ virtual void Copy();
+ virtual bool CanPaste();
+ virtual void Paste();
+ virtual void Paste(bool rectangular);
+ virtual void CreateCallTipWindow(PRectangle rc);
+ virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+ virtual void ClaimSelection();
+
+ NSPoint GetCaretPosition();
+
+ static sptr_t DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ void TimerFired(NSTimer* timer);
+ void IdleTimerFired();
+ int InsertText(NSString* input);
+
+ bool KeyboardInput(NSEvent* event);
+ void MouseDown(NSEvent* event);
+ void MouseMove(NSEvent* event);
+ void MouseUp(NSEvent* event);
+ void MouseEntered(NSEvent* event);
+ void MouseExited(NSEvent* event);
+ void MouseWheel(NSEvent* event);
+
+ // Drag and drop
+ void StartDrag();
+ bool GetDragData(id <NSDraggingInfo> info, NSPasteboard &pasteBoard, SelectionText* selectedText);
+ NSDragOperation DraggingEntered(id <NSDraggingInfo> info);
+ NSDragOperation DraggingUpdated(id <NSDraggingInfo> info);
+ void DraggingExited(id <NSDraggingInfo> info);
+ bool PerformDragOperation(id <NSDraggingInfo> info);
+ void DragScroll();
+
+ // Promote some methods needed for NSResponder actions.
+ virtual void SelectAll();
+ void DeleteBackward();
+ virtual void Cut();
+ virtual void Undo();
+ virtual void Redo();
+
+ virtual NSMenu* CreateContextMenu(NSEvent* event);
+ void HandleCommand(NSInteger command);
+
+// virtual OSStatus ActiveStateChanged();
+//
+// virtual void CallTipClick();
+
+};
+
+
+}
+
+
diff --git a/scintilla/cocoa/ScintillaCocoa.mm b/scintilla/cocoa/ScintillaCocoa.mm
new file mode 100644
index 0000000..9cb14a4
--- /dev/null
+++ b/scintilla/cocoa/ScintillaCocoa.mm
@@ -0,0 +1,1471 @@
+
+/**
+ * Scintilla source code edit control
+ * ScintillaCocoa.mm - Cocoa subclass of ScintillaBase
+ *
+ * Written by Mike Lischke <mlischke@sun.com>
+ *
+ * Loosely based on ScintillaMacOSX.cxx.
+ * Copyright 2003 by Evan Jones <ejones@uwaterloo.ca>
+ * Based on ScintillaGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+ * The License.txt file describes the conditions under which this software may be distributed.
+ *
+ * Copyright (c) 2009, 2010 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#import <Carbon/Carbon.h> // Temporary
+
+#include "ScintillaView.h"
+#include "PlatCocoa.h"
+
+using namespace Scintilla;
+
+#ifndef WM_UNICHAR
+#define WM_UNICHAR 0x0109
+#endif
+
+NSString* ScintillaRecPboardType = @"com.scintilla.utf16-plain-text.rectangular";
+
+//--------------------------------------------------------------------------------------------------
+
+// Define keyboard shortcuts (equivalents) the Mac way.
+#define SCI_CMD ( SCI_ALT | SCI_CTRL)
+#define SCI_SCMD ( SCI_CMD | SCI_SHIFT)
+
+static const KeyToCommand macMapDefault[] =
+{
+ {SCK_DOWN, SCI_CMD, SCI_DOCUMENTEND},
+ {SCK_UP, SCI_CMD, SCI_DOCUMENTSTART},
+ {SCK_LEFT, SCI_CMD, SCI_VCHOME},
+ {SCK_LEFT, SCI_SCMD, SCI_VCHOMEEXTEND},
+ {SCK_RIGHT, SCI_CMD, SCI_LINEEND},
+ {SCK_RIGHT, SCI_SCMD, SCI_LINEENDEXTEND},
+ {SCK_DOWN, SCI_NORM, SCI_LINEDOWN},
+ {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
+ {SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN},
+ {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
+ {SCK_UP, SCI_NORM, SCI_LINEUP},
+ {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
+ {SCK_UP, SCI_CTRL, SCI_LINESCROLLUP},
+ {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
+ {'[', SCI_CTRL, SCI_PARAUP},
+ {'[', SCI_CSHIFT, SCI_PARAUPEXTEND},
+ {']', SCI_CTRL, SCI_PARADOWN},
+ {']', SCI_CSHIFT, SCI_PARADOWNEXTEND},
+ {SCK_LEFT, SCI_NORM, SCI_CHARLEFT},
+ {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
+ {SCK_LEFT, SCI_ALT, SCI_WORDLEFT},
+ {SCK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND},
+ {SCK_LEFT, SCI_ASHIFT, SCI_WORDLEFTEXTEND},
+ {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
+ {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
+ {SCK_RIGHT, SCI_ALT, SCI_WORDRIGHT},
+ {SCK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND},
+ {SCK_RIGHT, SCI_ASHIFT, SCI_WORDRIGHTEXTEND},
+ {'/', SCI_CTRL, SCI_WORDPARTLEFT},
+ {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
+ {'\\', SCI_CTRL, SCI_WORDPARTRIGHT},
+ {'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
+ {SCK_HOME, SCI_NORM, SCI_VCHOME},
+ {SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
+ {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
+ {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
+ {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY},
+ {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
+ {SCK_END, SCI_NORM, SCI_LINEEND},
+ {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
+ {SCK_END, SCI_CTRL, SCI_DOCUMENTEND},
+ {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
+ {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY},
+ {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
+ {SCK_PRIOR, SCI_NORM, SCI_PAGEUP},
+ {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
+ {SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
+ {SCK_NEXT, SCI_NORM, SCI_PAGEDOWN},
+ {SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
+ {SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
+ {SCK_DELETE, SCI_NORM, SCI_CLEAR},
+ {SCK_DELETE, SCI_SHIFT, SCI_CUT},
+ {SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
+ {SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT},
+ {SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
+ {SCK_INSERT, SCI_SHIFT, SCI_PASTE},
+ {SCK_INSERT, SCI_CTRL, SCI_COPY},
+ {SCK_ESCAPE, SCI_NORM, SCI_CANCEL},
+ {SCK_BACK, SCI_NORM, SCI_DELETEBACK},
+ {SCK_BACK, SCI_SHIFT, SCI_DELETEBACK},
+ {SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
+ {SCK_BACK, SCI_ALT, SCI_UNDO},
+ {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT},
+ {'z', SCI_CMD, SCI_UNDO},
+ {'z', SCI_SCMD, SCI_REDO},
+ {'x', SCI_CMD, SCI_CUT},
+ {'c', SCI_CMD, SCI_COPY},
+ {'v', SCI_CMD, SCI_PASTE},
+ {'a', SCI_CMD, SCI_SELECTALL},
+ {SCK_TAB, SCI_NORM, SCI_TAB},
+ {SCK_TAB, SCI_SHIFT, SCI_BACKTAB},
+ {SCK_RETURN, SCI_NORM, SCI_NEWLINE},
+ {SCK_RETURN, SCI_SHIFT, SCI_NEWLINE},
+ {SCK_ADD, SCI_CMD, SCI_ZOOMIN},
+ {SCK_SUBTRACT, SCI_CMD, SCI_ZOOMOUT},
+ {SCK_DIVIDE, SCI_CMD, SCI_SETZOOM},
+ {'l', SCI_CMD, SCI_LINECUT},
+ {'l', SCI_CSHIFT, SCI_LINEDELETE},
+ {'t', SCI_CSHIFT, SCI_LINECOPY},
+ {'t', SCI_CTRL, SCI_LINETRANSPOSE},
+ {'d', SCI_CTRL, SCI_SELECTIONDUPLICATE},
+ {'u', SCI_CTRL, SCI_LOWERCASE},
+ {'u', SCI_CSHIFT, SCI_UPPERCASE},
+ {0, 0, 0},
+};
+
+//--------------------------------------------------------------------------------------------------
+
+@implementation TimerTarget
+
+- (id) init: (void*) target
+{
+ [super init];
+ if (self != nil)
+ {
+ mTarget = target;
+
+ // Get the default notification queue for the thread which created the instance (usually the
+ // main thread). We need that later for idle event processing.
+ NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+ notificationQueue = [[NSNotificationQueue alloc] initWithNotificationCenter: center];
+ [center addObserver: self selector: @selector(idleTriggered:) name: @"Idle" object: nil];
+ }
+ return self;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) dealloc
+{
+ [notificationQueue release];
+ [super dealloc];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Method called by a timer installed by ScintillaCocoa. This two step approach is needed because
+ * a native Obj-C class is required as target for the timer.
+ */
+- (void) timerFired: (NSTimer*) timer
+{
+ reinterpret_cast<ScintillaCocoa*>(mTarget)->TimerFired(timer);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Another timer callback for the idle timer.
+ */
+- (void) idleTimerFired: (NSTimer*) timer
+{
+ // Idle timer event.
+ // Post a new idle notification, which gets executed when the run loop is idle.
+ // Since we are coalescing on name and sender there will always be only one actual notification
+ // even for multiple requests.
+ NSNotification *notification = [NSNotification notificationWithName: @"Idle" object: self];
+ [notificationQueue enqueueNotification: notification
+ postingStyle: NSPostWhenIdle
+ coalesceMask: (NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender)
+ forModes: nil];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Another step for idle events. The timer (for idle events) simply requests a notification on
+ * idle time. Only when this notification is send we actually call back the editor.
+ */
+- (void) idleTriggered: (NSNotification*) notification
+{
+ reinterpret_cast<ScintillaCocoa*>(mTarget)->IdleTimerFired();
+}
+
+@end
+
+//----------------- ScintillaCocoa -----------------------------------------------------------------
+
+ScintillaCocoa::ScintillaCocoa(NSView* view)
+{
+ wMain= [view retain];
+ timerTarget = [[[TimerTarget alloc] init: this] retain];
+ Initialise();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+ScintillaCocoa::~ScintillaCocoa()
+{
+ SetTicking(false);
+ [timerTarget release];
+ NSView* container = ContentView();
+ [container release];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Core initialization of the control. Everything that needs to be set up happens here.
+ */
+void ScintillaCocoa::Initialise()
+{
+ notifyObj = NULL;
+ notifyProc = NULL;
+
+ capturedMouse = false;
+
+ // Tell Scintilla not to buffer: Quartz buffers drawing for us.
+ WndProc(SCI_SETBUFFEREDDRAW, 0, 0);
+
+ // We are working with Unicode exclusively.
+ WndProc(SCI_SETCODEPAGE, SC_CP_UTF8, 0);
+
+ // Add Mac specific key bindings.
+ for (int i = 0; macMapDefault[i].key; i++)
+ kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg);
+
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * We need some clean up. Do it here.
+ */
+void ScintillaCocoa::Finalise()
+{
+ SetTicking(false);
+ ScintillaBase::Finalise();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper function to get the outer container which represents the Scintilla editor on application side.
+ */
+ScintillaView* ScintillaCocoa::TopContainer()
+{
+ NSView* container = static_cast<NSView*>(wMain.GetID());
+ return static_cast<ScintillaView*>([container superview]);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper function to get the inner container which represents the actual "canvas" we work with.
+ */
+NSView* ScintillaCocoa::ContentView()
+{
+ return static_cast<NSView*>(wMain.GetID());
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Instead of returning the size of the inner view we have to return the visible part of it
+ * in order to make scrolling working properly.
+ */
+PRectangle ScintillaCocoa::GetClientRectangle()
+{
+ NSView* host = ContentView();
+ NSSize size = [host frame].size;
+ return PRectangle(0, 0, size.width, size.height);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Converts the given point from base coordinates to local coordinates and at the same time into
+ * a native Point structure. Base coordinates are used for the top window used in the view hierarchy.
+ */
+Scintilla::Point ScintillaCocoa::ConvertPoint(NSPoint point)
+{
+ NSView* container = ContentView();
+ NSPoint result = [container convertPoint: point fromView: nil];
+
+ return Point(result.x, result.y);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * A function to directly execute code that would usually go the long way via window messages.
+ * However this is a Windows metapher and not used here, hence we just call our fake
+ * window proc. The given parameters directly reflect the message parameters used on Windows.
+ *
+ * @param sciThis The target which is to be called.
+ * @param iMessage A code that indicates which message was sent.
+ * @param wParam One of the two free parameters for the message. Traditionally a word sized parameter
+ * (hence the w prefix).
+ * @param lParam The other of the two free parameters. A signed long.
+ */
+sptr_t ScintillaCocoa::DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam,
+ sptr_t lParam)
+{
+ return sciThis->WndProc(iMessage, wParam, lParam);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * This method is very similar to DirectFunction. On Windows it sends a message (not in the Obj-C sense)
+ * to the target window. Here we simply call our fake window proc.
+ */
+sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+{
+ ScintillaView *control = reinterpret_cast<ScintillaView*>(sci);
+ ScintillaCocoa* scintilla = [control backend];
+ return scintilla->WndProc(iMessage, wParam, lParam);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * That's our fake window procedure. On Windows each window has a dedicated procedure to handle
+ * commands (also used to synchronize UI and background threads), which is not the case in Cocoa.
+ *
+ * Messages handled here are almost solely for special commands of the backend. Everything which
+ * would be sytem messages on Windows (e.g. for key down, mouse move etc.) are handled by
+ * directly calling appropriate handlers.
+ */
+sptr_t ScintillaCocoa::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+{
+ switch (iMessage)
+ {
+ case SCI_GETDIRECTFUNCTION:
+ return reinterpret_cast<sptr_t>(DirectFunction);
+
+ case SCI_GETDIRECTPOINTER:
+ return reinterpret_cast<sptr_t>(this);
+
+ case SCI_GRABFOCUS:
+ // TODO: implement it
+ break;
+
+ case WM_UNICHAR:
+ // Special case not used normally. Characters passed in this way will be inserted
+ // regardless of their value or modifier states. That means no command interpretation is
+ // performed.
+ if (IsUnicodeMode())
+ {
+ NSString* input = [[NSString stringWithCharacters: (const unichar*) &wParam length: 1] autorelease];
+ const char* utf8 = [input UTF8String];
+ AddCharUTF((char*) utf8, strlen(utf8), false);
+ return 1;
+ }
+ return 0;
+
+ default:
+ unsigned int r = ScintillaBase::WndProc(iMessage, wParam, lParam);
+
+ return r;
+ }
+ return 0l;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * In Windows lingo this is the handler which handles anything that wasn't handled in the normal
+ * window proc which would usually send the message back to generic window proc that Windows uses.
+ */
+sptr_t ScintillaCocoa::DefWndProc(unsigned int, uptr_t, sptr_t)
+{
+ return 0;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Enables or disables a timer that can trigger background processing at a regular interval, like
+ * drag scrolling or caret blinking.
+ */
+void ScintillaCocoa::SetTicking(bool on)
+{
+ if (timer.ticking != on)
+ {
+ timer.ticking = on;
+ if (timer.ticking)
+ {
+ // Scintilla ticks = milliseconds
+ // Using userInfo as flag to distinct between tick and idle timer.
+ NSTimer* tickTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0
+ target: timerTarget
+ selector: @selector(timerFired:)
+ userInfo: nil
+ repeats: YES];
+ timer.tickerID = reinterpret_cast<TickerID>(tickTimer);
+ }
+ else
+ if (timer.tickerID != NULL)
+ {
+ [reinterpret_cast<NSTimer*>(timer.tickerID) invalidate];
+ timer.tickerID = 0;
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::SetIdle(bool on)
+{
+ if (idler.state != on)
+ {
+ idler.state = on;
+ if (idler.state)
+ {
+ // Scintilla ticks = milliseconds
+ NSTimer* idleTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0
+ target: timerTarget
+ selector: @selector(idleTimerFired:)
+ userInfo: nil
+ repeats: YES];
+ idler.idlerID = reinterpret_cast<IdlerID>(idleTimer);
+ }
+ else
+ if (idler.idlerID != NULL)
+ {
+ [reinterpret_cast<NSTimer*>(idler.idlerID) invalidate];
+ idler.idlerID = 0;
+ }
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::CopyToClipboard(const SelectionText &selectedText)
+{
+ SetPasteboardData([NSPasteboard generalPasteboard], selectedText);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::Copy()
+{
+ if (!sel.Empty())
+ {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ CopyToClipboard(selectedText);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::CanPaste()
+{
+ if (!Editor::CanPaste())
+ return false;
+
+ return GetPasteboardData([NSPasteboard generalPasteboard], NULL);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::Paste()
+{
+ Paste(false);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Pastes data from the paste board into the editor.
+ */
+void ScintillaCocoa::Paste(bool forceRectangular)
+{
+ SelectionText selectedText;
+ bool ok = GetPasteboardData([NSPasteboard generalPasteboard], &selectedText);
+ if (forceRectangular)
+ selectedText.rectangular = forceRectangular;
+
+ if (!ok || !selectedText.s)
+ // No data or no flavor we support.
+ return;
+
+ pdoc->BeginUndoAction();
+ ClearSelection();
+ if (selectedText.rectangular)
+ {
+ SelectionPosition selStart = sel.RangeMain().Start();
+ PasteRectangular(selStart, selectedText.s, selectedText.len);
+ }
+ else
+ if (pdoc->InsertString(sel.RangeMain().caret.Position(), selectedText.s, selectedText.len))
+ SetEmptySelection(sel.RangeMain().caret.Position() + selectedText.len);
+
+ pdoc->EndUndoAction();
+
+ Redraw();
+ EnsureCaretVisible();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::CreateCallTipWindow(PRectangle rc)
+{
+/*
+ // create a calltip window
+ if (!ct.wCallTip.Created()) {
+ WindowClass windowClass = kHelpWindowClass;
+ WindowAttributes attributes = kWindowNoAttributes;
+ Rect contentBounds;
+ WindowRef outWindow;
+
+ // convert PRectangle to Rect
+ // this adjustment gets the calltip window placed in the correct location relative
+ // to our editor window
+ Rect bounds;
+ OSStatus err;
+ err = GetWindowBounds( this->GetOwner(), kWindowGlobalPortRgn, &bounds );
+ assert( err == noErr );
+ contentBounds.top = rc.top + bounds.top;
+ contentBounds.bottom = rc.bottom + bounds.top;
+ contentBounds.right = rc.right + bounds.left;
+ contentBounds.left = rc.left + bounds.left;
+
+ // create our calltip hiview
+ HIViewRef ctw = scintilla_calltip_new();
+ CallTip* objectPtr = &ct;
+ ScintillaCocoa* sciThis = this;
+ SetControlProperty( ctw, scintillaMacOSType, 0, sizeof( this ), &sciThis );
+ SetControlProperty( ctw, scintillaCallTipType, 0, sizeof( objectPtr ), &objectPtr );
+
+ CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow);
+ ControlRef root;
+ CreateRootControl(outWindow, &root);
+
+ HIViewRef hiroot = HIViewGetRoot (outWindow);
+ HIViewAddSubview(hiroot, ctw);
+
+ HIRect boundsRect;
+ HIViewGetFrame(hiroot, &boundsRect);
+ HIViewSetFrame( ctw, &boundsRect );
+
+ // bind the size of the calltip to the size of it's container window
+ HILayoutInfo layout = {
+ kHILayoutInfoVersionZero,
+ {
+ { NULL, kHILayoutBindTop, 0 },
+ { NULL, kHILayoutBindLeft, 0 },
+ { NULL, kHILayoutBindBottom, 0 },
+ { NULL, kHILayoutBindRight, 0 }
+ },
+ {
+ { NULL, kHILayoutScaleAbsolute, 0 },
+ { NULL, kHILayoutScaleAbsolute, 0 }
+
+ },
+ {
+ { NULL, kHILayoutPositionTop, 0 },
+ { NULL, kHILayoutPositionLeft, 0 }
+ }
+ };
+ HIViewSetLayoutInfo(ctw, &layout);
+
+ ct.wCallTip = root;
+ ct.wDraw = ctw;
+ ct.wCallTip.SetWindow(outWindow);
+ HIViewSetVisible(ctw,true);
+
+ }
+*/
+}
+
+
+void ScintillaCocoa::AddToPopUp(const char *label, int cmd, bool enabled)
+{
+ NSMenuItem* item;
+ ScintillaContextMenu *menu= reinterpret_cast<ScintillaContextMenu*>(popup.GetID());
+ [menu setOwner: this];
+ [menu setAutoenablesItems: NO];
+
+ if (cmd == 0)
+ item = [NSMenuItem separatorItem];
+ else
+ item = [[NSMenuItem alloc] init];
+
+ [item setTarget: menu];
+ [item setAction: @selector(handleCommand:)];
+ [item setTag: cmd];
+ [item setTitle: [NSString stringWithUTF8String: label]];
+ [item setEnabled: enabled];
+
+ [menu addItem: item];
+}
+
+// -------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::ClaimSelection()
+{
+ // Mac OS X does not have a primary selection.
+}
+
+// -------------------------------------------------------------------------------------------------
+
+/**
+ * Returns the current caret position (which is tracked as an offset into the entire text string)
+ * as a row:column pair. The result is zero-based.
+ */
+NSPoint ScintillaCocoa::GetCaretPosition()
+{
+ NSPoint result;
+
+ result.y = pdoc->LineFromPosition(sel.RangeMain().caret.Position());
+ result.x = sel.RangeMain().caret.Position() - pdoc->LineStart(result.y);
+ return result;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+#pragma segment Drag
+
+/**
+ * Triggered by the tick timer on a regular basis to scroll the content during a drag operation.
+ */
+void ScintillaCocoa::DragScroll()
+{
+ if (!posDrag.IsValid())
+ {
+ scrollSpeed = 1;
+ scrollTicks = 2000;
+ return;
+ }
+
+ // TODO: does not work for wrapped lines, fix it.
+ int line = pdoc->LineFromPosition(posDrag.Position());
+ int currentVisibleLine = cs.DisplayFromDoc(line);
+ int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen(), cs.LinesDisplayed()) - 2;
+
+ if (currentVisibleLine <= topLine && topLine > 0)
+ ScrollTo(topLine - scrollSpeed);
+ else
+ if (currentVisibleLine >= lastVisibleLine)
+ ScrollTo(topLine + scrollSpeed);
+ else
+ {
+ scrollSpeed = 1;
+ scrollTicks = 2000;
+ return;
+ }
+
+ // TODO: also handle horizontal scrolling.
+
+ if (scrollSpeed == 1)
+ {
+ scrollTicks -= timer.tickSize;
+ if (scrollTicks <= 0)
+ {
+ scrollSpeed = 5;
+ scrollTicks = 2000;
+ }
+ }
+
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called when a drag operation was initiated from within Scintilla.
+ */
+void ScintillaCocoa::StartDrag()
+{
+ if (sel.Empty())
+ return;
+
+ // Put the data to be dragged on the drag pasteboard.
+ SelectionText selectedText;
+ NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName: NSDragPboard];
+ CopySelectionRange(&selectedText);
+ SetPasteboardData(pasteboard, selectedText);
+
+ // Prepare drag image.
+ PRectangle localRectangle = RectangleFromRange(sel.RangeMain().Start().Position(), sel.RangeMain().End().Position());
+ NSRect selectionRectangle = PRectangleToNSRect(localRectangle);
+
+ NSView* content = ContentView();
+
+#if 0 // TODO: fix initialization of the drag image with CGImageRef.
+ // To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface.
+ SurfaceImpl *sw = new SurfaceImpl();
+ SurfaceImpl *pixmap = NULL;
+
+ bool lastHideSelection = hideSelection;
+ hideSelection = true;
+ if (sw)
+ {
+ pixmap = new SurfaceImpl();
+ if (pixmap)
+ {
+ PRectangle client = GetClientRectangle();
+ PRectangle imageRect = NSRectToPRectangle(selectionRectangle);
+ paintState = painting;
+ //sw->InitPixMap(client.Width(), client.Height(), NULL, NULL);
+ sw->InitPixMap(imageRect.Width(), imageRect.Height(), NULL, NULL);
+ paintingAllText = true;
+ Paint(sw, imageRect);
+ paintState = notPainting;
+
+ pixmap->InitPixMap(imageRect.Width(), imageRect.Height(), NULL, NULL);
+
+ CGContextRef gc = pixmap->GetContext();
+
+ // To make Paint() work on a bitmap, we have to flip our coordinates and translate the origin
+ CGContextTranslateCTM(gc, 0, imageRect.Height());
+ CGContextScaleCTM(gc, 1.0, -1.0);
+
+ pixmap->CopyImageRectangle(*sw, imageRect, PRectangle(0, 0, imageRect.Width(), imageRect.Height()));
+ // XXX TODO: overwrite any part of the image that is not part of the
+ // selection to make it transparent. right now we just use
+ // the full rectangle which may include non-selected text.
+ }
+ sw->Release();
+ delete sw;
+ }
+ hideSelection = lastHideSelection;
+
+ NSBitmapImageRep* bitmap = NULL;
+ if (pixmap)
+ {
+ bitmap = [[[NSBitmapImageRep alloc] initWithCGImage: pixmap->GetImage()] autorelease];
+ pixmap->Release();
+ delete pixmap;
+ }
+#else
+
+ // Poor man's drag image: take a snapshot of the content view.
+ [content lockFocus];
+ NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: selectionRectangle] autorelease];
+ [bitmap setColorSpaceName: NSDeviceRGBColorSpace];
+ [content unlockFocus];
+
+#endif
+
+ NSImage* image = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease];
+ [image addRepresentation: bitmap];
+
+ NSImage* dragImage = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease];
+ [dragImage setBackgroundColor: [NSColor clearColor]];
+ [dragImage lockFocus];
+ [image dissolveToPoint: NSMakePoint(0.0, 0.0) fraction: 0.5];
+ [dragImage unlockFocus];
+
+ NSPoint startPoint;
+ startPoint.x = selectionRectangle.origin.x;
+ startPoint.y = selectionRectangle.origin.y + selectionRectangle.size.height;
+ [content dragImage: dragImage
+ at: startPoint
+ offset: NSZeroSize
+ event: lastMouseEvent // Set in MouseMove.
+ pasteboard: pasteboard
+ source: content
+ slideBack: YES];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called when a drag operation reaches the control which was initiated outside.
+ */
+NSDragOperation ScintillaCocoa::DraggingEntered(id <NSDraggingInfo> info)
+{
+ inDragDrop = ddDragging;
+ return DraggingUpdated(info);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called frequently during a drag operation if we are the target. Keep telling the caller
+ * what drag operation we accept and update the drop caret position to indicate the
+ * potential insertion point of the dragged data.
+ */
+NSDragOperation ScintillaCocoa::DraggingUpdated(id <NSDraggingInfo> info)
+{
+ // Convert the drag location from window coordinates to view coordinates and
+ // from there to a text position to finally set the drag position.
+ Point location = ConvertPoint([info draggingLocation]);
+ SetDragPosition(SPositionFromLocation(location));
+
+ NSDragOperation sourceDragMask = [info draggingSourceOperationMask];
+ if (sourceDragMask == NSDragOperationNone)
+ return sourceDragMask;
+
+ NSPasteboard* pasteboard = [info draggingPasteboard];
+
+ // Return what type of operation we will perform. Prefer move over copy.
+ if ([[pasteboard types] containsObject: NSStringPboardType] ||
+ [[pasteboard types] containsObject: ScintillaRecPboardType])
+ return (sourceDragMask & NSDragOperationMove) ? NSDragOperationMove : NSDragOperationCopy;
+
+ if ([[pasteboard types] containsObject: NSFilenamesPboardType])
+ return (sourceDragMask & NSDragOperationGeneric);
+ return NSDragOperationNone;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Resets the current drag position as we are no longer the drag target.
+ */
+void ScintillaCocoa::DraggingExited(id <NSDraggingInfo> info)
+{
+ SetDragPosition(SelectionPosition(invalidPosition));
+ inDragDrop = ddNone;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Here is where the real work is done. Insert the text from the pasteboard.
+ */
+bool ScintillaCocoa::PerformDragOperation(id <NSDraggingInfo> info)
+{
+ NSPasteboard* pasteboard = [info draggingPasteboard];
+
+ if ([[pasteboard types] containsObject: NSFilenamesPboardType])
+ {
+ NSArray* files = [pasteboard propertyListForType: NSFilenamesPboardType];
+ for (NSString* uri in files)
+ NotifyURIDropped([uri UTF8String]);
+ }
+ else
+ {
+ SelectionText text;
+ GetPasteboardData(pasteboard, &text);
+
+ if (text.len > 0)
+ {
+ NSDragOperation operation = [info draggingSourceOperationMask];
+ bool moving = (operation & NSDragOperationMove) != 0;
+
+ DropAt(posDrag, text.s, moving, text.rectangular);
+ };
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::SetPasteboardData(NSPasteboard* board, const SelectionText &selectedText)
+{
+ if (selectedText.len == 0)
+ return;
+
+ NSString *string;
+ string = [NSString stringWithUTF8String: selectedText.s];
+
+ [board declareTypes:[NSArray arrayWithObjects:
+ NSStringPboardType,
+ selectedText.rectangular ? ScintillaRecPboardType : nil,
+ nil] owner:nil];
+
+ if (selectedText.rectangular)
+ {
+ // This is specific to scintilla, allows us to drag rectangular selections around the document.
+ [board setString: string forType: ScintillaRecPboardType];
+ }
+
+ [board setString: string forType: NSStringPboardType];
+
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper method to retrieve the best fitting alternative from the general pasteboard.
+ */
+bool ScintillaCocoa::GetPasteboardData(NSPasteboard* board, SelectionText* selectedText)
+{
+ NSArray* supportedTypes = [NSArray arrayWithObjects: ScintillaRecPboardType,
+ NSStringPboardType,
+ nil];
+ NSString *bestType = [board availableTypeFromArray: supportedTypes];
+ NSString* data = [board stringForType: bestType];
+
+ if (data != nil)
+ {
+ if (selectedText != nil)
+ {
+ char* text = (char*) [data UTF8String];
+ bool rectangular = bestType == ScintillaRecPboardType;
+ selectedText->Copy(text, strlen(text) + 1, SC_CP_UTF8, SC_CHARSET_DEFAULT , rectangular, false);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::SetMouseCapture(bool on)
+{
+ capturedMouse = on;
+ /*
+ if (mouseDownCaptures)
+ {
+ if (capturedMouse)
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ else
+ // Reset to normal. Actual image will be set on mouse move.
+ WndProc(SCI_SETCURSOR, (unsigned int) SC_CURSORNORMAL, 0);
+ }
+ */
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::HaveMouseCapture()
+{
+ return capturedMouse;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Synchronously paint a rectangle of the window.
+ */
+void ScintillaCocoa::SyncPaint(void* gc, PRectangle rc)
+{
+ paintState = painting;
+ rcPaint = rc;
+ PRectangle rcText = GetTextRectangle();
+ paintingAllText = rcPaint.Contains(rcText);
+ Surface *sw = Surface::Allocate();
+ if (sw)
+ {
+ sw->Init(gc, wMain.GetID());
+ Paint(sw, rc);
+ if (paintState == paintAbandoned)
+ {
+ // Do a full paint.
+ rcPaint = GetClientRectangle();
+ paintState = painting;
+ paintingAllText = true;
+ Paint(sw, rcPaint);
+ }
+ sw->Release();
+ delete sw;
+ }
+ paintState = notPainting;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Modfies the vertical scroll position to make the current top line show up as such.
+ */
+void ScintillaCocoa::SetVerticalScrollPos()
+{
+ ScintillaView* topContainer = TopContainer();
+
+ // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area
+ // does *not* belong to the scroll range.
+ float relativePosition = (float) topLine / MaxScrollPos();
+ [topContainer setVerticalScrollPosition: relativePosition];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::SetHorizontalScrollPos()
+{
+ ScintillaView* topContainer = TopContainer();
+ PRectangle textRect = GetTextRectangle();
+
+ // Convert absolute coordinate into the range [0..1]. Keep in mind that the visible area
+ // does *not* belong to the scroll range.
+ float relativePosition = (float) xOffset / (scrollWidth - textRect.Width());
+ [topContainer setHorizontalScrollPosition: relativePosition];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to adjust both scrollers to reflect the current scroll range and position in the editor.
+ *
+ * @param nMax Number of lines in the editor.
+ * @param nPage Number of lines per scroll page.
+ * @return True if there was a change, otherwise false.
+ */
+bool ScintillaCocoa::ModifyScrollBars(int nMax, int nPage)
+{
+ // Input values are given in lines, not pixels, so we have to convert.
+ int lineHeight = WndProc(SCI_TEXTHEIGHT, 0, 0);
+ PRectangle bounds = GetTextRectangle();
+ ScintillaView* topContainer = TopContainer();
+
+ // Set page size to the same value as the scroll range to hide the scrollbar.
+ int scrollRange = lineHeight * (nMax + 1); // +1 because the caller subtracted one.
+ int pageSize;
+ if (verticalScrollBarVisible)
+ pageSize = bounds.Height();
+ else
+ pageSize = scrollRange;
+ bool verticalChange = [topContainer setVerticalScrollRange: scrollRange page: pageSize];
+
+ scrollRange = scrollWidth;
+ if (horizontalScrollBarVisible)
+ pageSize = bounds.Width();
+ else
+ pageSize = scrollRange;
+ bool horizontalChange = [topContainer setHorizontalScrollRange: scrollRange page: pageSize];
+
+ return verticalChange || horizontalChange;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::Resize()
+{
+ ChangeSize();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the frontend control when the user manipulates one of the scrollers.
+ *
+ * @param position The relative position of the scroller in the range of [0..1].
+ * @param part Specifies which part was clicked on by the user, so we can handle thumb tracking
+ * as well as page and line scrolling.
+ * @param horizontal True if the horizontal scroller was hit, otherwise false.
+ */
+void ScintillaCocoa::DoScroll(float position, NSScrollerPart part, bool horizontal)
+{
+ // If the given scroller part is not the knob (or knob slot) then the given position is not yet
+ // current and we have to update it.
+ if (horizontal)
+ {
+ // Horizontal offset is given in pixels.
+ PRectangle textRect = GetTextRectangle();
+ int offset = (int) (position * (scrollWidth - textRect.Width()));
+ int smallChange = (int) (textRect.Width() / 30);
+ if (smallChange < 5)
+ smallChange = 5;
+ switch (part)
+ {
+ case NSScrollerDecrementLine:
+ offset -= smallChange;
+ break;
+ case NSScrollerDecrementPage:
+ offset -= textRect.Width();
+ break;
+ case NSScrollerIncrementLine:
+ offset += smallChange;
+ break;
+ case NSScrollerIncrementPage:
+ offset += textRect.Width();
+ break;
+ };
+ HorizontalScrollTo(offset);
+ }
+ else
+ {
+ // VerticalScrolling is by line.
+ int topLine = (int) (position * MaxScrollPos());
+ int page = LinesOnScreen();
+ switch (part)
+ {
+ case NSScrollerDecrementLine:
+ topLine--;
+ break;
+ case NSScrollerDecrementPage:
+ topLine -= page;
+ break;
+ case NSScrollerIncrementLine:
+ topLine++;
+ break;
+ case NSScrollerIncrementPage:
+ topLine += page;
+ break;
+ };
+ ScrollTo(topLine, true);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to register a callback function for a given window. This is used to emulate the way
+ * Windows notfies other controls (mainly up in the view hierarchy) about certain events.
+ *
+ * @param windowid A handle to a window. That value is generic and can be anything. It is passed
+ * through to the callback.
+ * @param callback The callback function to be used for future notifications. If NULL then no
+ * notifications will be sent anymore.
+ */
+void ScintillaCocoa::RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback)
+{
+ notifyObj = windowid;
+ notifyProc = callback;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::NotifyChange()
+{
+ if (notifyProc != NULL)
+ notifyProc(notifyObj, WM_COMMAND, (uintptr_t) (SCEN_CHANGE << 16), (uintptr_t) this);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::NotifyFocus(bool focus)
+{
+ if (notifyProc != NULL)
+ notifyProc(notifyObj, WM_COMMAND, (uintptr_t) ((focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS) << 16), (uintptr_t) this);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to send a notification (as WM_NOTIFY call) to the procedure, which has been set by the call
+ * to RegisterNotifyCallback (so it is not necessarily the parent window).
+ *
+ * @param scn The notification to send.
+ */
+void ScintillaCocoa::NotifyParent(SCNotification scn)
+{
+ if (notifyProc != NULL)
+ {
+ scn.nmhdr.hwndFrom = (void*) this;
+ scn.nmhdr.idFrom = (unsigned int) wMain.GetID();
+ notifyProc(notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &scn);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::NotifyURIDropped(const char *uri)
+{
+ SCNotification scn;
+ scn.nmhdr.code = SCN_URIDROPPED;
+ scn.text = uri;
+
+ NotifyParent(scn);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::HasSelection()
+{
+ return !sel.Empty();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::CanUndo()
+{
+ return pdoc->CanUndo();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+bool ScintillaCocoa::CanRedo()
+{
+ return pdoc->CanRedo();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::TimerFired(NSTimer* timer)
+{
+ Tick();
+ DragScroll();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::IdleTimerFired()
+{
+ bool more = Idle();
+ if (!more)
+ SetIdle(false);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Main entry point for drawing the control.
+ *
+ * @param rect The area to paint, given in the sender's coordinate.
+ * @param gc The context we can use to paint.
+ */
+void ScintillaCocoa::Draw(NSRect rect, CGContextRef gc)
+{
+ SyncPaint(gc, NSRectToPRectangle(rect));
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper function to translate OS X key codes to Scintilla key codes.
+ */
+static inline UniChar KeyTranslate(UniChar unicodeChar)
+{
+ switch (unicodeChar)
+ {
+ case NSDownArrowFunctionKey:
+ return SCK_DOWN;
+ case NSUpArrowFunctionKey:
+ return SCK_UP;
+ case NSLeftArrowFunctionKey:
+ return SCK_LEFT;
+ case NSRightArrowFunctionKey:
+ return SCK_RIGHT;
+ case NSHomeFunctionKey:
+ return SCK_HOME;
+ case NSEndFunctionKey:
+ return SCK_END;
+ case NSPageUpFunctionKey:
+ return SCK_PRIOR;
+ case NSPageDownFunctionKey:
+ return SCK_NEXT;
+ case NSDeleteFunctionKey:
+ return SCK_DELETE;
+ case NSInsertFunctionKey:
+ return SCK_INSERT;
+ case '\n':
+ case 3:
+ return SCK_RETURN;
+ case 27:
+ return SCK_ESCAPE;
+ case 127:
+ return SCK_BACK;
+ case '\t':
+ case 25: // Shift tab, return to unmodified tab and handle that via modifiers.
+ return SCK_TAB;
+ default:
+ return unicodeChar;
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Main keyboard input handling method. It is called for any key down event, including function keys,
+ * numeric keypad input and whatnot.
+ *
+ * @param event The event instance associated with the key down event.
+ * @return True if the input was handled, false otherwise.
+ */
+bool ScintillaCocoa::KeyboardInput(NSEvent* event)
+{
+ // For now filter out function keys.
+ NSUInteger modifiers = [event modifierFlags];
+
+ NSString* input = [event characters];
+
+ bool control = (modifiers & NSControlKeyMask) != 0;
+ bool shift = (modifiers & NSShiftKeyMask) != 0;
+ bool command = (modifiers & NSCommandKeyMask) != 0;
+ bool alt = (modifiers & NSAlternateKeyMask) != 0;
+
+ bool handled = false;
+
+ // Handle each entry individually. Usually we only have one entry anway.
+ for (int i = 0; i < input.length; i++)
+ {
+ const UniChar originalKey = [input characterAtIndex: i];
+ UniChar key = KeyTranslate(originalKey);
+
+ bool consumed = false; // Consumed as command?
+
+ // Signal command as control + alt. This leaves us without command + control and command + alt
+ // but that's what we get when we have a modifier key more than other platforms.
+ if (KeyDown(key, shift, control || command, alt || command, &consumed))
+ handled = true;
+ if (consumed)
+ handled = true;
+ }
+
+ return handled;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to insert already processed text provided by the Cocoa text input system.
+ */
+int ScintillaCocoa::InsertText(NSString* input)
+{
+ const char* utf8 = [input UTF8String];
+ AddCharUTF((char*) utf8, strlen(utf8), false);
+ return true;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the owning view when the mouse pointer enters the control.
+ */
+void ScintillaCocoa::MouseEntered(NSEvent* event)
+{
+ if (!HaveMouseCapture())
+ {
+ WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0);
+
+ // Mouse location is given in screen coordinates and might also be outside of our bounds.
+ Point location = ConvertPoint([event locationInWindow]);
+ ButtonMove(location);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::MouseExited(NSEvent* event)
+{
+ // Nothing to do here.
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::MouseDown(NSEvent* event)
+{
+ Point location = ConvertPoint([event locationInWindow]);
+ NSTimeInterval time = [event timestamp];
+ bool command = ([event modifierFlags] & NSCommandKeyMask) != 0;
+ bool shift = ([event modifierFlags] & NSShiftKeyMask) != 0;
+ bool control = ([event modifierFlags] & NSControlKeyMask) != 0;
+
+ ButtonDown(Point(location.x, location.y), (int) (time * 1000), shift, control, command);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::MouseMove(NSEvent* event)
+{
+ lastMouseEvent = event;
+
+ ButtonMove(ConvertPoint([event locationInWindow]));
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::MouseUp(NSEvent* event)
+{
+ NSTimeInterval time = [event timestamp];
+ bool control = ([event modifierFlags] & NSControlKeyMask) != 0;
+
+ ButtonUp(ConvertPoint([event locationInWindow]), (int) (time * 1000), control);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void ScintillaCocoa::MouseWheel(NSEvent* event)
+{
+ bool command = ([event modifierFlags] & NSCommandKeyMask) != 0;
+ bool shift = ([event modifierFlags] & NSShiftKeyMask) != 0;
+ int delta;
+ if (shift)
+ delta = 10 * [event deltaX]; // Arbitrary scale factor.
+ else
+ {
+ // In order to make scrolling with larger offset smoother we scroll less lines the larger the
+ // delta value is.
+ if ([event deltaY] < 0)
+ delta = -(int) sqrt(-10.0 * [event deltaY]);
+ else
+ delta = (int) sqrt(10.0 * [event deltaY]);
+ }
+
+ if (command)
+ {
+ // Zoom! We play with the font sizes in the styles.
+ // Number of steps/line is ignored, we just care if sizing up or down.
+ if (delta > 0)
+ KeyCommand(SCI_ZOOMIN);
+ else
+ KeyCommand(SCI_ZOOMOUT);
+ }
+ else
+ if (shift)
+ HorizontalScrollTo(xOffset - delta);
+ else
+ ScrollTo(topLine - delta, true);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+// Helper methods for NSResponder actions.
+
+void ScintillaCocoa::SelectAll()
+{
+ Editor::SelectAll();
+}
+
+void ScintillaCocoa::DeleteBackward()
+{
+ KeyDown(SCK_BACK, false, false, false, nil);
+}
+
+void ScintillaCocoa::Cut()
+{
+ Editor::Cut();
+}
+
+void ScintillaCocoa::Undo()
+{
+ Editor::Undo();
+}
+
+void ScintillaCocoa::Redo()
+{
+ Editor::Undo();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Creates and returns a popup menu, which is then displayed by the Cocoa framework.
+ */
+NSMenu* ScintillaCocoa::CreateContextMenu(NSEvent* event)
+{
+ // Call ScintillaBase to create the context menu.
+ ContextMenu(Point(0, 0));
+
+ return reinterpret_cast<NSMenu*>(popup.GetID());
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * An intermediate function to forward context menu commands from the menu action handler to
+ * scintilla.
+ */
+void ScintillaCocoa::HandleCommand(NSInteger command)
+{
+ Command(command);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+//OSStatus ScintillaCocoa::ActiveStateChanged()
+//{
+// // If the window is being deactivated, lose the focus and turn off the ticking
+// if ( ! this->IsActive() ) {
+// DropCaret();
+// //SetFocusState( false );
+// SetTicking( false );
+// } else {
+// ShowCaretAtCurrentPosition();
+// }
+// return noErr;
+//}
+//
+
+//--------------------------------------------------------------------------------------------------
+
diff --git a/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings b/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..85e4bb6
--- /dev/null
+++ b/scintilla/cocoa/ScintillaFramework/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/scintilla/cocoa/ScintillaFramework/Info.plist b/scintilla/cocoa/ScintillaFramework/Info.plist
new file mode 100644
index 0000000..08f1e5d
--- /dev/null
+++ b/scintilla/cocoa/ScintillaFramework/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.sun.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
diff --git a/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj b/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..4c96bca
--- /dev/null
+++ b/scintilla/cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj
@@ -0,0 +1,969 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 11374AAA10514AA900651FE9 /* LexMarkdown.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11374AA910514AA900651FE9 /* LexMarkdown.cxx */; };
+ 2744E4DC0FC1682C00E85C33 /* AutoComplete.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4CF0FC1682C00E85C33 /* AutoComplete.cxx */; };
+ 2744E4DD0FC1682C00E85C33 /* CallTip.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D00FC1682C00E85C33 /* CallTip.cxx */; };
+ 2744E4DE0FC1682C00E85C33 /* CellBuffer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D10FC1682C00E85C33 /* CellBuffer.cxx */; };
+ 2744E4DF0FC1682C00E85C33 /* CharClassify.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D20FC1682C00E85C33 /* CharClassify.cxx */; };
+ 2744E4E00FC1682C00E85C33 /* ContractionState.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D30FC1682C00E85C33 /* ContractionState.cxx */; };
+ 2744E4E10FC1682C00E85C33 /* Decoration.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D40FC1682C00E85C33 /* Decoration.cxx */; };
+ 2744E4E20FC1682C00E85C33 /* Document.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D50FC1682C00E85C33 /* Document.cxx */; };
+ 2744E4E30FC1682C00E85C33 /* DocumentAccessor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D60FC1682C00E85C33 /* DocumentAccessor.cxx */; };
+ 2744E4E40FC1682C00E85C33 /* Editor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D70FC1682C00E85C33 /* Editor.cxx */; };
+ 2744E4E50FC1682C00E85C33 /* ExternalLexer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D80FC1682C00E85C33 /* ExternalLexer.cxx */; };
+ 2744E4E60FC1682C00E85C33 /* Indicator.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4D90FC1682C00E85C33 /* Indicator.cxx */; };
+ 2744E4E70FC1682C00E85C33 /* KeyMap.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4DA0FC1682C00E85C33 /* KeyMap.cxx */; };
+ 2744E4E80FC1682C00E85C33 /* KeyWords.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4DB0FC1682C00E85C33 /* KeyWords.cxx */; };
+ 2744E5360FC1684700E85C33 /* LexAbaqus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4E90FC1684700E85C33 /* LexAbaqus.cxx */; };
+ 2744E5370FC1684700E85C33 /* LexAda.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4EA0FC1684700E85C33 /* LexAda.cxx */; };
+ 2744E5380FC1684700E85C33 /* LexAPDL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4EB0FC1684700E85C33 /* LexAPDL.cxx */; };
+ 2744E5390FC1684700E85C33 /* LexAsm.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4EC0FC1684700E85C33 /* LexAsm.cxx */; };
+ 2744E53A0FC1684700E85C33 /* LexAsn1.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4ED0FC1684700E85C33 /* LexAsn1.cxx */; };
+ 2744E53B0FC1684700E85C33 /* LexASY.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4EE0FC1684700E85C33 /* LexASY.cxx */; };
+ 2744E53C0FC1684700E85C33 /* LexAU3.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4EF0FC1684700E85C33 /* LexAU3.cxx */; };
+ 2744E53D0FC1684700E85C33 /* LexAVE.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F00FC1684700E85C33 /* LexAVE.cxx */; };
+ 2744E53E0FC1684700E85C33 /* LexBaan.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F10FC1684700E85C33 /* LexBaan.cxx */; };
+ 2744E53F0FC1684700E85C33 /* LexBash.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F20FC1684700E85C33 /* LexBash.cxx */; };
+ 2744E5400FC1684700E85C33 /* LexBasic.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F30FC1684700E85C33 /* LexBasic.cxx */; };
+ 2744E5410FC1684700E85C33 /* LexBullant.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F40FC1684700E85C33 /* LexBullant.cxx */; };
+ 2744E5420FC1684700E85C33 /* LexCaml.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F50FC1684700E85C33 /* LexCaml.cxx */; };
+ 2744E5430FC1684700E85C33 /* LexCLW.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F60FC1684700E85C33 /* LexCLW.cxx */; };
+ 2744E5440FC1684700E85C33 /* LexCmake.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F70FC1684700E85C33 /* LexCmake.cxx */; };
+ 2744E5450FC1684700E85C33 /* LexCOBOL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F80FC1684700E85C33 /* LexCOBOL.cxx */; };
+ 2744E5460FC1684700E85C33 /* LexConf.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4F90FC1684700E85C33 /* LexConf.cxx */; };
+ 2744E5470FC1684700E85C33 /* LexCPP.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FA0FC1684700E85C33 /* LexCPP.cxx */; };
+ 2744E5480FC1684700E85C33 /* LexCrontab.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FB0FC1684700E85C33 /* LexCrontab.cxx */; };
+ 2744E5490FC1684700E85C33 /* LexCsound.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FC0FC1684700E85C33 /* LexCsound.cxx */; };
+ 2744E54A0FC1684700E85C33 /* LexCSS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FD0FC1684700E85C33 /* LexCSS.cxx */; };
+ 2744E54B0FC1684700E85C33 /* LexD.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FE0FC1684700E85C33 /* LexD.cxx */; };
+ 2744E54C0FC1684700E85C33 /* LexEiffel.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E4FF0FC1684700E85C33 /* LexEiffel.cxx */; };
+ 2744E54D0FC1684700E85C33 /* LexErlang.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5000FC1684700E85C33 /* LexErlang.cxx */; };
+ 2744E54E0FC1684700E85C33 /* LexEScript.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5010FC1684700E85C33 /* LexEScript.cxx */; };
+ 2744E54F0FC1684700E85C33 /* LexFlagship.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5020FC1684700E85C33 /* LexFlagship.cxx */; };
+ 2744E5500FC1684700E85C33 /* LexForth.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5030FC1684700E85C33 /* LexForth.cxx */; };
+ 2744E5510FC1684700E85C33 /* LexFortran.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5040FC1684700E85C33 /* LexFortran.cxx */; };
+ 2744E5520FC1684700E85C33 /* LexGAP.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5050FC1684700E85C33 /* LexGAP.cxx */; };
+ 2744E5530FC1684700E85C33 /* LexGui4Cli.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5060FC1684700E85C33 /* LexGui4Cli.cxx */; };
+ 2744E5540FC1684700E85C33 /* LexHaskell.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5070FC1684700E85C33 /* LexHaskell.cxx */; };
+ 2744E5550FC1684700E85C33 /* LexHTML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5080FC1684700E85C33 /* LexHTML.cxx */; };
+ 2744E5560FC1684700E85C33 /* LexInno.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5090FC1684700E85C33 /* LexInno.cxx */; };
+ 2744E5570FC1684700E85C33 /* LexKix.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50A0FC1684700E85C33 /* LexKix.cxx */; };
+ 2744E5580FC1684700E85C33 /* LexLisp.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50B0FC1684700E85C33 /* LexLisp.cxx */; };
+ 2744E5590FC1684700E85C33 /* LexLout.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50C0FC1684700E85C33 /* LexLout.cxx */; };
+ 2744E55A0FC1684700E85C33 /* LexLua.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50D0FC1684700E85C33 /* LexLua.cxx */; };
+ 2744E55B0FC1684700E85C33 /* LexMagik.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50E0FC1684700E85C33 /* LexMagik.cxx */; };
+ 2744E55C0FC1684700E85C33 /* LexMatlab.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E50F0FC1684700E85C33 /* LexMatlab.cxx */; };
+ 2744E55D0FC1684700E85C33 /* LexMetapost.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5100FC1684700E85C33 /* LexMetapost.cxx */; };
+ 2744E55E0FC1684700E85C33 /* LexMMIXAL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5110FC1684700E85C33 /* LexMMIXAL.cxx */; };
+ 2744E55F0FC1684700E85C33 /* LexMPT.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5120FC1684700E85C33 /* LexMPT.cxx */; };
+ 2744E5600FC1684700E85C33 /* LexMSSQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5130FC1684700E85C33 /* LexMSSQL.cxx */; };
+ 2744E5610FC1684700E85C33 /* LexMySQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5140FC1684700E85C33 /* LexMySQL.cxx */; };
+ 2744E5620FC1684700E85C33 /* LexNimrod.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5150FC1684700E85C33 /* LexNimrod.cxx */; };
+ 2744E5630FC1684700E85C33 /* LexNsis.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5160FC1684700E85C33 /* LexNsis.cxx */; };
+ 2744E5640FC1684700E85C33 /* LexOpal.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5170FC1684700E85C33 /* LexOpal.cxx */; };
+ 2744E5650FC1684700E85C33 /* LexOthers.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5180FC1684700E85C33 /* LexOthers.cxx */; };
+ 2744E5660FC1684700E85C33 /* LexPascal.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5190FC1684700E85C33 /* LexPascal.cxx */; };
+ 2744E5670FC1684700E85C33 /* LexPB.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51A0FC1684700E85C33 /* LexPB.cxx */; };
+ 2744E5680FC1684700E85C33 /* LexPerl.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51B0FC1684700E85C33 /* LexPerl.cxx */; };
+ 2744E5690FC1684700E85C33 /* LexPLM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51C0FC1684700E85C33 /* LexPLM.cxx */; };
+ 2744E56A0FC1684700E85C33 /* LexPOV.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51D0FC1684700E85C33 /* LexPOV.cxx */; };
+ 2744E56B0FC1684700E85C33 /* LexPowerPro.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51E0FC1684700E85C33 /* LexPowerPro.cxx */; };
+ 2744E56C0FC1684700E85C33 /* LexPowerShell.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E51F0FC1684700E85C33 /* LexPowerShell.cxx */; };
+ 2744E56D0FC1684700E85C33 /* LexProgress.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5200FC1684700E85C33 /* LexProgress.cxx */; };
+ 2744E56E0FC1684700E85C33 /* LexPS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5210FC1684700E85C33 /* LexPS.cxx */; };
+ 2744E56F0FC1684700E85C33 /* LexPython.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5220FC1684700E85C33 /* LexPython.cxx */; };
+ 2744E5700FC1684700E85C33 /* LexR.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5230FC1684700E85C33 /* LexR.cxx */; };
+ 2744E5710FC1684700E85C33 /* LexRebol.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5240FC1684700E85C33 /* LexRebol.cxx */; };
+ 2744E5720FC1684700E85C33 /* LexRuby.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5250FC1684700E85C33 /* LexRuby.cxx */; };
+ 2744E5730FC1684700E85C33 /* LexScriptol.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5260FC1684700E85C33 /* LexScriptol.cxx */; };
+ 2744E5740FC1684700E85C33 /* LexSmalltalk.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5270FC1684700E85C33 /* LexSmalltalk.cxx */; };
+ 2744E5750FC1684700E85C33 /* LexSML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5280FC1684700E85C33 /* LexSML.cxx */; };
+ 2744E5760FC1684700E85C33 /* LexSorcus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5290FC1684700E85C33 /* LexSorcus.cxx */; };
+ 2744E5770FC1684700E85C33 /* LexSpecman.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52A0FC1684700E85C33 /* LexSpecman.cxx */; };
+ 2744E5780FC1684700E85C33 /* LexSpice.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52B0FC1684700E85C33 /* LexSpice.cxx */; };
+ 2744E5790FC1684700E85C33 /* LexSQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52C0FC1684700E85C33 /* LexSQL.cxx */; };
+ 2744E57A0FC1684700E85C33 /* LexTACL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52D0FC1684700E85C33 /* LexTACL.cxx */; };
+ 2744E57B0FC1684700E85C33 /* LexTADS3.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52E0FC1684700E85C33 /* LexTADS3.cxx */; };
+ 2744E57C0FC1684700E85C33 /* LexTAL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E52F0FC1684700E85C33 /* LexTAL.cxx */; };
+ 2744E57D0FC1684700E85C33 /* LexTCL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5300FC1684700E85C33 /* LexTCL.cxx */; };
+ 2744E57E0FC1684700E85C33 /* LexTeX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5310FC1684700E85C33 /* LexTeX.cxx */; };
+ 2744E57F0FC1684700E85C33 /* LexVB.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5320FC1684700E85C33 /* LexVB.cxx */; };
+ 2744E5800FC1684700E85C33 /* LexVerilog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5330FC1684700E85C33 /* LexVerilog.cxx */; };
+ 2744E5810FC1684700E85C33 /* LexVHDL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5340FC1684700E85C33 /* LexVHDL.cxx */; };
+ 2744E5820FC1684700E85C33 /* LexYAML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5350FC1684700E85C33 /* LexYAML.cxx */; };
+ 2744E5900FC1685C00E85C33 /* LineMarker.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5830FC1685C00E85C33 /* LineMarker.cxx */; };
+ 2744E5910FC1685C00E85C33 /* PerLine.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5840FC1685C00E85C33 /* PerLine.cxx */; };
+ 2744E5920FC1685C00E85C33 /* PositionCache.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5850FC1685C00E85C33 /* PositionCache.cxx */; };
+ 2744E5930FC1685C00E85C33 /* PropSet.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5860FC1685C00E85C33 /* PropSet.cxx */; };
+ 2744E5940FC1685C00E85C33 /* RESearch.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5870FC1685C00E85C33 /* RESearch.cxx */; };
+ 2744E5950FC1685C00E85C33 /* RunStyles.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5880FC1685C00E85C33 /* RunStyles.cxx */; };
+ 2744E5960FC1685C00E85C33 /* ScintillaBase.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5890FC1685C00E85C33 /* ScintillaBase.cxx */; };
+ 2744E5970FC1685C00E85C33 /* Style.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58A0FC1685C00E85C33 /* Style.cxx */; };
+ 2744E5980FC1685C00E85C33 /* StyleContext.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58B0FC1685C00E85C33 /* StyleContext.cxx */; };
+ 2744E5990FC1685C00E85C33 /* UniConversion.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58C0FC1685C00E85C33 /* UniConversion.cxx */; };
+ 2744E59A0FC1685C00E85C33 /* ViewStyle.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58D0FC1685C00E85C33 /* ViewStyle.cxx */; };
+ 2744E59B0FC1685C00E85C33 /* WindowAccessor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58E0FC1685C00E85C33 /* WindowAccessor.cxx */; };
+ 2744E59C0FC1685C00E85C33 /* XPM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2744E58F0FC1685C00E85C33 /* XPM.cxx */; };
+ 2744E5A40FC168A100E85C33 /* InfoBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59D0FC168A100E85C33 /* InfoBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2744E5AA0FC168A100E85C33 /* ScintillaView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A30FC168A100E85C33 /* ScintillaView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2744E5AC0FC168B200E85C33 /* InfoBarCommunicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2744E5B20FC168C500E85C33 /* InfoBar.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5AD0FC168C500E85C33 /* InfoBar.mm */; };
+ 2744E5B30FC168C500E85C33 /* PlatCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */; };
+ 2744E5B50FC168C500E85C33 /* ScintillaCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */; };
+ 2744E5B60FC168C500E85C33 /* ScintillaView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5B10FC168C500E85C33 /* ScintillaView.mm */; };
+ 277B5BDA104EE6B900F40CE4 /* Selection.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 277B5BD9104EE6B900F40CE4 /* Selection.cxx */; };
+ 277B5BDD104EE6CF00F40CE4 /* PropSetSimple.h in Headers */ = {isa = PBXBuildFile; fileRef = 277B5BDB104EE6CF00F40CE4 /* PropSetSimple.h */; };
+ 277B5BDE104EE6CF00F40CE4 /* Selection.h in Headers */ = {isa = PBXBuildFile; fileRef = 277B5BDC104EE6CF00F40CE4 /* Selection.h */; };
+ 2791F3C60FC19F71009DBCF9 /* PlatCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59E0FC168A100E85C33 /* PlatCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3C70FC19F71009DBCF9 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4850FC1678600E85C33 /* Platform.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3C80FC19F71009DBCF9 /* SciLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4870FC1678600E85C33 /* SciLexer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3C90FC19F71009DBCF9 /* Scintilla.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4880FC1678600E85C33 /* Scintilla.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E00FC1A390009DBCF9 /* ScintillaCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E30FC1A3AE009DBCF9 /* QuartzTextLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E40FC1A3AE009DBCF9 /* QuartzTextStyleAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E50FC1A3AE009DBCF9 /* Accessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4830FC1678600E85C33 /* Accessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E60FC1A3AE009DBCF9 /* KeyWords.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4840FC1678600E85C33 /* KeyWords.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E70FC1A3AE009DBCF9 /* PropSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4860FC1678600E85C33 /* PropSet.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3E80FC1A3AE009DBCF9 /* ScintillaWidget.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E48A0FC1678600E85C33 /* ScintillaWidget.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3EA0FC1A3AE009DBCF9 /* WindowAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E48C0FC1678600E85C33 /* WindowAccessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3EB0FC1A3BD009DBCF9 /* AutoComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4990FC1681200E85C33 /* AutoComplete.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3EC0FC1A3BD009DBCF9 /* CallTip.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49A0FC1681200E85C33 /* CallTip.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3ED0FC1A3BD009DBCF9 /* CellBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49B0FC1681200E85C33 /* CellBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3EE0FC1A3BD009DBCF9 /* CharacterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49C0FC1681200E85C33 /* CharacterSet.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3EF0FC1A3BD009DBCF9 /* CharClassify.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49D0FC1681200E85C33 /* CharClassify.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F00FC1A3BD009DBCF9 /* ContractionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49E0FC1681200E85C33 /* ContractionState.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F10FC1A3BD009DBCF9 /* Decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E49F0FC1681200E85C33 /* Decoration.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F20FC1A3BD009DBCF9 /* Document.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A00FC1681200E85C33 /* Document.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F30FC1A3BD009DBCF9 /* DocumentAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A10FC1681200E85C33 /* DocumentAccessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F40FC1A3BD009DBCF9 /* Editor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A20FC1681200E85C33 /* Editor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F50FC1A3BD009DBCF9 /* ExternalLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A30FC1681200E85C33 /* ExternalLexer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F60FC1A3BD009DBCF9 /* Indicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A40FC1681200E85C33 /* Indicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F70FC1A3BD009DBCF9 /* KeyMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A50FC1681200E85C33 /* KeyMap.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F80FC1A3BD009DBCF9 /* LineMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A60FC1681200E85C33 /* LineMarker.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3F90FC1A3BD009DBCF9 /* Partitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A70FC1681200E85C33 /* Partitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FA0FC1A3BD009DBCF9 /* PerLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A80FC1681200E85C33 /* PerLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FB0FC1A3BD009DBCF9 /* PositionCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4A90FC1681200E85C33 /* PositionCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FC0FC1A3BD009DBCF9 /* RESearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AA0FC1681200E85C33 /* RESearch.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FD0FC1A3BD009DBCF9 /* RunStyles.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AB0FC1681200E85C33 /* RunStyles.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FE0FC1A3BD009DBCF9 /* ScintillaBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AC0FC1681200E85C33 /* ScintillaBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F3FF0FC1A3BD009DBCF9 /* SplitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AD0FC1681200E85C33 /* SplitVector.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4000FC1A3BD009DBCF9 /* Style.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AE0FC1681200E85C33 /* Style.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4010FC1A3BD009DBCF9 /* StyleContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4AF0FC1681200E85C33 /* StyleContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4020FC1A3BD009DBCF9 /* SVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4B00FC1681200E85C33 /* SVector.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4030FC1A3BD009DBCF9 /* UniConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4B10FC1681200E85C33 /* UniConversion.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4040FC1A3BD009DBCF9 /* ViewStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4B20FC1681200E85C33 /* ViewStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2791F4050FC1A3BD009DBCF9 /* XPM.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4B30FC1681200E85C33 /* XPM.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 27FEF4540FC1B413005E115A /* info_bar_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4510FC1B413005E115A /* info_bar_bg.png */; };
+ 27FEF4550FC1B413005E115A /* mac_cursor_busy.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4520FC1B413005E115A /* mac_cursor_busy.png */; };
+ 27FEF4560FC1B413005E115A /* mac_cursor_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */; };
+ 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 11374AA910514AA900651FE9 /* LexMarkdown.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMarkdown.cxx; path = ../../src/LexMarkdown.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4830FC1678600E85C33 /* Accessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Accessor.h; path = ../../include/Accessor.h; sourceTree = SOURCE_ROOT; };
+ 2744E4840FC1678600E85C33 /* KeyWords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyWords.h; path = ../../include/KeyWords.h; sourceTree = SOURCE_ROOT; };
+ 2744E4850FC1678600E85C33 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = ../../include/Platform.h; sourceTree = SOURCE_ROOT; };
+ 2744E4860FC1678600E85C33 /* PropSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PropSet.h; path = ../../include/PropSet.h; sourceTree = SOURCE_ROOT; };
+ 2744E4870FC1678600E85C33 /* SciLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SciLexer.h; path = ../../include/SciLexer.h; sourceTree = SOURCE_ROOT; };
+ 2744E4880FC1678600E85C33 /* Scintilla.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scintilla.h; path = ../../include/Scintilla.h; sourceTree = SOURCE_ROOT; };
+ 2744E48A0FC1678600E85C33 /* ScintillaWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaWidget.h; path = ../../include/ScintillaWidget.h; sourceTree = SOURCE_ROOT; };
+ 2744E48C0FC1678600E85C33 /* WindowAccessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WindowAccessor.h; path = ../../include/WindowAccessor.h; sourceTree = SOURCE_ROOT; };
+ 2744E4990FC1681200E85C33 /* AutoComplete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AutoComplete.h; path = ../../src/AutoComplete.h; sourceTree = SOURCE_ROOT; };
+ 2744E49A0FC1681200E85C33 /* CallTip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallTip.h; path = ../../src/CallTip.h; sourceTree = SOURCE_ROOT; };
+ 2744E49B0FC1681200E85C33 /* CellBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CellBuffer.h; path = ../../src/CellBuffer.h; sourceTree = SOURCE_ROOT; };
+ 2744E49C0FC1681200E85C33 /* CharacterSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CharacterSet.h; path = ../../src/CharacterSet.h; sourceTree = SOURCE_ROOT; };
+ 2744E49D0FC1681200E85C33 /* CharClassify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CharClassify.h; path = ../../src/CharClassify.h; sourceTree = SOURCE_ROOT; };
+ 2744E49E0FC1681200E85C33 /* ContractionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContractionState.h; path = ../../src/ContractionState.h; sourceTree = SOURCE_ROOT; };
+ 2744E49F0FC1681200E85C33 /* Decoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Decoration.h; path = ../../src/Decoration.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A00FC1681200E85C33 /* Document.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Document.h; path = ../../src/Document.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A10FC1681200E85C33 /* DocumentAccessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DocumentAccessor.h; path = ../../src/DocumentAccessor.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A20FC1681200E85C33 /* Editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Editor.h; path = ../../src/Editor.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A30FC1681200E85C33 /* ExternalLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalLexer.h; path = ../../src/ExternalLexer.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A40FC1681200E85C33 /* Indicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Indicator.h; path = ../../src/Indicator.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A50FC1681200E85C33 /* KeyMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyMap.h; path = ../../src/KeyMap.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A60FC1681200E85C33 /* LineMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineMarker.h; path = ../../src/LineMarker.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A70FC1681200E85C33 /* Partitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Partitioning.h; path = ../../src/Partitioning.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A80FC1681200E85C33 /* PerLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PerLine.h; path = ../../src/PerLine.h; sourceTree = SOURCE_ROOT; };
+ 2744E4A90FC1681200E85C33 /* PositionCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PositionCache.h; path = ../../src/PositionCache.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AA0FC1681200E85C33 /* RESearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RESearch.h; path = ../../src/RESearch.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AB0FC1681200E85C33 /* RunStyles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RunStyles.h; path = ../../src/RunStyles.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AC0FC1681200E85C33 /* ScintillaBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaBase.h; path = ../../src/ScintillaBase.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AD0FC1681200E85C33 /* SplitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SplitVector.h; path = ../../src/SplitVector.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AE0FC1681200E85C33 /* Style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Style.h; path = ../../src/Style.h; sourceTree = SOURCE_ROOT; };
+ 2744E4AF0FC1681200E85C33 /* StyleContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StyleContext.h; path = ../../src/StyleContext.h; sourceTree = SOURCE_ROOT; };
+ 2744E4B00FC1681200E85C33 /* SVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SVector.h; path = ../../src/SVector.h; sourceTree = SOURCE_ROOT; };
+ 2744E4B10FC1681200E85C33 /* UniConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UniConversion.h; path = ../../src/UniConversion.h; sourceTree = SOURCE_ROOT; };
+ 2744E4B20FC1681200E85C33 /* ViewStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewStyle.h; path = ../../src/ViewStyle.h; sourceTree = SOURCE_ROOT; };
+ 2744E4B30FC1681200E85C33 /* XPM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPM.h; path = ../../src/XPM.h; sourceTree = SOURCE_ROOT; };
+ 2744E4CF0FC1682C00E85C33 /* AutoComplete.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AutoComplete.cxx; path = ../../src/AutoComplete.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D00FC1682C00E85C33 /* CallTip.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CallTip.cxx; path = ../../src/CallTip.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D10FC1682C00E85C33 /* CellBuffer.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CellBuffer.cxx; path = ../../src/CellBuffer.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D20FC1682C00E85C33 /* CharClassify.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CharClassify.cxx; path = ../../src/CharClassify.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D30FC1682C00E85C33 /* ContractionState.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContractionState.cxx; path = ../../src/ContractionState.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D40FC1682C00E85C33 /* Decoration.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Decoration.cxx; path = ../../src/Decoration.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D50FC1682C00E85C33 /* Document.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Document.cxx; path = ../../src/Document.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D60FC1682C00E85C33 /* DocumentAccessor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DocumentAccessor.cxx; path = ../../src/DocumentAccessor.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D70FC1682C00E85C33 /* Editor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Editor.cxx; path = ../../src/Editor.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D80FC1682C00E85C33 /* ExternalLexer.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExternalLexer.cxx; path = ../../src/ExternalLexer.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4D90FC1682C00E85C33 /* Indicator.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Indicator.cxx; path = ../../src/Indicator.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4DA0FC1682C00E85C33 /* KeyMap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyMap.cxx; path = ../../src/KeyMap.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4DB0FC1682C00E85C33 /* KeyWords.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyWords.cxx; path = ../../src/KeyWords.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4E90FC1684700E85C33 /* LexAbaqus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAbaqus.cxx; path = ../../src/LexAbaqus.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4EA0FC1684700E85C33 /* LexAda.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAda.cxx; path = ../../src/LexAda.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4EB0FC1684700E85C33 /* LexAPDL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAPDL.cxx; path = ../../src/LexAPDL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4EC0FC1684700E85C33 /* LexAsm.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAsm.cxx; path = ../../src/LexAsm.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4ED0FC1684700E85C33 /* LexAsn1.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAsn1.cxx; path = ../../src/LexAsn1.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4EE0FC1684700E85C33 /* LexASY.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexASY.cxx; path = ../../src/LexASY.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4EF0FC1684700E85C33 /* LexAU3.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAU3.cxx; path = ../../src/LexAU3.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F00FC1684700E85C33 /* LexAVE.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAVE.cxx; path = ../../src/LexAVE.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F10FC1684700E85C33 /* LexBaan.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBaan.cxx; path = ../../src/LexBaan.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F20FC1684700E85C33 /* LexBash.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBash.cxx; path = ../../src/LexBash.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F30FC1684700E85C33 /* LexBasic.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBasic.cxx; path = ../../src/LexBasic.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F40FC1684700E85C33 /* LexBullant.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBullant.cxx; path = ../../src/LexBullant.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F50FC1684700E85C33 /* LexCaml.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCaml.cxx; path = ../../src/LexCaml.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F60FC1684700E85C33 /* LexCLW.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCLW.cxx; path = ../../src/LexCLW.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F70FC1684700E85C33 /* LexCmake.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCmake.cxx; path = ../../src/LexCmake.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F80FC1684700E85C33 /* LexCOBOL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCOBOL.cxx; path = ../../src/LexCOBOL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4F90FC1684700E85C33 /* LexConf.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexConf.cxx; path = ../../src/LexConf.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FA0FC1684700E85C33 /* LexCPP.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCPP.cxx; path = ../../src/LexCPP.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FB0FC1684700E85C33 /* LexCrontab.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCrontab.cxx; path = ../../src/LexCrontab.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FC0FC1684700E85C33 /* LexCsound.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCsound.cxx; path = ../../src/LexCsound.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FD0FC1684700E85C33 /* LexCSS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCSS.cxx; path = ../../src/LexCSS.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FE0FC1684700E85C33 /* LexD.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexD.cxx; path = ../../src/LexD.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E4FF0FC1684700E85C33 /* LexEiffel.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexEiffel.cxx; path = ../../src/LexEiffel.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5000FC1684700E85C33 /* LexErlang.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexErlang.cxx; path = ../../src/LexErlang.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5010FC1684700E85C33 /* LexEScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexEScript.cxx; path = ../../src/LexEScript.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5020FC1684700E85C33 /* LexFlagship.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexFlagship.cxx; path = ../../src/LexFlagship.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5030FC1684700E85C33 /* LexForth.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexForth.cxx; path = ../../src/LexForth.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5040FC1684700E85C33 /* LexFortran.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexFortran.cxx; path = ../../src/LexFortran.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5050FC1684700E85C33 /* LexGAP.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexGAP.cxx; path = ../../src/LexGAP.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5060FC1684700E85C33 /* LexGui4Cli.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexGui4Cli.cxx; path = ../../src/LexGui4Cli.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5070FC1684700E85C33 /* LexHaskell.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexHaskell.cxx; path = ../../src/LexHaskell.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5080FC1684700E85C33 /* LexHTML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexHTML.cxx; path = ../../src/LexHTML.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5090FC1684700E85C33 /* LexInno.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexInno.cxx; path = ../../src/LexInno.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50A0FC1684700E85C33 /* LexKix.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexKix.cxx; path = ../../src/LexKix.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50B0FC1684700E85C33 /* LexLisp.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLisp.cxx; path = ../../src/LexLisp.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50C0FC1684700E85C33 /* LexLout.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLout.cxx; path = ../../src/LexLout.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50D0FC1684700E85C33 /* LexLua.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLua.cxx; path = ../../src/LexLua.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50E0FC1684700E85C33 /* LexMagik.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMagik.cxx; path = ../../src/LexMagik.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E50F0FC1684700E85C33 /* LexMatlab.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMatlab.cxx; path = ../../src/LexMatlab.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5100FC1684700E85C33 /* LexMetapost.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMetapost.cxx; path = ../../src/LexMetapost.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5110FC1684700E85C33 /* LexMMIXAL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMMIXAL.cxx; path = ../../src/LexMMIXAL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5120FC1684700E85C33 /* LexMPT.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMPT.cxx; path = ../../src/LexMPT.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5130FC1684700E85C33 /* LexMSSQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMSSQL.cxx; path = ../../src/LexMSSQL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5140FC1684700E85C33 /* LexMySQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMySQL.cxx; path = ../../src/LexMySQL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5150FC1684700E85C33 /* LexNimrod.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNimrod.cxx; path = ../../src/LexNimrod.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5160FC1684700E85C33 /* LexNsis.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNsis.cxx; path = ../../src/LexNsis.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5170FC1684700E85C33 /* LexOpal.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexOpal.cxx; path = ../../src/LexOpal.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5180FC1684700E85C33 /* LexOthers.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexOthers.cxx; path = ../../src/LexOthers.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5190FC1684700E85C33 /* LexPascal.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPascal.cxx; path = ../../src/LexPascal.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51A0FC1684700E85C33 /* LexPB.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPB.cxx; path = ../../src/LexPB.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51B0FC1684700E85C33 /* LexPerl.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPerl.cxx; path = ../../src/LexPerl.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51C0FC1684700E85C33 /* LexPLM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPLM.cxx; path = ../../src/LexPLM.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51D0FC1684700E85C33 /* LexPOV.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPOV.cxx; path = ../../src/LexPOV.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51E0FC1684700E85C33 /* LexPowerPro.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPowerPro.cxx; path = ../../src/LexPowerPro.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E51F0FC1684700E85C33 /* LexPowerShell.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPowerShell.cxx; path = ../../src/LexPowerShell.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5200FC1684700E85C33 /* LexProgress.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexProgress.cxx; path = ../../src/LexProgress.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5210FC1684700E85C33 /* LexPS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPS.cxx; path = ../../src/LexPS.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5220FC1684700E85C33 /* LexPython.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPython.cxx; path = ../../src/LexPython.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5230FC1684700E85C33 /* LexR.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexR.cxx; path = ../../src/LexR.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5240FC1684700E85C33 /* LexRebol.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexRebol.cxx; path = ../../src/LexRebol.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5250FC1684700E85C33 /* LexRuby.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexRuby.cxx; path = ../../src/LexRuby.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5260FC1684700E85C33 /* LexScriptol.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexScriptol.cxx; path = ../../src/LexScriptol.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5270FC1684700E85C33 /* LexSmalltalk.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSmalltalk.cxx; path = ../../src/LexSmalltalk.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5280FC1684700E85C33 /* LexSML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSML.cxx; path = ../../src/LexSML.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5290FC1684700E85C33 /* LexSorcus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSorcus.cxx; path = ../../src/LexSorcus.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52A0FC1684700E85C33 /* LexSpecman.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSpecman.cxx; path = ../../src/LexSpecman.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52B0FC1684700E85C33 /* LexSpice.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSpice.cxx; path = ../../src/LexSpice.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52C0FC1684700E85C33 /* LexSQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSQL.cxx; path = ../../src/LexSQL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52D0FC1684700E85C33 /* LexTACL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTACL.cxx; path = ../../src/LexTACL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52E0FC1684700E85C33 /* LexTADS3.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTADS3.cxx; path = ../../src/LexTADS3.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E52F0FC1684700E85C33 /* LexTAL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTAL.cxx; path = ../../src/LexTAL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5300FC1684700E85C33 /* LexTCL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTCL.cxx; path = ../../src/LexTCL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5310FC1684700E85C33 /* LexTeX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTeX.cxx; path = ../../src/LexTeX.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5320FC1684700E85C33 /* LexVB.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVB.cxx; path = ../../src/LexVB.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5330FC1684700E85C33 /* LexVerilog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVerilog.cxx; path = ../../src/LexVerilog.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5340FC1684700E85C33 /* LexVHDL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVHDL.cxx; path = ../../src/LexVHDL.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5350FC1684700E85C33 /* LexYAML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexYAML.cxx; path = ../../src/LexYAML.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5830FC1685C00E85C33 /* LineMarker.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LineMarker.cxx; path = ../../src/LineMarker.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5840FC1685C00E85C33 /* PerLine.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PerLine.cxx; path = ../../src/PerLine.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5850FC1685C00E85C33 /* PositionCache.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PositionCache.cxx; path = ../../src/PositionCache.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5860FC1685C00E85C33 /* PropSet.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PropSet.cxx; path = ../../src/PropSet.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5870FC1685C00E85C33 /* RESearch.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RESearch.cxx; path = ../../src/RESearch.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5880FC1685C00E85C33 /* RunStyles.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RunStyles.cxx; path = ../../src/RunStyles.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E5890FC1685C00E85C33 /* ScintillaBase.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScintillaBase.cxx; path = ../../src/ScintillaBase.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58A0FC1685C00E85C33 /* Style.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Style.cxx; path = ../../src/Style.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58B0FC1685C00E85C33 /* StyleContext.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StyleContext.cxx; path = ../../src/StyleContext.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58C0FC1685C00E85C33 /* UniConversion.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UniConversion.cxx; path = ../../src/UniConversion.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58D0FC1685C00E85C33 /* ViewStyle.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ViewStyle.cxx; path = ../../src/ViewStyle.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58E0FC1685C00E85C33 /* WindowAccessor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WindowAccessor.cxx; path = ../../src/WindowAccessor.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E58F0FC1685C00E85C33 /* XPM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XPM.cxx; path = ../../src/XPM.cxx; sourceTree = SOURCE_ROOT; };
+ 2744E59D0FC168A100E85C33 /* InfoBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InfoBar.h; path = ../InfoBar.h; sourceTree = SOURCE_ROOT; };
+ 2744E59E0FC168A100E85C33 /* PlatCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatCocoa.h; path = ../PlatCocoa.h; sourceTree = SOURCE_ROOT; };
+ 2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuartzTextLayout.h; path = ../QuartzTextLayout.h; sourceTree = SOURCE_ROOT; };
+ 2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuartzTextStyleAttribute.h; path = ../QuartzTextStyleAttribute.h; sourceTree = SOURCE_ROOT; };
+ 2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaCocoa.h; path = ../ScintillaCocoa.h; sourceTree = "<group>"; };
+ 2744E5A30FC168A100E85C33 /* ScintillaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaView.h; path = ../ScintillaView.h; sourceTree = "<group>"; };
+ 2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InfoBarCommunicator.h; path = ../InfoBarCommunicator.h; sourceTree = SOURCE_ROOT; };
+ 2744E5AD0FC168C500E85C33 /* InfoBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InfoBar.mm; path = ../InfoBar.mm; sourceTree = SOURCE_ROOT; };
+ 2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatCocoa.mm; path = ../PlatCocoa.mm; sourceTree = SOURCE_ROOT; };
+ 2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScintillaCocoa.mm; path = ../ScintillaCocoa.mm; sourceTree = "<group>"; };
+ 2744E5B10FC168C500E85C33 /* ScintillaView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScintillaView.mm; path = ../ScintillaView.mm; sourceTree = "<group>"; };
+ 277B5BD9104EE6B900F40CE4 /* Selection.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Selection.cxx; path = ../../src/Selection.cxx; sourceTree = SOURCE_ROOT; };
+ 277B5BDB104EE6CF00F40CE4 /* PropSetSimple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PropSetSimple.h; path = ../../src/PropSetSimple.h; sourceTree = SOURCE_ROOT; };
+ 277B5BDC104EE6CF00F40CE4 /* Selection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Selection.h; path = ../../src/Selection.h; sourceTree = SOURCE_ROOT; };
+ 27FEF4510FC1B413005E115A /* info_bar_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = info_bar_bg.png; sourceTree = "<group>"; };
+ 27FEF4520FC1B413005E115A /* mac_cursor_busy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mac_cursor_busy.png; sourceTree = "<group>"; };
+ 27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mac_cursor_flipped.png; sourceTree = "<group>"; };
+ 32DBCF5E0370ADEE00C91783 /* Scintilla_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scintilla_Prefix.pch; sourceTree = "<group>"; };
+ 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 8DC2EF5B0486A6940098B216 /* Scintilla.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Scintilla.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DC2EF560486A6940098B216 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DFFF38A50411DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DC2EF5B0486A6940098B216 /* Scintilla.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* Scintilla */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E47D0FC1674E00E85C33 /* Lexers */,
+ 2744E47C0FC1674100E85C33 /* Backend */,
+ 08FB77AEFE84172EC02AAC07 /* Classes */,
+ 32C88DFF0371C24200C91783 /* Other Sources */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 034768DFFF38A50411DB9C8B /* Products */,
+ );
+ name = Scintilla;
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
+ 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 27FEF4500FC1B413005E115A /* res */,
+ 8DC2EF5A0486A6940098B216 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77AEFE84172EC02AAC07 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E4980FC167ED00E85C33 /* Source Files */,
+ 2744E4970FC167E400E85C33 /* Header Files */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+ 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "<group>";
+ };
+ 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 0867D6A5FE840307C02AAC07 /* AppKit.framework */,
+ D2F7E79907B2D74100F64583 /* CoreData.framework */,
+ 0867D69BFE84028FC02AAC07 /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 2744E47C0FC1674100E85C33 /* Backend */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E47F0FC1676400E85C33 /* Source Files */,
+ 2744E47E0FC1675800E85C33 /* Header Files */,
+ );
+ name = Backend;
+ sourceTree = "<group>";
+ };
+ 2744E47D0FC1674E00E85C33 /* Lexers */ = {
+ isa = PBXGroup;
+ children = (
+ 11374AA910514AA900651FE9 /* LexMarkdown.cxx */,
+ 2744E4E90FC1684700E85C33 /* LexAbaqus.cxx */,
+ 2744E4EA0FC1684700E85C33 /* LexAda.cxx */,
+ 2744E4EB0FC1684700E85C33 /* LexAPDL.cxx */,
+ 2744E4EC0FC1684700E85C33 /* LexAsm.cxx */,
+ 2744E4ED0FC1684700E85C33 /* LexAsn1.cxx */,
+ 2744E4EE0FC1684700E85C33 /* LexASY.cxx */,
+ 2744E4EF0FC1684700E85C33 /* LexAU3.cxx */,
+ 2744E4F00FC1684700E85C33 /* LexAVE.cxx */,
+ 2744E4F10FC1684700E85C33 /* LexBaan.cxx */,
+ 2744E4F20FC1684700E85C33 /* LexBash.cxx */,
+ 2744E4F30FC1684700E85C33 /* LexBasic.cxx */,
+ 2744E4F40FC1684700E85C33 /* LexBullant.cxx */,
+ 2744E4F50FC1684700E85C33 /* LexCaml.cxx */,
+ 2744E4F60FC1684700E85C33 /* LexCLW.cxx */,
+ 2744E4F70FC1684700E85C33 /* LexCmake.cxx */,
+ 2744E4F80FC1684700E85C33 /* LexCOBOL.cxx */,
+ 2744E4F90FC1684700E85C33 /* LexConf.cxx */,
+ 2744E4FA0FC1684700E85C33 /* LexCPP.cxx */,
+ 2744E4FB0FC1684700E85C33 /* LexCrontab.cxx */,
+ 2744E4FC0FC1684700E85C33 /* LexCsound.cxx */,
+ 2744E4FD0FC1684700E85C33 /* LexCSS.cxx */,
+ 2744E4FE0FC1684700E85C33 /* LexD.cxx */,
+ 2744E4FF0FC1684700E85C33 /* LexEiffel.cxx */,
+ 2744E5000FC1684700E85C33 /* LexErlang.cxx */,
+ 2744E5010FC1684700E85C33 /* LexEScript.cxx */,
+ 2744E5020FC1684700E85C33 /* LexFlagship.cxx */,
+ 2744E5030FC1684700E85C33 /* LexForth.cxx */,
+ 2744E5040FC1684700E85C33 /* LexFortran.cxx */,
+ 2744E5050FC1684700E85C33 /* LexGAP.cxx */,
+ 2744E5060FC1684700E85C33 /* LexGui4Cli.cxx */,
+ 2744E5070FC1684700E85C33 /* LexHaskell.cxx */,
+ 2744E5080FC1684700E85C33 /* LexHTML.cxx */,
+ 2744E5090FC1684700E85C33 /* LexInno.cxx */,
+ 2744E50A0FC1684700E85C33 /* LexKix.cxx */,
+ 2744E50B0FC1684700E85C33 /* LexLisp.cxx */,
+ 2744E50C0FC1684700E85C33 /* LexLout.cxx */,
+ 2744E50D0FC1684700E85C33 /* LexLua.cxx */,
+ 2744E50E0FC1684700E85C33 /* LexMagik.cxx */,
+ 2744E50F0FC1684700E85C33 /* LexMatlab.cxx */,
+ 2744E5100FC1684700E85C33 /* LexMetapost.cxx */,
+ 2744E5110FC1684700E85C33 /* LexMMIXAL.cxx */,
+ 2744E5120FC1684700E85C33 /* LexMPT.cxx */,
+ 2744E5130FC1684700E85C33 /* LexMSSQL.cxx */,
+ 2744E5140FC1684700E85C33 /* LexMySQL.cxx */,
+ 2744E5150FC1684700E85C33 /* LexNimrod.cxx */,
+ 2744E5160FC1684700E85C33 /* LexNsis.cxx */,
+ 2744E5170FC1684700E85C33 /* LexOpal.cxx */,
+ 2744E5180FC1684700E85C33 /* LexOthers.cxx */,
+ 2744E5190FC1684700E85C33 /* LexPascal.cxx */,
+ 2744E51A0FC1684700E85C33 /* LexPB.cxx */,
+ 2744E51B0FC1684700E85C33 /* LexPerl.cxx */,
+ 2744E51C0FC1684700E85C33 /* LexPLM.cxx */,
+ 2744E51D0FC1684700E85C33 /* LexPOV.cxx */,
+ 2744E51E0FC1684700E85C33 /* LexPowerPro.cxx */,
+ 2744E51F0FC1684700E85C33 /* LexPowerShell.cxx */,
+ 2744E5200FC1684700E85C33 /* LexProgress.cxx */,
+ 2744E5210FC1684700E85C33 /* LexPS.cxx */,
+ 2744E5220FC1684700E85C33 /* LexPython.cxx */,
+ 2744E5230FC1684700E85C33 /* LexR.cxx */,
+ 2744E5240FC1684700E85C33 /* LexRebol.cxx */,
+ 2744E5250FC1684700E85C33 /* LexRuby.cxx */,
+ 2744E5260FC1684700E85C33 /* LexScriptol.cxx */,
+ 2744E5270FC1684700E85C33 /* LexSmalltalk.cxx */,
+ 2744E5280FC1684700E85C33 /* LexSML.cxx */,
+ 2744E5290FC1684700E85C33 /* LexSorcus.cxx */,
+ 2744E52A0FC1684700E85C33 /* LexSpecman.cxx */,
+ 2744E52B0FC1684700E85C33 /* LexSpice.cxx */,
+ 2744E52C0FC1684700E85C33 /* LexSQL.cxx */,
+ 2744E52D0FC1684700E85C33 /* LexTACL.cxx */,
+ 2744E52E0FC1684700E85C33 /* LexTADS3.cxx */,
+ 2744E52F0FC1684700E85C33 /* LexTAL.cxx */,
+ 2744E5300FC1684700E85C33 /* LexTCL.cxx */,
+ 2744E5310FC1684700E85C33 /* LexTeX.cxx */,
+ 2744E5320FC1684700E85C33 /* LexVB.cxx */,
+ 2744E5330FC1684700E85C33 /* LexVerilog.cxx */,
+ 2744E5340FC1684700E85C33 /* LexVHDL.cxx */,
+ 2744E5350FC1684700E85C33 /* LexYAML.cxx */,
+ );
+ name = Lexers;
+ sourceTree = "<group>";
+ };
+ 2744E47E0FC1675800E85C33 /* Header Files */ = {
+ isa = PBXGroup;
+ children = (
+ 277B5BDB104EE6CF00F40CE4 /* PropSetSimple.h */,
+ 277B5BDC104EE6CF00F40CE4 /* Selection.h */,
+ 2744E4990FC1681200E85C33 /* AutoComplete.h */,
+ 2744E49A0FC1681200E85C33 /* CallTip.h */,
+ 2744E49B0FC1681200E85C33 /* CellBuffer.h */,
+ 2744E49C0FC1681200E85C33 /* CharacterSet.h */,
+ 2744E49D0FC1681200E85C33 /* CharClassify.h */,
+ 2744E49E0FC1681200E85C33 /* ContractionState.h */,
+ 2744E49F0FC1681200E85C33 /* Decoration.h */,
+ 2744E4A00FC1681200E85C33 /* Document.h */,
+ 2744E4A10FC1681200E85C33 /* DocumentAccessor.h */,
+ 2744E4A20FC1681200E85C33 /* Editor.h */,
+ 2744E4A30FC1681200E85C33 /* ExternalLexer.h */,
+ 2744E4A40FC1681200E85C33 /* Indicator.h */,
+ 2744E4A50FC1681200E85C33 /* KeyMap.h */,
+ 2744E4A60FC1681200E85C33 /* LineMarker.h */,
+ 2744E4A70FC1681200E85C33 /* Partitioning.h */,
+ 2744E4A80FC1681200E85C33 /* PerLine.h */,
+ 2744E4A90FC1681200E85C33 /* PositionCache.h */,
+ 2744E4AA0FC1681200E85C33 /* RESearch.h */,
+ 2744E4AB0FC1681200E85C33 /* RunStyles.h */,
+ 2744E4AC0FC1681200E85C33 /* ScintillaBase.h */,
+ 2744E4AD0FC1681200E85C33 /* SplitVector.h */,
+ 2744E4AE0FC1681200E85C33 /* Style.h */,
+ 2744E4AF0FC1681200E85C33 /* StyleContext.h */,
+ 2744E4B00FC1681200E85C33 /* SVector.h */,
+ 2744E4B10FC1681200E85C33 /* UniConversion.h */,
+ 2744E4B20FC1681200E85C33 /* ViewStyle.h */,
+ 2744E4B30FC1681200E85C33 /* XPM.h */,
+ );
+ name = "Header Files";
+ sourceTree = "<group>";
+ };
+ 2744E47F0FC1676400E85C33 /* Source Files */ = {
+ isa = PBXGroup;
+ children = (
+ 277B5BD9104EE6B900F40CE4 /* Selection.cxx */,
+ 2744E4CF0FC1682C00E85C33 /* AutoComplete.cxx */,
+ 2744E4D00FC1682C00E85C33 /* CallTip.cxx */,
+ 2744E4D10FC1682C00E85C33 /* CellBuffer.cxx */,
+ 2744E4D20FC1682C00E85C33 /* CharClassify.cxx */,
+ 2744E4D30FC1682C00E85C33 /* ContractionState.cxx */,
+ 2744E4D40FC1682C00E85C33 /* Decoration.cxx */,
+ 2744E4D50FC1682C00E85C33 /* Document.cxx */,
+ 2744E4D60FC1682C00E85C33 /* DocumentAccessor.cxx */,
+ 2744E4D70FC1682C00E85C33 /* Editor.cxx */,
+ 2744E4D80FC1682C00E85C33 /* ExternalLexer.cxx */,
+ 2744E4D90FC1682C00E85C33 /* Indicator.cxx */,
+ 2744E4DA0FC1682C00E85C33 /* KeyMap.cxx */,
+ 2744E4DB0FC1682C00E85C33 /* KeyWords.cxx */,
+ 2744E5830FC1685C00E85C33 /* LineMarker.cxx */,
+ 2744E5840FC1685C00E85C33 /* PerLine.cxx */,
+ 2744E5850FC1685C00E85C33 /* PositionCache.cxx */,
+ 2744E5860FC1685C00E85C33 /* PropSet.cxx */,
+ 2744E5870FC1685C00E85C33 /* RESearch.cxx */,
+ 2744E5880FC1685C00E85C33 /* RunStyles.cxx */,
+ 2744E5890FC1685C00E85C33 /* ScintillaBase.cxx */,
+ 2744E58A0FC1685C00E85C33 /* Style.cxx */,
+ 2744E58B0FC1685C00E85C33 /* StyleContext.cxx */,
+ 2744E58C0FC1685C00E85C33 /* UniConversion.cxx */,
+ 2744E58D0FC1685C00E85C33 /* ViewStyle.cxx */,
+ 2744E58E0FC1685C00E85C33 /* WindowAccessor.cxx */,
+ 2744E58F0FC1685C00E85C33 /* XPM.cxx */,
+ );
+ name = "Source Files";
+ sourceTree = "<group>";
+ };
+ 2744E4970FC167E400E85C33 /* Header Files */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E59D0FC168A100E85C33 /* InfoBar.h */,
+ 2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */,
+ 2744E59E0FC168A100E85C33 /* PlatCocoa.h */,
+ 2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */,
+ 2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */,
+ 2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */,
+ 2744E5A30FC168A100E85C33 /* ScintillaView.h */,
+ 2744E4830FC1678600E85C33 /* Accessor.h */,
+ 2744E4840FC1678600E85C33 /* KeyWords.h */,
+ 2744E4850FC1678600E85C33 /* Platform.h */,
+ 2744E4860FC1678600E85C33 /* PropSet.h */,
+ 2744E4870FC1678600E85C33 /* SciLexer.h */,
+ 2744E4880FC1678600E85C33 /* Scintilla.h */,
+ 2744E48A0FC1678600E85C33 /* ScintillaWidget.h */,
+ 2744E48C0FC1678600E85C33 /* WindowAccessor.h */,
+ );
+ name = "Header Files";
+ sourceTree = "<group>";
+ };
+ 2744E4980FC167ED00E85C33 /* Source Files */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E5AD0FC168C500E85C33 /* InfoBar.mm */,
+ 2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */,
+ 2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */,
+ 2744E5B10FC168C500E85C33 /* ScintillaView.mm */,
+ );
+ name = "Source Files";
+ sourceTree = "<group>";
+ };
+ 27FEF4500FC1B413005E115A /* res */ = {
+ isa = PBXGroup;
+ children = (
+ 27FEF4510FC1B413005E115A /* info_bar_bg.png */,
+ 27FEF4520FC1B413005E115A /* mac_cursor_busy.png */,
+ 27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */,
+ );
+ name = res;
+ path = ../res;
+ sourceTree = SOURCE_ROOT;
+ };
+ 32C88DFF0371C24200C91783 /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 32DBCF5E0370ADEE00C91783 /* Scintilla_Prefix.pch */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8DC2EF500486A6940098B216 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2791F3EB0FC1A3BD009DBCF9 /* AutoComplete.h in Headers */,
+ 2791F3EC0FC1A3BD009DBCF9 /* CallTip.h in Headers */,
+ 2791F3ED0FC1A3BD009DBCF9 /* CellBuffer.h in Headers */,
+ 2791F3EE0FC1A3BD009DBCF9 /* CharacterSet.h in Headers */,
+ 2791F3EF0FC1A3BD009DBCF9 /* CharClassify.h in Headers */,
+ 2791F3F00FC1A3BD009DBCF9 /* ContractionState.h in Headers */,
+ 2791F3F10FC1A3BD009DBCF9 /* Decoration.h in Headers */,
+ 2791F3F20FC1A3BD009DBCF9 /* Document.h in Headers */,
+ 2791F3F30FC1A3BD009DBCF9 /* DocumentAccessor.h in Headers */,
+ 2791F3F40FC1A3BD009DBCF9 /* Editor.h in Headers */,
+ 2791F3F50FC1A3BD009DBCF9 /* ExternalLexer.h in Headers */,
+ 2791F3F60FC1A3BD009DBCF9 /* Indicator.h in Headers */,
+ 2791F3F70FC1A3BD009DBCF9 /* KeyMap.h in Headers */,
+ 2791F3F80FC1A3BD009DBCF9 /* LineMarker.h in Headers */,
+ 2791F3F90FC1A3BD009DBCF9 /* Partitioning.h in Headers */,
+ 2791F3FA0FC1A3BD009DBCF9 /* PerLine.h in Headers */,
+ 2791F3FB0FC1A3BD009DBCF9 /* PositionCache.h in Headers */,
+ 2791F3FC0FC1A3BD009DBCF9 /* RESearch.h in Headers */,
+ 2791F3FD0FC1A3BD009DBCF9 /* RunStyles.h in Headers */,
+ 2791F3FE0FC1A3BD009DBCF9 /* ScintillaBase.h in Headers */,
+ 2791F3FF0FC1A3BD009DBCF9 /* SplitVector.h in Headers */,
+ 2791F4000FC1A3BD009DBCF9 /* Style.h in Headers */,
+ 2791F4010FC1A3BD009DBCF9 /* StyleContext.h in Headers */,
+ 2791F4020FC1A3BD009DBCF9 /* SVector.h in Headers */,
+ 2791F4030FC1A3BD009DBCF9 /* UniConversion.h in Headers */,
+ 2791F4040FC1A3BD009DBCF9 /* ViewStyle.h in Headers */,
+ 2791F4050FC1A3BD009DBCF9 /* XPM.h in Headers */,
+ 2744E5A40FC168A100E85C33 /* InfoBar.h in Headers */,
+ 2744E5AC0FC168B200E85C33 /* InfoBarCommunicator.h in Headers */,
+ 2791F3C60FC19F71009DBCF9 /* PlatCocoa.h in Headers */,
+ 2791F3E30FC1A3AE009DBCF9 /* QuartzTextLayout.h in Headers */,
+ 2791F3E40FC1A3AE009DBCF9 /* QuartzTextStyleAttribute.h in Headers */,
+ 2791F3E00FC1A390009DBCF9 /* ScintillaCocoa.h in Headers */,
+ 2744E5AA0FC168A100E85C33 /* ScintillaView.h in Headers */,
+ 2791F3E50FC1A3AE009DBCF9 /* Accessor.h in Headers */,
+ 2791F3E60FC1A3AE009DBCF9 /* KeyWords.h in Headers */,
+ 2791F3C70FC19F71009DBCF9 /* Platform.h in Headers */,
+ 2791F3E70FC1A3AE009DBCF9 /* PropSet.h in Headers */,
+ 2791F3C80FC19F71009DBCF9 /* SciLexer.h in Headers */,
+ 2791F3C90FC19F71009DBCF9 /* Scintilla.h in Headers */,
+ 2791F3E80FC1A3AE009DBCF9 /* ScintillaWidget.h in Headers */,
+ 2791F3EA0FC1A3AE009DBCF9 /* WindowAccessor.h in Headers */,
+ 277B5BDD104EE6CF00F40CE4 /* PropSetSimple.h in Headers */,
+ 277B5BDE104EE6CF00F40CE4 /* Selection.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 8DC2EF4F0486A6940098B216 /* Scintilla */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Scintilla" */;
+ buildPhases = (
+ 8DC2EF500486A6940098B216 /* Headers */,
+ 8DC2EF520486A6940098B216 /* Resources */,
+ 8DC2EF540486A6940098B216 /* Sources */,
+ 8DC2EF560486A6940098B216 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Scintilla;
+ productInstallPath = "$(HOME)/Library/Frameworks";
+ productName = Scintilla;
+ productReference = 8DC2EF5B0486A6940098B216 /* Scintilla.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ScintillaFramework" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 0867D691FE84028FC02AAC07 /* Scintilla */;
+ productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DC2EF4F0486A6940098B216 /* Scintilla */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8DC2EF520486A6940098B216 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
+ 27FEF4540FC1B413005E115A /* info_bar_bg.png in Resources */,
+ 27FEF4550FC1B413005E115A /* mac_cursor_busy.png in Resources */,
+ 27FEF4560FC1B413005E115A /* mac_cursor_flipped.png in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DC2EF540486A6940098B216 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2744E4DC0FC1682C00E85C33 /* AutoComplete.cxx in Sources */,
+ 2744E4DD0FC1682C00E85C33 /* CallTip.cxx in Sources */,
+ 2744E4DE0FC1682C00E85C33 /* CellBuffer.cxx in Sources */,
+ 2744E4DF0FC1682C00E85C33 /* CharClassify.cxx in Sources */,
+ 2744E4E00FC1682C00E85C33 /* ContractionState.cxx in Sources */,
+ 2744E4E10FC1682C00E85C33 /* Decoration.cxx in Sources */,
+ 2744E4E20FC1682C00E85C33 /* Document.cxx in Sources */,
+ 2744E4E30FC1682C00E85C33 /* DocumentAccessor.cxx in Sources */,
+ 2744E4E40FC1682C00E85C33 /* Editor.cxx in Sources */,
+ 2744E4E50FC1682C00E85C33 /* ExternalLexer.cxx in Sources */,
+ 2744E4E60FC1682C00E85C33 /* Indicator.cxx in Sources */,
+ 2744E4E70FC1682C00E85C33 /* KeyMap.cxx in Sources */,
+ 2744E4E80FC1682C00E85C33 /* KeyWords.cxx in Sources */,
+ 2744E5360FC1684700E85C33 /* LexAbaqus.cxx in Sources */,
+ 2744E5370FC1684700E85C33 /* LexAda.cxx in Sources */,
+ 2744E5380FC1684700E85C33 /* LexAPDL.cxx in Sources */,
+ 2744E5390FC1684700E85C33 /* LexAsm.cxx in Sources */,
+ 2744E53A0FC1684700E85C33 /* LexAsn1.cxx in Sources */,
+ 2744E53B0FC1684700E85C33 /* LexASY.cxx in Sources */,
+ 2744E53C0FC1684700E85C33 /* LexAU3.cxx in Sources */,
+ 2744E53D0FC1684700E85C33 /* LexAVE.cxx in Sources */,
+ 2744E53E0FC1684700E85C33 /* LexBaan.cxx in Sources */,
+ 2744E53F0FC1684700E85C33 /* LexBash.cxx in Sources */,
+ 2744E5400FC1684700E85C33 /* LexBasic.cxx in Sources */,
+ 2744E5410FC1684700E85C33 /* LexBullant.cxx in Sources */,
+ 2744E5420FC1684700E85C33 /* LexCaml.cxx in Sources */,
+ 2744E5430FC1684700E85C33 /* LexCLW.cxx in Sources */,
+ 2744E5440FC1684700E85C33 /* LexCmake.cxx in Sources */,
+ 2744E5450FC1684700E85C33 /* LexCOBOL.cxx in Sources */,
+ 2744E5460FC1684700E85C33 /* LexConf.cxx in Sources */,
+ 2744E5470FC1684700E85C33 /* LexCPP.cxx in Sources */,
+ 2744E5480FC1684700E85C33 /* LexCrontab.cxx in Sources */,
+ 2744E5490FC1684700E85C33 /* LexCsound.cxx in Sources */,
+ 2744E54A0FC1684700E85C33 /* LexCSS.cxx in Sources */,
+ 2744E54B0FC1684700E85C33 /* LexD.cxx in Sources */,
+ 2744E54C0FC1684700E85C33 /* LexEiffel.cxx in Sources */,
+ 2744E54D0FC1684700E85C33 /* LexErlang.cxx in Sources */,
+ 2744E54E0FC1684700E85C33 /* LexEScript.cxx in Sources */,
+ 2744E54F0FC1684700E85C33 /* LexFlagship.cxx in Sources */,
+ 2744E5500FC1684700E85C33 /* LexForth.cxx in Sources */,
+ 2744E5510FC1684700E85C33 /* LexFortran.cxx in Sources */,
+ 2744E5520FC1684700E85C33 /* LexGAP.cxx in Sources */,
+ 2744E5530FC1684700E85C33 /* LexGui4Cli.cxx in Sources */,
+ 2744E5540FC1684700E85C33 /* LexHaskell.cxx in Sources */,
+ 2744E5550FC1684700E85C33 /* LexHTML.cxx in Sources */,
+ 2744E5560FC1684700E85C33 /* LexInno.cxx in Sources */,
+ 2744E5570FC1684700E85C33 /* LexKix.cxx in Sources */,
+ 2744E5580FC1684700E85C33 /* LexLisp.cxx in Sources */,
+ 2744E5590FC1684700E85C33 /* LexLout.cxx in Sources */,
+ 2744E55A0FC1684700E85C33 /* LexLua.cxx in Sources */,
+ 2744E55B0FC1684700E85C33 /* LexMagik.cxx in Sources */,
+ 2744E55C0FC1684700E85C33 /* LexMatlab.cxx in Sources */,
+ 2744E55D0FC1684700E85C33 /* LexMetapost.cxx in Sources */,
+ 2744E55E0FC1684700E85C33 /* LexMMIXAL.cxx in Sources */,
+ 2744E55F0FC1684700E85C33 /* LexMPT.cxx in Sources */,
+ 2744E5600FC1684700E85C33 /* LexMSSQL.cxx in Sources */,
+ 2744E5610FC1684700E85C33 /* LexMySQL.cxx in Sources */,
+ 2744E5620FC1684700E85C33 /* LexNimrod.cxx in Sources */,
+ 2744E5630FC1684700E85C33 /* LexNsis.cxx in Sources */,
+ 2744E5640FC1684700E85C33 /* LexOpal.cxx in Sources */,
+ 2744E5650FC1684700E85C33 /* LexOthers.cxx in Sources */,
+ 2744E5660FC1684700E85C33 /* LexPascal.cxx in Sources */,
+ 2744E5670FC1684700E85C33 /* LexPB.cxx in Sources */,
+ 2744E5680FC1684700E85C33 /* LexPerl.cxx in Sources */,
+ 2744E5690FC1684700E85C33 /* LexPLM.cxx in Sources */,
+ 2744E56A0FC1684700E85C33 /* LexPOV.cxx in Sources */,
+ 2744E56B0FC1684700E85C33 /* LexPowerPro.cxx in Sources */,
+ 2744E56C0FC1684700E85C33 /* LexPowerShell.cxx in Sources */,
+ 2744E56D0FC1684700E85C33 /* LexProgress.cxx in Sources */,
+ 2744E56E0FC1684700E85C33 /* LexPS.cxx in Sources */,
+ 2744E56F0FC1684700E85C33 /* LexPython.cxx in Sources */,
+ 2744E5700FC1684700E85C33 /* LexR.cxx in Sources */,
+ 2744E5710FC1684700E85C33 /* LexRebol.cxx in Sources */,
+ 2744E5720FC1684700E85C33 /* LexRuby.cxx in Sources */,
+ 2744E5730FC1684700E85C33 /* LexScriptol.cxx in Sources */,
+ 2744E5740FC1684700E85C33 /* LexSmalltalk.cxx in Sources */,
+ 2744E5750FC1684700E85C33 /* LexSML.cxx in Sources */,
+ 2744E5760FC1684700E85C33 /* LexSorcus.cxx in Sources */,
+ 2744E5770FC1684700E85C33 /* LexSpecman.cxx in Sources */,
+ 2744E5780FC1684700E85C33 /* LexSpice.cxx in Sources */,
+ 2744E5790FC1684700E85C33 /* LexSQL.cxx in Sources */,
+ 2744E57A0FC1684700E85C33 /* LexTACL.cxx in Sources */,
+ 2744E57B0FC1684700E85C33 /* LexTADS3.cxx in Sources */,
+ 2744E57C0FC1684700E85C33 /* LexTAL.cxx in Sources */,
+ 2744E57D0FC1684700E85C33 /* LexTCL.cxx in Sources */,
+ 2744E57E0FC1684700E85C33 /* LexTeX.cxx in Sources */,
+ 2744E57F0FC1684700E85C33 /* LexVB.cxx in Sources */,
+ 2744E5800FC1684700E85C33 /* LexVerilog.cxx in Sources */,
+ 2744E5810FC1684700E85C33 /* LexVHDL.cxx in Sources */,
+ 2744E5820FC1684700E85C33 /* LexYAML.cxx in Sources */,
+ 2744E5900FC1685C00E85C33 /* LineMarker.cxx in Sources */,
+ 2744E5910FC1685C00E85C33 /* PerLine.cxx in Sources */,
+ 2744E5920FC1685C00E85C33 /* PositionCache.cxx in Sources */,
+ 2744E5930FC1685C00E85C33 /* PropSet.cxx in Sources */,
+ 2744E5940FC1685C00E85C33 /* RESearch.cxx in Sources */,
+ 2744E5950FC1685C00E85C33 /* RunStyles.cxx in Sources */,
+ 2744E5960FC1685C00E85C33 /* ScintillaBase.cxx in Sources */,
+ 2744E5970FC1685C00E85C33 /* Style.cxx in Sources */,
+ 2744E5980FC1685C00E85C33 /* StyleContext.cxx in Sources */,
+ 2744E5990FC1685C00E85C33 /* UniConversion.cxx in Sources */,
+ 2744E59A0FC1685C00E85C33 /* ViewStyle.cxx in Sources */,
+ 2744E59B0FC1685C00E85C33 /* WindowAccessor.cxx in Sources */,
+ 2744E59C0FC1685C00E85C33 /* XPM.cxx in Sources */,
+ 2744E5B20FC168C500E85C33 /* InfoBar.mm in Sources */,
+ 2744E5B30FC168C500E85C33 /* PlatCocoa.mm in Sources */,
+ 2744E5B50FC168C500E85C33 /* ScintillaCocoa.mm in Sources */,
+ 2744E5B60FC168C500E85C33 /* ScintillaView.mm in Sources */,
+ 277B5BDA104EE6B900F40CE4 /* Selection.cxx in Sources */,
+ 11374AAA10514AA900651FE9 /* LexMarkdown.cxx in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C1667FE841158C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91AE08733DA50010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Scintilla_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ SCI_NAMESPACE,
+ SCI_LEXER,
+ );
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PRODUCT_NAME = Scintilla;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Debug;
+ };
+ 1DEB91AF08733DA50010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Scintilla_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ SCI_NAMESPACE,
+ SCI_LEXER,
+ );
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PRODUCT_NAME = Scintilla;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+ 1DEB91B208733DA50010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ 1DEB91B308733DA50010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Scintilla" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91AE08733DA50010E9CD /* Debug */,
+ 1DEB91AF08733DA50010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ScintillaFramework" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91B208733DA50010E9CD /* Debug */,
+ 1DEB91B308733DA50010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/scintilla/cocoa/ScintillaFramework/Scintilla_Prefix.pch b/scintilla/cocoa/ScintillaFramework/Scintilla_Prefix.pch
new file mode 100644
index 0000000..d14300b
--- /dev/null
+++ b/scintilla/cocoa/ScintillaFramework/Scintilla_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'Scintilla' target in the 'Scintilla' project.
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
diff --git a/scintilla/cocoa/ScintillaListBox.h b/scintilla/cocoa/ScintillaListBox.h
new file mode 100644
index 0000000..9f6b722
--- /dev/null
+++ b/scintilla/cocoa/ScintillaListBox.h
@@ -0,0 +1,64 @@
+
+/*
+ * ScintillaMacOSX.h
+ * tutorial
+ *
+ * Created by Evan Jones on Sun Sep 01 2002.
+ *
+ */
+
+#ifndef SCINTILLA_LISTBOX_H
+#define SCINTILLA_LISTBOX_H
+
+#include "TView.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+static const OSType scintillaListBoxType = 'sclb';
+
+namespace Scintilla {
+
+class ScintillaListBox : public TView
+{
+public:
+ // Private so ScintillaListBox objects can not be copied
+ ScintillaListBox(const ScintillaListBox &) : TView( NULL ) {}
+ ScintillaListBox &operator=(const ScintillaListBox &) { return * this; }
+ ~ScintillaListBox() {};
+
+public:
+ /** This is the class ID that we've assigned to Scintilla. */
+ static const CFStringRef kScintillaListBoxClassID;
+ static const ControlKind kScintillaListBoxKind;
+
+ ScintillaListBox( void* windowid );
+
+ /** Returns the HIView object kind, needed to subclass TView. */
+ virtual ControlKind GetKind() { return kScintillaListBoxKind; }
+
+private:
+
+ virtual ControlPartCode HitTest( const HIPoint& where );
+ virtual void Draw( RgnHandle rgn, CGContextRef gc );
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+
+public:
+ static HIViewRef Create();
+private:
+ static OSStatus Construct( HIViewRef inControl, TView** outView );
+
+};
+
+
+}
+
+
+#endif
diff --git a/scintilla/cocoa/ScintillaListBox.mm b/scintilla/cocoa/ScintillaListBox.mm
new file mode 100644
index 0000000..8c51785
--- /dev/null
+++ b/scintilla/cocoa/ScintillaListBox.mm
@@ -0,0 +1,110 @@
+
+#include "ScintillaCocoa.h"
+#include "ScintillaListBox.h"
+
+using namespace Scintilla;
+
+const CFStringRef ScintillaListBox::kScintillaListBoxClassID = CFSTR( "org.scintilla.listbox" );
+const ControlKind ScintillaListBox::kScintillaListBoxKind = { 'ejon', 'Sclb' };
+
+ScintillaListBox::ScintillaListBox( void* windowid ) :
+ TView( reinterpret_cast<HIViewRef>( windowid ) )
+{
+ ActivateInterface( kMouse );
+ // debugPrint = true;
+}
+
+void ScintillaListBox::Draw(
+ RgnHandle /*inLimitRgn*/,
+ CGContextRef inContext )
+{
+ Rect contentBounds;
+ GetControlBounds(GetViewRef(), &contentBounds);
+
+ HIRect controlFrame;
+ HIViewGetFrame( GetViewRef(), &controlFrame );
+
+ // what is the global pos?
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow)
+ {
+ surfaceWindow->Init(inContext, GetViewRef());
+
+ // TODO: Implement or find workaround
+ // ctip->PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+
+}
+
+ControlPartCode ScintillaListBox::HitTest( const HIPoint& where )
+{
+ if ( CGRectContainsPoint( Bounds(), where ) )
+ return 1;
+ else
+ return kControlNoPart;
+}
+
+OSStatus ScintillaListBox::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ ListBox* ctip = NULL;
+ ScintillaCocoa *sciThis = NULL;
+ OSStatus err = GetControlProperty( GetViewRef(), scintillaListBoxType, 0, sizeof( ctip ), NULL, &ctip );
+ err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis );
+
+ // TODO: Implement of find work around.
+ // ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ));
+
+ // TODO: still needed?
+ // sciThis->ListBoxClick();
+ return noErr;
+}
+
+OSStatus ScintillaListBox::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ return noErr;
+}
+
+HIViewRef ScintillaListBox::Create()
+{
+ // Register the HIView, if needed
+ static bool registered = false;
+
+ if ( not registered )
+ {
+ TView::RegisterSubclass( kScintillaListBoxClassID, Construct );
+ registered = true;
+ }
+
+ OSStatus err = noErr;
+ EventRef event = CreateInitializationEvent();
+ assert( event != NULL );
+
+ HIViewRef control = NULL;
+ err = HIObjectCreate( kScintillaListBoxClassID, event, reinterpret_cast<HIObjectRef*>( &control ) );
+ ReleaseEvent( event );
+ if ( err == noErr ) {
+ Platform::DebugPrintf("ScintillaListBox::Create control %08X\n",control);
+ return control;
+ }
+ return NULL;
+}
+
+OSStatus ScintillaListBox::Construct( HIViewRef inControl, TView** outView )
+{
+ *outView = new ScintillaListBox( inControl );
+ Platform::DebugPrintf("ScintillaListBox::Construct scintilla %08X\n",*outView);
+ if ( *outView != NULL )
+ return noErr;
+ else
+ return memFullErr;
+}
+
+extern "C" {
+HIViewRef scintilla_listbox_new() {
+ return ScintillaListBox::Create();
+}
+}
diff --git a/scintilla/cocoa/ScintillaTest/AppController.h b/scintilla/cocoa/ScintillaTest/AppController.h
new file mode 100644
index 0000000..fe84e0a
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/AppController.h
@@ -0,0 +1,23 @@
+/**
+ * AppController.h
+ * SciTest
+ *
+ * Created by Mike Lischke on 01.04.09.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#import "ScintillaView.h"
+#import "InfoBar.h"
+
+@interface AppController : NSObject {
+ IBOutlet NSBox *mEditHost;
+ ScintillaView* mEditor;
+}
+
+- (void) awakeFromNib;
+- (void) setupEditor;
+
+@end
diff --git a/scintilla/cocoa/ScintillaTest/AppController.mm b/scintilla/cocoa/ScintillaTest/AppController.mm
new file mode 100644
index 0000000..217bc9c
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/AppController.mm
@@ -0,0 +1,215 @@
+/**
+ * AppController.m
+ * ScintillaTest
+ *
+ * Created by Mike Lischke on 01.04.09.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import "AppController.h"
+
+const char major_keywords[] =
+ "accessible add all alter analyze and as asc asensitive "
+ "before between bigint binary blob both by "
+ "call cascade case change char character check collate column condition connection constraint "
+ "continue convert create cross current_date current_time current_timestamp current_user cursor "
+ "database databases day_hour day_microsecond day_minute day_second dec decimal declare default "
+ "delayed delete desc describe deterministic distinct distinctrow div double drop dual "
+ "each else elseif enclosed escaped exists exit explain "
+ "false fetch float float4 float8 for force foreign from fulltext "
+ "goto grant group "
+ "having high_priority hour_microsecond hour_minute hour_second "
+ "if ignore in index infile inner inout insensitive insert int int1 int2 int3 int4 int8 integer "
+ "interval into is iterate "
+ "join "
+ "key keys kill "
+ "label leading leave left like limit linear lines load localtime localtimestamp lock long "
+ "longblob longtext loop low_priority "
+ "master_ssl_verify_server_cert match mediumblob mediumint mediumtext middleint minute_microsecond "
+ "minute_second mod modifies "
+ "natural not no_write_to_binlog null numeric "
+ "on optimize option optionally or order out outer outfile "
+ "precision primary procedure purge "
+ "range read reads read_only read_write real references regexp release rename repeat replace "
+ "require restrict return revoke right rlike "
+ "schema schemas second_microsecond select sensitive separator set show smallint spatial specific "
+ "sql sqlexception sqlstate sqlwarning sql_big_result sql_calc_found_rows sql_small_result ssl "
+ "starting straight_join "
+ "table terminated then tinyblob tinyint tinytext to trailing trigger true "
+ "undo union unique unlock unsigned update upgrade usage use using utc_date utc_time utc_timestamp "
+ "values varbinary varchar varcharacter varying "
+ "when where while with write "
+ "xor "
+ "year_month "
+ "zerofill";
+
+const char procedure_keywords[] = // Not reserved words but intrinsic part of procedure definitions.
+ "begin comment end";
+
+const char client_keywords[] = // Definition of keywords only used by clients, not the server itself.
+ "delimiter";
+
+const char user_keywords[] = // Definition of own keywords, not used by MySQL.
+ "edit";
+
+//--------------------------------------------------------------------------------------------------
+
+@implementation AppController
+
+- (void) awakeFromNib
+{
+ // Manually set up the scintilla editor. Create an instance and dock it to our edit host.
+ // Leave some free space around the new view to avoid overlapping with the box borders.
+ NSRect newFrame = mEditHost.frame;
+ newFrame.size.width -= 2 * newFrame.origin.x;
+ newFrame.size.height -= 3 * newFrame.origin.y;
+
+ mEditor = [[[ScintillaView alloc] initWithFrame: newFrame] autorelease];
+
+ [mEditHost.contentView addSubview: mEditor];
+ [mEditor setAutoresizesSubviews: YES];
+ [mEditor setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
+
+ // Let's load some text for the editor, as initial content.
+ NSError* error = nil;
+
+ NSString* path = [[NSBundle mainBundle] pathForResource: @"TestData"
+ ofType: @"sql" inDirectory: nil];
+
+ NSString* sql = [NSString stringWithContentsOfFile: path
+ encoding: NSUTF8StringEncoding
+ error: &error];
+ if (error && [[error domain] isEqual: NSCocoaErrorDomain])
+ NSLog(@"%@", error);
+
+ [mEditor setString: sql];
+
+ [self setupEditor];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Initialize scintilla editor (styles, colors, markers, folding etc.].
+ */
+- (void) setupEditor
+{
+ // Lexer type is MySQL.
+ [mEditor setGeneralProperty: SCI_SETLEXER parameter: SCLEX_MYSQL value: 0];
+ // alternatively: [mEditor setEditorProperty: SCI_SETLEXERLANGUAGE parameter: nil value: (sptr_t) "mysql"];
+
+ // Number of styles we use with this lexer.
+ [mEditor setGeneralProperty: SCI_SETSTYLEBITS parameter: 5 value: 0];
+
+ // Keywords to highlight. Indices are:
+ // 0 - Major keywords (reserved keywords)
+ // 1 - Normal keywords (everything not reserved but integral part of the language)
+ // 2 - Database objects
+ // 3 - Function keywords
+ // 4 - System variable keywords
+ // 5 - Procedure keywords (keywords used in procedures like "begin" and "end")
+ // 6..8 - User keywords 1..3
+ [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 0 value: major_keywords];
+ [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 5 value: procedure_keywords];
+ [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 6 value: client_keywords];
+ [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords];
+
+ // Colors and styles for various syntactic elements. First the default style.
+ [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Andale Mono"];
+ // [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font.
+ [mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]];
+
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DEFAULT value: [NSColor blackColor]];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENT fromHTML: @"#097BF7"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENTLINE fromHTML: @"#097BF7"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#097BF7"];
+ [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#F0F0F0"];
+
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_VARIABLE fromHTML: @"378EA5"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SYSTEMVARIABLE fromHTML: @"378EA5"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KNOWNSYSTEMVARIABLE fromHTML: @"#3A37A5"];
+
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_NUMBER fromHTML: @"#7F7F00"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SQSTRING fromHTML: @"#FFAA3E"];
+
+ // Note: if we were using ANSI quotes we would set the DQSTRING to the same color as the
+ // the back tick string.
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DQSTRING fromHTML: @"#274A6D"];
+
+ // Keyword highlighting.
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_MAJORKEYWORD fromHTML: @"#007F00"];
+ [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_MAJORKEYWORD value: 1];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KEYWORD fromHTML: @"#007F00"];
+ [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_KEYWORD value: 1];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_PROCEDUREKEYWORD fromHTML: @"#56007F"];
+ [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_PROCEDUREKEYWORD value: 1];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER1 fromHTML: @"#808080"];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER2 fromHTML: @"#808080"];
+ [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_USER2 fromHTML: @"#F0E0E0"];
+
+ // The following 3 styles have no impact as we did not set a keyword list for any of them.
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DATABASEOBJECT value: [NSColor redColor]];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_FUNCTION value: [NSColor redColor]];
+
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_IDENTIFIER value: [NSColor blackColor]];
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_QUOTEDIDENTIFIER fromHTML: @"#274A6D"];
+ [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_SQL_OPERATOR value: 1];
+
+ // Line number style.
+ [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_LINENUMBER fromHTML: @"#F0F0F0"];
+ [mEditor setColorProperty: SCI_STYLESETBACK parameter: STYLE_LINENUMBER fromHTML: @"#808080"];
+
+ [mEditor setGeneralProperty: SCI_SETMARGINTYPEN parameter: 0 value: SC_MARGIN_NUMBER];
+ [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 0 value: 35];
+
+ // Markers.
+ [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 1 value: 16];
+
+ // Some special lexer properties.
+ [mEditor setLexerProperty: @"fold" value: @"1"];
+ [mEditor setLexerProperty: @"fold.compact" value: @"0"];
+ [mEditor setLexerProperty: @"fold.comment" value: @"1"];
+ [mEditor setLexerProperty: @"fold.preprocessor" value: @"1"];
+
+ // Folder setup.
+ [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 2 value: 16];
+ [mEditor setGeneralProperty: SCI_SETMARGINMASKN parameter: 2 value: SC_MASK_FOLDERS];
+ [mEditor setGeneralProperty: SCI_SETMARGINSENSITIVEN parameter: 2 value: 1];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPEN value: SC_MARK_BOXMINUS];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDER value: SC_MARK_BOXPLUS];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERSUB value: SC_MARK_VLINE];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERTAIL value: SC_MARK_LCORNER];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEREND value: SC_MARK_BOXPLUSCONNECTED];
+ [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPENMID value: SC_MARK_BOXMINUSCONNECTED];
+ [mEditor setGeneralProperty
+ : SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERMIDTAIL value: SC_MARK_TCORNER];
+ for (int n= 25; n < 32; ++n) // Markers 25..31 are reserved for folding.
+ {
+ [mEditor setColorProperty: SCI_MARKERSETFORE parameter: n value: [NSColor whiteColor]];
+ [mEditor setColorProperty: SCI_MARKERSETBACK parameter: n value: [NSColor blackColor]];
+ }
+
+ // Init markers & indicators for highlighting of syntax errors.
+ [mEditor setColorProperty: SCI_INDICSETFORE parameter: 0 value: [NSColor redColor]];
+ [mEditor setGeneralProperty: SCI_INDICSETUNDER parameter: 0 value: 1];
+ [mEditor setGeneralProperty: SCI_INDICSETSTYLE parameter: 0 value: INDIC_SQUIGGLE];
+
+ [mEditor setColorProperty: SCI_MARKERSETBACK parameter: 0 fromHTML: @"#B1151C"];
+
+ [mEditor setColorProperty: SCI_SETSELBACK parameter: 1 value: [NSColor selectedTextBackgroundColor]];
+
+ // Uncomment if you wanna see auto wrapping in action.
+ //[mEditor setGeneralProperty: SCI_SETWRAPMODE parameter: SC_WRAP_WORD value: 0];
+
+ InfoBar* infoBar = [[[InfoBar alloc] initWithFrame: NSMakeRect(0, 0, 400, 0)] autorelease];
+ [infoBar setDisplay: IBShowAll];
+ [mEditor setInfoBar: infoBar top: NO];
+ [mEditor setStatusText: @"Operation complete"];
+}
+
+@end
+
+//--------------------------------------------------------------------------------------------------
+
diff --git a/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings b/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..85e4bb6
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib b/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib
new file mode 100644
index 0000000..253d29d
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/English.lproj/MainMenu.xib
@@ -0,0 +1,3185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">9G55</string>
+ <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.AppKitVersion">949.43</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="372"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1021">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSCustomObject" id="1014">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1050">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSMenu" id="649796088">
+ <string key="NSTitle">AMainMenu</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="694149608">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">NewApplication</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <object class="NSCustomResource" key="NSOnImage" id="35465992">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuCheckmark</string>
+ </object>
+ <object class="NSCustomResource" key="NSMixedImage" id="502551668">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSMenuMixedState</string>
+ </object>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="110575045">
+ <string key="NSTitle">NewApplication</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="238522557">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">About NewApplication</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="304266470">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="609285721">
+ <reference key="NSMenu" ref="110575045"/>
+ <string type="base64-UTF8" key="NSTitle">UHJlZmVyZW5jZXPigKY</string>
+ <string key="NSKeyEquiv">,</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="481834944">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1046388886">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Services</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="752062318">
+ <string key="NSTitle">Services</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <string key="NSName">_NSServicesMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="646227648">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="755159360">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Hide NewApplication</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="342932134">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Hide Others</string>
+ <string key="NSKeyEquiv">h</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="908899353">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Show All</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1056857174">
+ <reference key="NSMenu" ref="110575045"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="632727374">
+ <reference key="NSMenu" ref="110575045"/>
+ <string key="NSTitle">Quit NewApplication</string>
+ <string key="NSKeyEquiv">q</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ <string key="NSName">_NSAppleMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="379814623">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">File</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="720053764">
+ <string key="NSTitle">File</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="705341025">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">New</string>
+ <string key="NSKeyEquiv">n</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="722745758">
+ <reference key="NSMenu" ref="720053764"/>
+ <string type="base64-UTF8" key="NSTitle">T3BlbuKApg</string>
+ <string key="NSKeyEquiv">o</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1025936716">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">Open Recent</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="1065607017">
+ <string key="NSTitle">Open Recent</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="759406840">
+ <reference key="NSMenu" ref="1065607017"/>
+ <string key="NSTitle">Clear Menu</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ <string key="NSName">_NSRecentDocumentsMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="425164168">
+ <reference key="NSMenu" ref="720053764"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="776162233">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">Close</string>
+ <string key="NSKeyEquiv">w</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1023925487">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">Save</string>
+ <string key="NSKeyEquiv">s</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="117038363">
+ <reference key="NSMenu" ref="720053764"/>
+ <string type="base64-UTF8" key="NSTitle">U2F2ZSBBc+KApg</string>
+ <string key="NSKeyEquiv">S</string>
+ <int key="NSKeyEquivModMask">1179648</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="579971712">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">Revert to Saved</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1010469920">
+ <reference key="NSMenu" ref="720053764"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="294629803">
+ <reference key="NSMenu" ref="720053764"/>
+ <string key="NSTitle">Page Setup...</string>
+ <string key="NSKeyEquiv">P</string>
+ <int key="NSKeyEquivModMask">1179648</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSToolTip"/>
+ </object>
+ <object class="NSMenuItem" id="49223823">
+ <reference key="NSMenu" ref="720053764"/>
+ <string type="base64-UTF8" key="NSTitle">UHJpbnTigKY</string>
+ <string key="NSKeyEquiv">p</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="952259628">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Edit</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="789758025">
+ <string key="NSTitle">Edit</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="1058277027">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Undo</string>
+ <string key="NSKeyEquiv">z</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="790794224">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Redo</string>
+ <string key="NSKeyEquiv">Z</string>
+ <int key="NSKeyEquivModMask">1179648</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1040322652">
+ <reference key="NSMenu" ref="789758025"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="296257095">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Cut</string>
+ <string key="NSKeyEquiv">x</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="860595796">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Copy</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="29853731">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Paste</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="437104165">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Delete</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="583158037">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Select All</string>
+ <string key="NSKeyEquiv">a</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="212016141">
+ <reference key="NSMenu" ref="789758025"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="892235320">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Find</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="963351320">
+ <string key="NSTitle">Find</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="447796847">
+ <reference key="NSMenu" ref="963351320"/>
+ <string type="base64-UTF8" key="NSTitle">RmluZOKApg</string>
+ <string key="NSKeyEquiv">f</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">1</int>
+ </object>
+ <object class="NSMenuItem" id="326711663">
+ <reference key="NSMenu" ref="963351320"/>
+ <string key="NSTitle">Find Next</string>
+ <string key="NSKeyEquiv">g</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">2</int>
+ </object>
+ <object class="NSMenuItem" id="270902937">
+ <reference key="NSMenu" ref="963351320"/>
+ <string key="NSTitle">Find Previous</string>
+ <string key="NSKeyEquiv">G</string>
+ <int key="NSKeyEquivModMask">1179648</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">3</int>
+ </object>
+ <object class="NSMenuItem" id="159080638">
+ <reference key="NSMenu" ref="963351320"/>
+ <string key="NSTitle">Use Selection for Find</string>
+ <string key="NSKeyEquiv">e</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">7</int>
+ </object>
+ <object class="NSMenuItem" id="88285865">
+ <reference key="NSMenu" ref="963351320"/>
+ <string key="NSTitle">Jump to Selection</string>
+ <string key="NSKeyEquiv">j</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="972420730">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Spelling and Grammar</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="769623530">
+ <string key="NSTitle">Spelling and Grammar</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="679648819">
+ <reference key="NSMenu" ref="769623530"/>
+ <string type="base64-UTF8" key="NSTitle">U2hvdyBTcGVsbGluZ+KApg</string>
+ <string key="NSKeyEquiv">:</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="96193923">
+ <reference key="NSMenu" ref="769623530"/>
+ <string key="NSTitle">Check Spelling</string>
+ <string key="NSKeyEquiv">;</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="948374510">
+ <reference key="NSMenu" ref="769623530"/>
+ <string key="NSTitle">Check Spelling While Typing</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="967646866">
+ <reference key="NSMenu" ref="769623530"/>
+ <string key="NSTitle">Check Grammar With Spelling</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="507821607">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Substitutions</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="698887838">
+ <string key="NSTitle">Substitutions</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="605118523">
+ <reference key="NSMenu" ref="698887838"/>
+ <string key="NSTitle">Smart Copy/Paste</string>
+ <string key="NSKeyEquiv">f</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">1</int>
+ </object>
+ <object class="NSMenuItem" id="197661976">
+ <reference key="NSMenu" ref="698887838"/>
+ <string key="NSTitle">Smart Quotes</string>
+ <string key="NSKeyEquiv">g</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">2</int>
+ </object>
+ <object class="NSMenuItem" id="708854459">
+ <reference key="NSMenu" ref="698887838"/>
+ <string key="NSTitle">Smart Links</string>
+ <string key="NSKeyEquiv">G</string>
+ <int key="NSKeyEquivModMask">1179648</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">3</int>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="676164635">
+ <reference key="NSMenu" ref="789758025"/>
+ <string key="NSTitle">Speech</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="785027613">
+ <string key="NSTitle">Speech</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="731782645">
+ <reference key="NSMenu" ref="785027613"/>
+ <string key="NSTitle">Start Speaking</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="680220178">
+ <reference key="NSMenu" ref="785027613"/>
+ <string key="NSTitle">Stop Speaking</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="302598603">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Format</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="941447902">
+ <string key="NSTitle">Format</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="792887677">
+ <reference key="NSMenu" ref="941447902"/>
+ <string key="NSTitle">Font</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="786677654">
+ <string key="NSTitle">Font</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="159677712">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Show Fonts</string>
+ <string key="NSKeyEquiv">t</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="305399458">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Bold</string>
+ <string key="NSKeyEquiv">b</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">2</int>
+ </object>
+ <object class="NSMenuItem" id="814362025">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Italic</string>
+ <string key="NSKeyEquiv">i</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">1</int>
+ </object>
+ <object class="NSMenuItem" id="330926929">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Underline</string>
+ <string key="NSKeyEquiv">u</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="533507878">
+ <reference key="NSMenu" ref="786677654"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="158063935">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Bigger</string>
+ <string key="NSKeyEquiv">+</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">3</int>
+ </object>
+ <object class="NSMenuItem" id="885547335">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Smaller</string>
+ <string key="NSKeyEquiv">-</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <int key="NSTag">4</int>
+ </object>
+ <object class="NSMenuItem" id="901062459">
+ <reference key="NSMenu" ref="786677654"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="767671776">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Kern</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="175441468">
+ <string key="NSTitle">Kern</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="252969304">
+ <reference key="NSMenu" ref="175441468"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="766922938">
+ <reference key="NSMenu" ref="175441468"/>
+ <string key="NSTitle">Use None</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="677519740">
+ <reference key="NSMenu" ref="175441468"/>
+ <string key="NSTitle">Tighten</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="238351151">
+ <reference key="NSMenu" ref="175441468"/>
+ <string key="NSTitle">Loosen</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="691570813">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Ligature</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="1058217995">
+ <string key="NSTitle">Ligature</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="706297211">
+ <reference key="NSMenu" ref="1058217995"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="568384683">
+ <reference key="NSMenu" ref="1058217995"/>
+ <string key="NSTitle">Use None</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="663508465">
+ <reference key="NSMenu" ref="1058217995"/>
+ <string key="NSTitle">Use All</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="769124883">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Baseline</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="18263474">
+ <string key="NSTitle">Baseline</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="257962622">
+ <reference key="NSMenu" ref="18263474"/>
+ <string key="NSTitle">Use Default</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="644725453">
+ <reference key="NSMenu" ref="18263474"/>
+ <string key="NSTitle">Superscript</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1037576581">
+ <reference key="NSMenu" ref="18263474"/>
+ <string key="NSTitle">Subscript</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="941806246">
+ <reference key="NSMenu" ref="18263474"/>
+ <string key="NSTitle">Raise</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1045724900">
+ <reference key="NSMenu" ref="18263474"/>
+ <string key="NSTitle">Lower</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="739652853">
+ <reference key="NSMenu" ref="786677654"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="1012600125">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Show Colors</string>
+ <string key="NSKeyEquiv">C</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="214559597">
+ <reference key="NSMenu" ref="786677654"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="596732606">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Copy Style</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="393423671">
+ <reference key="NSMenu" ref="786677654"/>
+ <string key="NSTitle">Paste Style</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ <string key="NSName">_NSFontMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="15516124">
+ <reference key="NSMenu" ref="941447902"/>
+ <string key="NSTitle">Text</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="23081656">
+ <string key="NSTitle">Text</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="135107054">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Align Left</string>
+ <string key="NSKeyEquiv">{</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="310547522">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Center</string>
+ <string key="NSKeyEquiv">|</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="436088763">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Justify</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="498119243">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Align Right</string>
+ <string key="NSKeyEquiv">}</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="607995063">
+ <reference key="NSMenu" ref="23081656"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="420564933">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Show Ruler</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="479856769">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Copy Ruler</string>
+ <string key="NSKeyEquiv">c</string>
+ <int key="NSKeyEquivModMask">1310720</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="333628178">
+ <reference key="NSMenu" ref="23081656"/>
+ <string key="NSTitle">Paste Ruler</string>
+ <string key="NSKeyEquiv">v</string>
+ <int key="NSKeyEquivModMask">1310720</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="586577488">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">View</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="466310130">
+ <string key="NSTitle">View</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="102151532">
+ <reference key="NSMenu" ref="466310130"/>
+ <string key="NSTitle">Show Toolbar</string>
+ <string key="NSKeyEquiv">t</string>
+ <int key="NSKeyEquivModMask">1572864</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="237841660">
+ <reference key="NSMenu" ref="466310130"/>
+ <string type="base64-UTF8" key="NSTitle">Q3VzdG9taXplIFRvb2xiYXLigKY</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="713487014">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Window</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="835318025">
+ <string key="NSTitle">Window</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="1011231497">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Minimize</string>
+ <string key="NSKeyEquiv">m</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="575023229">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Zoom</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="299356726">
+ <reference key="NSMenu" ref="835318025"/>
+ <bool key="NSIsDisabled">YES</bool>
+ <bool key="NSIsSeparator">YES</bool>
+ <string key="NSTitle"/>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ <object class="NSMenuItem" id="625202149">
+ <reference key="NSMenu" ref="835318025"/>
+ <string key="NSTitle">Bring All to Front</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ <string key="NSName">_NSWindowsMenu</string>
+ </object>
+ </object>
+ <object class="NSMenuItem" id="391199113">
+ <reference key="NSMenu" ref="649796088"/>
+ <string key="NSTitle">Help</string>
+ <string key="NSKeyEquiv"/>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ <string key="NSAction">submenuAction:</string>
+ <object class="NSMenu" key="NSSubmenu" id="374024848">
+ <string key="NSTitle">Help</string>
+ <object class="NSMutableArray" key="NSMenuItems">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMenuItem" id="238773614">
+ <reference key="NSMenu" ref="374024848"/>
+ <string key="NSTitle">NewApplication Help</string>
+ <string key="NSKeyEquiv">?</string>
+ <int key="NSKeyEquivModMask">1048576</int>
+ <int key="NSMnemonicLoc">2147483647</int>
+ <reference key="NSOnImage" ref="35465992"/>
+ <reference key="NSMixedImage" ref="502551668"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <string key="NSName">_NSMainMenu</string>
+ </object>
+ <object class="NSWindowTemplate" id="972006081">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{335, 58}, {982, 692}}</string>
+ <int key="NSWTFlags">1946157056</int>
+ <string key="NSWindowTitle">Window</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <nil key="NSViewClass"/>
+ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ <object class="NSView" key="NSWindowView" id="439893737">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">319</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSBox" id="1016473779">
+ <reference key="NSNextResponder" ref="439893737"/>
+ <int key="NSvFlags">18</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSView" id="33804839">
+ <reference key="NSNextResponder" ref="1016473779"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrame">{{1, 1}, {842, 640}}</string>
+ <reference key="NSSuperview" ref="1016473779"/>
+ </object>
+ </object>
+ <string key="NSFrame">{{17, 16}, {844, 656}}</string>
+ <reference key="NSSuperview" ref="439893737"/>
+ <string key="NSOffsets">{0, 0}</string>
+ <object class="NSTextFieldCell" key="NSTitleCell">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">0</int>
+ <string key="NSContents">Scintilla Editor</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.100000e+01</double>
+ <int key="NSfFlags">3100</int>
+ </object>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+ </object>
+ </object>
+ <reference key="NSContentView" ref="33804839"/>
+ <int key="NSBorderType">1</int>
+ <int key="NSBoxType">0</int>
+ <int key="NSTitlePosition">2</int>
+ <bool key="NSTransparent">NO</bool>
+ </object>
+ <object class="NSButton" id="610247741">
+ <reference key="NSNextResponder" ref="439893737"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{872, 12}, {96, 32}}</string>
+ <reference key="NSSuperview" ref="439893737"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="1009897894">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">Quit</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">1.300000e+01</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="610247741"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{982, 692}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
+ <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+ </object>
+ <object class="NSCustomObject" id="755631768">
+ <string key="NSClassName">NSFontManager</string>
+ </object>
+ <object class="NSCustomObject" id="229445039">
+ <string key="NSClassName">AppController</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performMiniaturize:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1011231497"/>
+ </object>
+ <int key="connectionID">37</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">arrangeInFront:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="625202149"/>
+ </object>
+ <int key="connectionID">39</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">print:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="49223823"/>
+ </object>
+ <int key="connectionID">86</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">runPageLayout:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="294629803"/>
+ </object>
+ <int key="connectionID">87</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">clearRecentDocuments:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="759406840"/>
+ </object>
+ <int key="connectionID">127</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontStandardAboutPanel:</string>
+ <reference key="source" ref="1021"/>
+ <reference key="destination" ref="238522557"/>
+ </object>
+ <int key="connectionID">142</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performClose:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="776162233"/>
+ </object>
+ <int key="connectionID">193</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleContinuousSpellChecking:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="948374510"/>
+ </object>
+ <int key="connectionID">222</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">undo:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1058277027"/>
+ </object>
+ <int key="connectionID">223</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copy:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="860595796"/>
+ </object>
+ <int key="connectionID">224</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">checkSpelling:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="96193923"/>
+ </object>
+ <int key="connectionID">225</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">paste:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="29853731"/>
+ </object>
+ <int key="connectionID">226</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">stopSpeaking:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="680220178"/>
+ </object>
+ <int key="connectionID">227</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">cut:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="296257095"/>
+ </object>
+ <int key="connectionID">228</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">showGuessPanel:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="679648819"/>
+ </object>
+ <int key="connectionID">230</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">redo:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="790794224"/>
+ </object>
+ <int key="connectionID">231</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">selectAll:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="583158037"/>
+ </object>
+ <int key="connectionID">232</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">startSpeaking:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="731782645"/>
+ </object>
+ <int key="connectionID">233</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">delete:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="437104165"/>
+ </object>
+ <int key="connectionID">235</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performZoom:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="575023229"/>
+ </object>
+ <int key="connectionID">240</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">performFindPanelAction:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="447796847"/>
+ </object>
+ <int key="connectionID">241</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">centerSelectionInVisibleArea:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="88285865"/>
+ </object>
+ <int key="connectionID">245</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleGrammarChecking:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="967646866"/>
+ </object>
+ <int key="connectionID">347</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleSmartInsertDelete:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="605118523"/>
+ </object>
+ <int key="connectionID">355</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticQuoteSubstitution:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="197661976"/>
+ </object>
+ <int key="connectionID">356</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleAutomaticLinkDetection:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="708854459"/>
+ </object>
+ <int key="connectionID">357</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">showHelp:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="238773614"/>
+ </object>
+ <int key="connectionID">360</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">saveDocument:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1023925487"/>
+ </object>
+ <int key="connectionID">362</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">saveDocumentAs:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="117038363"/>
+ </object>
+ <int key="connectionID">363</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">revertDocumentToSaved:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="579971712"/>
+ </object>
+ <int key="connectionID">364</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">runToolbarCustomizationPalette:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="237841660"/>
+ </object>
+ <int key="connectionID">365</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleToolbarShown:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="102151532"/>
+ </object>
+ <int key="connectionID">366</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hide:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="755159360"/>
+ </object>
+ <int key="connectionID">367</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">hideOtherApplications:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="342932134"/>
+ </object>
+ <int key="connectionID">368</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">unhideAllApplications:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="908899353"/>
+ </object>
+ <int key="connectionID">370</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">newDocument:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="705341025"/>
+ </object>
+ <int key="connectionID">373</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">openDocument:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="722745758"/>
+ </object>
+ <int key="connectionID">374</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">addFontTrait:</string>
+ <reference key="source" ref="755631768"/>
+ <reference key="destination" ref="305399458"/>
+ </object>
+ <int key="connectionID">421</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">addFontTrait:</string>
+ <reference key="source" ref="755631768"/>
+ <reference key="destination" ref="814362025"/>
+ </object>
+ <int key="connectionID">422</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">modifyFont:</string>
+ <reference key="source" ref="755631768"/>
+ <reference key="destination" ref="885547335"/>
+ </object>
+ <int key="connectionID">423</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontFontPanel:</string>
+ <reference key="source" ref="755631768"/>
+ <reference key="destination" ref="159677712"/>
+ </object>
+ <int key="connectionID">424</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">modifyFont:</string>
+ <reference key="source" ref="755631768"/>
+ <reference key="destination" ref="158063935"/>
+ </object>
+ <int key="connectionID">425</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">raiseBaseline:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="941806246"/>
+ </object>
+ <int key="connectionID">426</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">lowerBaseline:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1045724900"/>
+ </object>
+ <int key="connectionID">427</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copyFont:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="596732606"/>
+ </object>
+ <int key="connectionID">428</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">subscript:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1037576581"/>
+ </object>
+ <int key="connectionID">429</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">superscript:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="644725453"/>
+ </object>
+ <int key="connectionID">430</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">tightenKerning:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="677519740"/>
+ </object>
+ <int key="connectionID">431</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">underline:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="330926929"/>
+ </object>
+ <int key="connectionID">432</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">orderFrontColorPanel:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="1012600125"/>
+ </object>
+ <int key="connectionID">433</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useAllLigatures:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="663508465"/>
+ </object>
+ <int key="connectionID">434</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">loosenKerning:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="238351151"/>
+ </object>
+ <int key="connectionID">435</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">pasteFont:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="393423671"/>
+ </object>
+ <int key="connectionID">436</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">unscript:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="257962622"/>
+ </object>
+ <int key="connectionID">437</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useStandardKerning:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="252969304"/>
+ </object>
+ <int key="connectionID">438</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">useStandardLigatures:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="706297211"/>
+ </object>
+ <int key="connectionID">439</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">turnOffLigatures:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="568384683"/>
+ </object>
+ <int key="connectionID">440</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">turnOffKerning:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="766922938"/>
+ </object>
+ <int key="connectionID">441</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignLeft:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="135107054"/>
+ </object>
+ <int key="connectionID">442</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignJustified:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="436088763"/>
+ </object>
+ <int key="connectionID">443</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">copyRuler:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="479856769"/>
+ </object>
+ <int key="connectionID">444</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignCenter:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="310547522"/>
+ </object>
+ <int key="connectionID">445</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">toggleRuler:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="420564933"/>
+ </object>
+ <int key="connectionID">446</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">alignRight:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="498119243"/>
+ </object>
+ <int key="connectionID">447</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">pasteRuler:</string>
+ <reference key="source" ref="1014"/>
+ <reference key="destination" ref="333628178"/>
+ </object>
+ <int key="connectionID">448</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">terminate:</string>
+ <reference key="source" ref="1050"/>
+ <reference key="destination" ref="632727374"/>
+ </object>
+ <int key="connectionID">449</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">mEditHost</string>
+ <reference key="source" ref="229445039"/>
+ <reference key="destination" ref="1016473779"/>
+ </object>
+ <int key="connectionID">454</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">terminate:</string>
+ <reference key="source" ref="1050"/>
+ <reference key="destination" ref="610247741"/>
+ </object>
+ <int key="connectionID">455</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="1049">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1048"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1021"/>
+ <reference key="parent" ref="1049"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1014"/>
+ <reference key="parent" ref="1049"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1050"/>
+ <reference key="parent" ref="1049"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">29</int>
+ <reference key="object" ref="649796088"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="713487014"/>
+ <reference ref="694149608"/>
+ <reference ref="391199113"/>
+ <reference ref="952259628"/>
+ <reference ref="379814623"/>
+ <reference ref="586577488"/>
+ <reference ref="302598603"/>
+ </object>
+ <reference key="parent" ref="1049"/>
+ <string key="objectName">MainMenu</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">19</int>
+ <reference key="object" ref="713487014"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="835318025"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">56</int>
+ <reference key="object" ref="694149608"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="110575045"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">103</int>
+ <reference key="object" ref="391199113"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="374024848"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ <string key="objectName">1</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">217</int>
+ <reference key="object" ref="952259628"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="789758025"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">83</int>
+ <reference key="object" ref="379814623"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="720053764"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">81</int>
+ <reference key="object" ref="720053764"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1023925487"/>
+ <reference ref="117038363"/>
+ <reference ref="49223823"/>
+ <reference ref="722745758"/>
+ <reference ref="705341025"/>
+ <reference ref="1025936716"/>
+ <reference ref="294629803"/>
+ <reference ref="776162233"/>
+ <reference ref="425164168"/>
+ <reference ref="579971712"/>
+ <reference ref="1010469920"/>
+ </object>
+ <reference key="parent" ref="379814623"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">75</int>
+ <reference key="object" ref="1023925487"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">3</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">80</int>
+ <reference key="object" ref="117038363"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">8</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">78</int>
+ <reference key="object" ref="49223823"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">6</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">72</int>
+ <reference key="object" ref="722745758"/>
+ <reference key="parent" ref="720053764"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">82</int>
+ <reference key="object" ref="705341025"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">9</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">124</int>
+ <reference key="object" ref="1025936716"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1065607017"/>
+ </object>
+ <reference key="parent" ref="720053764"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">77</int>
+ <reference key="object" ref="294629803"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">5</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">73</int>
+ <reference key="object" ref="776162233"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">1</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">79</int>
+ <reference key="object" ref="425164168"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">7</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">112</int>
+ <reference key="object" ref="579971712"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">10</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">74</int>
+ <reference key="object" ref="1010469920"/>
+ <reference key="parent" ref="720053764"/>
+ <string key="objectName">2</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">125</int>
+ <reference key="object" ref="1065607017"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="759406840"/>
+ </object>
+ <reference key="parent" ref="1025936716"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">126</int>
+ <reference key="object" ref="759406840"/>
+ <reference key="parent" ref="1065607017"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">205</int>
+ <reference key="object" ref="789758025"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="437104165"/>
+ <reference ref="583158037"/>
+ <reference ref="1058277027"/>
+ <reference ref="212016141"/>
+ <reference ref="296257095"/>
+ <reference ref="29853731"/>
+ <reference ref="860595796"/>
+ <reference ref="1040322652"/>
+ <reference ref="790794224"/>
+ <reference ref="892235320"/>
+ <reference ref="972420730"/>
+ <reference ref="676164635"/>
+ <reference ref="507821607"/>
+ </object>
+ <reference key="parent" ref="952259628"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">202</int>
+ <reference key="object" ref="437104165"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">198</int>
+ <reference key="object" ref="583158037"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">207</int>
+ <reference key="object" ref="1058277027"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">214</int>
+ <reference key="object" ref="212016141"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">199</int>
+ <reference key="object" ref="296257095"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">203</int>
+ <reference key="object" ref="29853731"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">197</int>
+ <reference key="object" ref="860595796"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">206</int>
+ <reference key="object" ref="1040322652"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">215</int>
+ <reference key="object" ref="790794224"/>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">218</int>
+ <reference key="object" ref="892235320"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="963351320"/>
+ </object>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">216</int>
+ <reference key="object" ref="972420730"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="769623530"/>
+ </object>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">200</int>
+ <reference key="object" ref="769623530"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="948374510"/>
+ <reference ref="96193923"/>
+ <reference ref="679648819"/>
+ <reference ref="967646866"/>
+ </object>
+ <reference key="parent" ref="972420730"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">219</int>
+ <reference key="object" ref="948374510"/>
+ <reference key="parent" ref="769623530"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">201</int>
+ <reference key="object" ref="96193923"/>
+ <reference key="parent" ref="769623530"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">204</int>
+ <reference key="object" ref="679648819"/>
+ <reference key="parent" ref="769623530"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">220</int>
+ <reference key="object" ref="963351320"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="270902937"/>
+ <reference ref="88285865"/>
+ <reference ref="159080638"/>
+ <reference ref="326711663"/>
+ <reference ref="447796847"/>
+ </object>
+ <reference key="parent" ref="892235320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">213</int>
+ <reference key="object" ref="270902937"/>
+ <reference key="parent" ref="963351320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">210</int>
+ <reference key="object" ref="88285865"/>
+ <reference key="parent" ref="963351320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">221</int>
+ <reference key="object" ref="159080638"/>
+ <reference key="parent" ref="963351320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">208</int>
+ <reference key="object" ref="326711663"/>
+ <reference key="parent" ref="963351320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">209</int>
+ <reference key="object" ref="447796847"/>
+ <reference key="parent" ref="963351320"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">106</int>
+ <reference key="object" ref="374024848"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="238773614"/>
+ </object>
+ <reference key="parent" ref="391199113"/>
+ <string key="objectName">2</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">111</int>
+ <reference key="object" ref="238773614"/>
+ <reference key="parent" ref="374024848"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">57</int>
+ <reference key="object" ref="110575045"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="238522557"/>
+ <reference ref="755159360"/>
+ <reference ref="908899353"/>
+ <reference ref="632727374"/>
+ <reference ref="646227648"/>
+ <reference ref="609285721"/>
+ <reference ref="481834944"/>
+ <reference ref="304266470"/>
+ <reference ref="1046388886"/>
+ <reference ref="1056857174"/>
+ <reference ref="342932134"/>
+ </object>
+ <reference key="parent" ref="694149608"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">58</int>
+ <reference key="object" ref="238522557"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">134</int>
+ <reference key="object" ref="755159360"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">150</int>
+ <reference key="object" ref="908899353"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">136</int>
+ <reference key="object" ref="632727374"/>
+ <reference key="parent" ref="110575045"/>
+ <string key="objectName">1111</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">144</int>
+ <reference key="object" ref="646227648"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">129</int>
+ <reference key="object" ref="609285721"/>
+ <reference key="parent" ref="110575045"/>
+ <string key="objectName">121</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">143</int>
+ <reference key="object" ref="481834944"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">236</int>
+ <reference key="object" ref="304266470"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">131</int>
+ <reference key="object" ref="1046388886"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="752062318"/>
+ </object>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">149</int>
+ <reference key="object" ref="1056857174"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">145</int>
+ <reference key="object" ref="342932134"/>
+ <reference key="parent" ref="110575045"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">130</int>
+ <reference key="object" ref="752062318"/>
+ <reference key="parent" ref="1046388886"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">24</int>
+ <reference key="object" ref="835318025"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="299356726"/>
+ <reference ref="625202149"/>
+ <reference ref="575023229"/>
+ <reference ref="1011231497"/>
+ </object>
+ <reference key="parent" ref="713487014"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">92</int>
+ <reference key="object" ref="299356726"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="625202149"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">239</int>
+ <reference key="object" ref="575023229"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">23</int>
+ <reference key="object" ref="1011231497"/>
+ <reference key="parent" ref="835318025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">295</int>
+ <reference key="object" ref="586577488"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="466310130"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">296</int>
+ <reference key="object" ref="466310130"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="102151532"/>
+ <reference ref="237841660"/>
+ </object>
+ <reference key="parent" ref="586577488"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">297</int>
+ <reference key="object" ref="102151532"/>
+ <reference key="parent" ref="466310130"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">298</int>
+ <reference key="object" ref="237841660"/>
+ <reference key="parent" ref="466310130"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">211</int>
+ <reference key="object" ref="676164635"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="785027613"/>
+ </object>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">212</int>
+ <reference key="object" ref="785027613"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="680220178"/>
+ <reference ref="731782645"/>
+ </object>
+ <reference key="parent" ref="676164635"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">195</int>
+ <reference key="object" ref="680220178"/>
+ <reference key="parent" ref="785027613"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">196</int>
+ <reference key="object" ref="731782645"/>
+ <reference key="parent" ref="785027613"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">346</int>
+ <reference key="object" ref="967646866"/>
+ <reference key="parent" ref="769623530"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">348</int>
+ <reference key="object" ref="507821607"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="698887838"/>
+ </object>
+ <reference key="parent" ref="789758025"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">349</int>
+ <reference key="object" ref="698887838"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="605118523"/>
+ <reference ref="197661976"/>
+ <reference ref="708854459"/>
+ </object>
+ <reference key="parent" ref="507821607"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">350</int>
+ <reference key="object" ref="605118523"/>
+ <reference key="parent" ref="698887838"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">351</int>
+ <reference key="object" ref="197661976"/>
+ <reference key="parent" ref="698887838"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">354</int>
+ <reference key="object" ref="708854459"/>
+ <reference key="parent" ref="698887838"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">371</int>
+ <reference key="object" ref="972006081"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="439893737"/>
+ </object>
+ <reference key="parent" ref="1049"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">372</int>
+ <reference key="object" ref="439893737"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1016473779"/>
+ <reference ref="610247741"/>
+ </object>
+ <reference key="parent" ref="972006081"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">375</int>
+ <reference key="object" ref="302598603"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="941447902"/>
+ </object>
+ <reference key="parent" ref="649796088"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">376</int>
+ <reference key="object" ref="941447902"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="792887677"/>
+ <reference ref="15516124"/>
+ </object>
+ <reference key="parent" ref="302598603"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">377</int>
+ <reference key="object" ref="792887677"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="786677654"/>
+ </object>
+ <reference key="parent" ref="941447902"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">378</int>
+ <reference key="object" ref="15516124"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="23081656"/>
+ </object>
+ <reference key="parent" ref="941447902"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">379</int>
+ <reference key="object" ref="23081656"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="135107054"/>
+ <reference ref="310547522"/>
+ <reference ref="436088763"/>
+ <reference ref="498119243"/>
+ <reference ref="607995063"/>
+ <reference ref="420564933"/>
+ <reference ref="479856769"/>
+ <reference ref="333628178"/>
+ </object>
+ <reference key="parent" ref="15516124"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">380</int>
+ <reference key="object" ref="135107054"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">381</int>
+ <reference key="object" ref="310547522"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">382</int>
+ <reference key="object" ref="436088763"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">383</int>
+ <reference key="object" ref="498119243"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">384</int>
+ <reference key="object" ref="607995063"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">385</int>
+ <reference key="object" ref="420564933"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">386</int>
+ <reference key="object" ref="479856769"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">387</int>
+ <reference key="object" ref="333628178"/>
+ <reference key="parent" ref="23081656"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">388</int>
+ <reference key="object" ref="786677654"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="159677712"/>
+ <reference ref="305399458"/>
+ <reference ref="814362025"/>
+ <reference ref="330926929"/>
+ <reference ref="533507878"/>
+ <reference ref="158063935"/>
+ <reference ref="885547335"/>
+ <reference ref="901062459"/>
+ <reference ref="767671776"/>
+ <reference ref="691570813"/>
+ <reference ref="769124883"/>
+ <reference ref="739652853"/>
+ <reference ref="1012600125"/>
+ <reference ref="214559597"/>
+ <reference ref="596732606"/>
+ <reference ref="393423671"/>
+ </object>
+ <reference key="parent" ref="792887677"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">389</int>
+ <reference key="object" ref="159677712"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">390</int>
+ <reference key="object" ref="305399458"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">391</int>
+ <reference key="object" ref="814362025"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">392</int>
+ <reference key="object" ref="330926929"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">393</int>
+ <reference key="object" ref="533507878"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">394</int>
+ <reference key="object" ref="158063935"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">395</int>
+ <reference key="object" ref="885547335"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">396</int>
+ <reference key="object" ref="901062459"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">397</int>
+ <reference key="object" ref="767671776"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="175441468"/>
+ </object>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">398</int>
+ <reference key="object" ref="691570813"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1058217995"/>
+ </object>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">399</int>
+ <reference key="object" ref="769124883"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="18263474"/>
+ </object>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">400</int>
+ <reference key="object" ref="739652853"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">401</int>
+ <reference key="object" ref="1012600125"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">402</int>
+ <reference key="object" ref="214559597"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">403</int>
+ <reference key="object" ref="596732606"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">404</int>
+ <reference key="object" ref="393423671"/>
+ <reference key="parent" ref="786677654"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">405</int>
+ <reference key="object" ref="18263474"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="257962622"/>
+ <reference ref="644725453"/>
+ <reference ref="1037576581"/>
+ <reference ref="941806246"/>
+ <reference ref="1045724900"/>
+ </object>
+ <reference key="parent" ref="769124883"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">406</int>
+ <reference key="object" ref="257962622"/>
+ <reference key="parent" ref="18263474"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">407</int>
+ <reference key="object" ref="644725453"/>
+ <reference key="parent" ref="18263474"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">408</int>
+ <reference key="object" ref="1037576581"/>
+ <reference key="parent" ref="18263474"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">409</int>
+ <reference key="object" ref="941806246"/>
+ <reference key="parent" ref="18263474"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">410</int>
+ <reference key="object" ref="1045724900"/>
+ <reference key="parent" ref="18263474"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">411</int>
+ <reference key="object" ref="1058217995"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="706297211"/>
+ <reference ref="568384683"/>
+ <reference ref="663508465"/>
+ </object>
+ <reference key="parent" ref="691570813"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">412</int>
+ <reference key="object" ref="706297211"/>
+ <reference key="parent" ref="1058217995"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">413</int>
+ <reference key="object" ref="568384683"/>
+ <reference key="parent" ref="1058217995"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">414</int>
+ <reference key="object" ref="663508465"/>
+ <reference key="parent" ref="1058217995"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">415</int>
+ <reference key="object" ref="175441468"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="252969304"/>
+ <reference ref="766922938"/>
+ <reference ref="677519740"/>
+ <reference ref="238351151"/>
+ </object>
+ <reference key="parent" ref="767671776"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">416</int>
+ <reference key="object" ref="252969304"/>
+ <reference key="parent" ref="175441468"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">417</int>
+ <reference key="object" ref="766922938"/>
+ <reference key="parent" ref="175441468"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">418</int>
+ <reference key="object" ref="677519740"/>
+ <reference key="parent" ref="175441468"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">419</int>
+ <reference key="object" ref="238351151"/>
+ <reference key="parent" ref="175441468"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">420</int>
+ <reference key="object" ref="755631768"/>
+ <reference key="parent" ref="1049"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">450</int>
+ <reference key="object" ref="229445039"/>
+ <reference key="parent" ref="1049"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">451</int>
+ <reference key="object" ref="1016473779"/>
+ <reference key="parent" ref="439893737"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">452</int>
+ <reference key="object" ref="610247741"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1009897894"/>
+ </object>
+ <reference key="parent" ref="439893737"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">453</int>
+ <reference key="object" ref="1009897894"/>
+ <reference key="parent" ref="610247741"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.IBPluginDependency</string>
+ <string>-2.IBPluginDependency</string>
+ <string>-3.IBPluginDependency</string>
+ <string>103.IBPluginDependency</string>
+ <string>103.ImportedFromIB2</string>
+ <string>106.IBPluginDependency</string>
+ <string>106.ImportedFromIB2</string>
+ <string>106.editorWindowContentRectSynchronizationRect</string>
+ <string>111.IBPluginDependency</string>
+ <string>111.ImportedFromIB2</string>
+ <string>112.IBPluginDependency</string>
+ <string>112.ImportedFromIB2</string>
+ <string>124.IBPluginDependency</string>
+ <string>124.ImportedFromIB2</string>
+ <string>125.IBPluginDependency</string>
+ <string>125.ImportedFromIB2</string>
+ <string>125.editorWindowContentRectSynchronizationRect</string>
+ <string>126.IBPluginDependency</string>
+ <string>126.ImportedFromIB2</string>
+ <string>129.IBPluginDependency</string>
+ <string>129.ImportedFromIB2</string>
+ <string>130.IBPluginDependency</string>
+ <string>130.ImportedFromIB2</string>
+ <string>130.editorWindowContentRectSynchronizationRect</string>
+ <string>131.IBPluginDependency</string>
+ <string>131.ImportedFromIB2</string>
+ <string>134.IBPluginDependency</string>
+ <string>134.ImportedFromIB2</string>
+ <string>136.IBPluginDependency</string>
+ <string>136.ImportedFromIB2</string>
+ <string>143.IBPluginDependency</string>
+ <string>143.ImportedFromIB2</string>
+ <string>144.IBPluginDependency</string>
+ <string>144.ImportedFromIB2</string>
+ <string>145.IBPluginDependency</string>
+ <string>145.ImportedFromIB2</string>
+ <string>149.IBPluginDependency</string>
+ <string>149.ImportedFromIB2</string>
+ <string>150.IBPluginDependency</string>
+ <string>150.ImportedFromIB2</string>
+ <string>19.IBPluginDependency</string>
+ <string>19.ImportedFromIB2</string>
+ <string>195.IBPluginDependency</string>
+ <string>195.ImportedFromIB2</string>
+ <string>196.IBPluginDependency</string>
+ <string>196.ImportedFromIB2</string>
+ <string>197.IBPluginDependency</string>
+ <string>197.ImportedFromIB2</string>
+ <string>198.IBPluginDependency</string>
+ <string>198.ImportedFromIB2</string>
+ <string>199.IBPluginDependency</string>
+ <string>199.ImportedFromIB2</string>
+ <string>200.IBPluginDependency</string>
+ <string>200.ImportedFromIB2</string>
+ <string>200.editorWindowContentRectSynchronizationRect</string>
+ <string>201.IBPluginDependency</string>
+ <string>201.ImportedFromIB2</string>
+ <string>202.IBPluginDependency</string>
+ <string>202.ImportedFromIB2</string>
+ <string>203.IBPluginDependency</string>
+ <string>203.ImportedFromIB2</string>
+ <string>204.IBPluginDependency</string>
+ <string>204.ImportedFromIB2</string>
+ <string>205.IBPluginDependency</string>
+ <string>205.ImportedFromIB2</string>
+ <string>205.editorWindowContentRectSynchronizationRect</string>
+ <string>206.IBPluginDependency</string>
+ <string>206.ImportedFromIB2</string>
+ <string>207.IBPluginDependency</string>
+ <string>207.ImportedFromIB2</string>
+ <string>208.IBPluginDependency</string>
+ <string>208.ImportedFromIB2</string>
+ <string>209.IBPluginDependency</string>
+ <string>209.ImportedFromIB2</string>
+ <string>210.IBPluginDependency</string>
+ <string>210.ImportedFromIB2</string>
+ <string>211.IBPluginDependency</string>
+ <string>211.ImportedFromIB2</string>
+ <string>212.IBPluginDependency</string>
+ <string>212.ImportedFromIB2</string>
+ <string>212.editorWindowContentRectSynchronizationRect</string>
+ <string>213.IBPluginDependency</string>
+ <string>213.ImportedFromIB2</string>
+ <string>214.IBPluginDependency</string>
+ <string>214.ImportedFromIB2</string>
+ <string>215.IBPluginDependency</string>
+ <string>215.ImportedFromIB2</string>
+ <string>216.IBPluginDependency</string>
+ <string>216.ImportedFromIB2</string>
+ <string>217.IBPluginDependency</string>
+ <string>217.ImportedFromIB2</string>
+ <string>218.IBPluginDependency</string>
+ <string>218.ImportedFromIB2</string>
+ <string>219.IBPluginDependency</string>
+ <string>219.ImportedFromIB2</string>
+ <string>220.IBPluginDependency</string>
+ <string>220.ImportedFromIB2</string>
+ <string>220.editorWindowContentRectSynchronizationRect</string>
+ <string>221.IBPluginDependency</string>
+ <string>221.ImportedFromIB2</string>
+ <string>23.IBPluginDependency</string>
+ <string>23.ImportedFromIB2</string>
+ <string>236.IBPluginDependency</string>
+ <string>236.ImportedFromIB2</string>
+ <string>239.IBPluginDependency</string>
+ <string>239.ImportedFromIB2</string>
+ <string>24.IBPluginDependency</string>
+ <string>24.ImportedFromIB2</string>
+ <string>24.editorWindowContentRectSynchronizationRect</string>
+ <string>29.IBEditorWindowLastContentRect</string>
+ <string>29.IBPluginDependency</string>
+ <string>29.ImportedFromIB2</string>
+ <string>29.WindowOrigin</string>
+ <string>29.editorWindowContentRectSynchronizationRect</string>
+ <string>295.IBPluginDependency</string>
+ <string>296.IBPluginDependency</string>
+ <string>296.editorWindowContentRectSynchronizationRect</string>
+ <string>297.IBPluginDependency</string>
+ <string>298.IBPluginDependency</string>
+ <string>346.IBPluginDependency</string>
+ <string>346.ImportedFromIB2</string>
+ <string>348.IBPluginDependency</string>
+ <string>348.ImportedFromIB2</string>
+ <string>349.IBPluginDependency</string>
+ <string>349.ImportedFromIB2</string>
+ <string>349.editorWindowContentRectSynchronizationRect</string>
+ <string>350.IBPluginDependency</string>
+ <string>350.ImportedFromIB2</string>
+ <string>351.IBPluginDependency</string>
+ <string>351.ImportedFromIB2</string>
+ <string>354.IBPluginDependency</string>
+ <string>354.ImportedFromIB2</string>
+ <string>371.IBEditorWindowLastContentRect</string>
+ <string>371.IBWindowTemplateEditedContentRect</string>
+ <string>371.NSWindowTemplate.visibleAtLaunch</string>
+ <string>371.editorWindowContentRectSynchronizationRect</string>
+ <string>371.windowTemplate.maxSize</string>
+ <string>372.IBPluginDependency</string>
+ <string>375.IBPluginDependency</string>
+ <string>376.IBEditorWindowLastContentRect</string>
+ <string>376.IBPluginDependency</string>
+ <string>377.IBPluginDependency</string>
+ <string>378.IBPluginDependency</string>
+ <string>379.IBPluginDependency</string>
+ <string>380.IBPluginDependency</string>
+ <string>381.IBPluginDependency</string>
+ <string>382.IBPluginDependency</string>
+ <string>383.IBPluginDependency</string>
+ <string>384.IBPluginDependency</string>
+ <string>385.IBPluginDependency</string>
+ <string>386.IBPluginDependency</string>
+ <string>387.IBPluginDependency</string>
+ <string>388.IBEditorWindowLastContentRect</string>
+ <string>388.IBPluginDependency</string>
+ <string>389.IBPluginDependency</string>
+ <string>390.IBPluginDependency</string>
+ <string>391.IBPluginDependency</string>
+ <string>392.IBPluginDependency</string>
+ <string>393.IBPluginDependency</string>
+ <string>394.IBPluginDependency</string>
+ <string>395.IBPluginDependency</string>
+ <string>396.IBPluginDependency</string>
+ <string>397.IBPluginDependency</string>
+ <string>398.IBPluginDependency</string>
+ <string>399.IBPluginDependency</string>
+ <string>400.IBPluginDependency</string>
+ <string>401.IBPluginDependency</string>
+ <string>402.IBPluginDependency</string>
+ <string>403.IBPluginDependency</string>
+ <string>404.IBPluginDependency</string>
+ <string>405.IBPluginDependency</string>
+ <string>406.IBPluginDependency</string>
+ <string>407.IBPluginDependency</string>
+ <string>408.IBPluginDependency</string>
+ <string>409.IBPluginDependency</string>
+ <string>410.IBPluginDependency</string>
+ <string>411.IBPluginDependency</string>
+ <string>412.IBPluginDependency</string>
+ <string>413.IBPluginDependency</string>
+ <string>414.IBPluginDependency</string>
+ <string>415.IBPluginDependency</string>
+ <string>416.IBPluginDependency</string>
+ <string>417.IBPluginDependency</string>
+ <string>418.IBPluginDependency</string>
+ <string>419.IBPluginDependency</string>
+ <string>420.IBPluginDependency</string>
+ <string>450.IBPluginDependency</string>
+ <string>451.IBPluginDependency</string>
+ <string>452.IBPluginDependency</string>
+ <string>453.IBPluginDependency</string>
+ <string>5.IBPluginDependency</string>
+ <string>5.ImportedFromIB2</string>
+ <string>56.IBPluginDependency</string>
+ <string>56.ImportedFromIB2</string>
+ <string>57.IBEditorWindowLastContentRect</string>
+ <string>57.IBPluginDependency</string>
+ <string>57.ImportedFromIB2</string>
+ <string>57.editorWindowContentRectSynchronizationRect</string>
+ <string>58.IBPluginDependency</string>
+ <string>58.ImportedFromIB2</string>
+ <string>72.IBPluginDependency</string>
+ <string>72.ImportedFromIB2</string>
+ <string>73.IBPluginDependency</string>
+ <string>73.ImportedFromIB2</string>
+ <string>74.IBPluginDependency</string>
+ <string>74.ImportedFromIB2</string>
+ <string>75.IBPluginDependency</string>
+ <string>75.ImportedFromIB2</string>
+ <string>77.IBPluginDependency</string>
+ <string>77.ImportedFromIB2</string>
+ <string>78.IBPluginDependency</string>
+ <string>78.ImportedFromIB2</string>
+ <string>79.IBPluginDependency</string>
+ <string>79.ImportedFromIB2</string>
+ <string>80.IBPluginDependency</string>
+ <string>80.ImportedFromIB2</string>
+ <string>81.IBPluginDependency</string>
+ <string>81.ImportedFromIB2</string>
+ <string>81.editorWindowContentRectSynchronizationRect</string>
+ <string>82.IBPluginDependency</string>
+ <string>82.ImportedFromIB2</string>
+ <string>83.IBPluginDependency</string>
+ <string>83.ImportedFromIB2</string>
+ <string>92.IBPluginDependency</string>
+ <string>92.ImportedFromIB2</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>com.apple.InterfaceBuilderKit</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <integer value="1" id="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{596, 852}, {216, 23}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{522, 812}, {146, 23}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{436, 809}, {64, 6}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{608, 612}, {275, 83}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{187, 434}, {243, 243}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{608, 612}, {167, 43}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{608, 612}, {241, 103}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{525, 802}, {197, 73}}</string>
+ <string>{{207, 285}, {478, 20}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{74, 862}</string>
+ <string>{{6, 978}, {478, 20}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{475, 832}, {234, 43}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{608, 612}, {215, 63}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{274, 369}, {982, 692}}</string>
+ <string>{{274, 369}, {982, 692}}</string>
+ <reference ref="9"/>
+ <string>{{33, 99}, {480, 360}}</string>
+ <string>{3.40282e+38, 3.40282e+38}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{437, 242}, {86, 43}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{523, 2}, {178, 283}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{219, 102}, {245, 183}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{23, 794}, {245, 183}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>{{145, 474}, {199, 203}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <reference ref="9"/>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">458</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">AppController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">mEditHost</string>
+ <string key="NS.object.0">NSBox</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">AppController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../ScintillaTest.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/scintilla/cocoa/ScintillaTest/Info.plist b/scintilla/cocoa/ScintillaTest/Info.plist
new file mode 100644
index 0000000..abf64b2
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.sun.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist b/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist
new file mode 100644
index 0000000..b3f87c0
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/Scintilla-Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.sun.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
diff --git a/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj b/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..43f5b79
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj
@@ -0,0 +1,381 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
+ 271FA52C0F850BE20033D021 /* AppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 271FA52B0F850BE20033D021 /* AppController.mm */; };
+ 2791F4490FC1A8E9009DBCF9 /* TestData.sql in Resources */ = {isa = PBXBuildFile; fileRef = 2791F4480FC1A8E9009DBCF9 /* TestData.sql */; };
+ 27AF7EC30FC2C351007160EF /* Scintilla.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */; };
+ 27AF7ECA0FC2C388007160EF /* Scintilla.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */; };
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
+ 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 2744E5E90FC16BE200E85C33 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
+ remoteInfo = Scintilla;
+ };
+ 27AF7EC60FC2C36A007160EF /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = Scintilla;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 272133C20F973596006BE49A /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 27AF7ECA0FC2C388007160EF /* Scintilla.framework in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+ 1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 271FA52A0F850BE20033D021 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
+ 271FA52B0F850BE20033D021 /* AppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppController.mm; sourceTree = "<group>"; wrapsLines = 0; };
+ 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ScintillaFramework.xcodeproj; path = ../ScintillaFramework/ScintillaFramework.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 2791F4480FC1A8E9009DBCF9 /* TestData.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestData.sql; sourceTree = "<group>"; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 32CA4F630368D1EE00C91783 /* ScintillaTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScintillaTest_Prefix.pch; sourceTree = "<group>"; };
+ 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 8D1107320486CEB800E47090 /* ScintillaTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScintillaTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D11072E0486CEB800E47090 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 27AF7EC30FC2C351007160EF /* Scintilla.framework in Frameworks */,
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 271FA52A0F850BE20033D021 /* AppController.h */,
+ 271FA52B0F850BE20033D021 /* AppController.mm */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "<group>";
+ };
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */,
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D1107320486CEB800E47090 /* ScintillaTest.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 2744E5E30FC16BE200E85C33 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* ScintillaTest */ = {
+ isa = PBXGroup;
+ children = (
+ 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */,
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = ScintillaTest;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 32CA4F630368D1EE00C91783 /* ScintillaTest_Prefix.pch */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 2791F4480FC1A8E9009DBCF9 /* TestData.sql */,
+ 8D1107310486CEB800E47090 /* Info.plist */,
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
+ 1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D1107260486CEB800E47090 /* ScintillaTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ScintillaTest" */;
+ buildPhases = (
+ 8D1107290486CEB800E47090 /* Resources */,
+ 8D11072C0486CEB800E47090 /* Sources */,
+ 8D11072E0486CEB800E47090 /* Frameworks */,
+ 272133C20F973596006BE49A /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27AF7EC70FC2C36A007160EF /* PBXTargetDependency */,
+ );
+ name = ScintillaTest;
+ productInstallPath = "$(HOME)/Applications";
+ productName = ScintillaTest;
+ productReference = 8D1107320486CEB800E47090 /* ScintillaTest.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ScintillaTest" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 29B97314FDCFA39411CA2CEA /* ScintillaTest */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 2744E5E30FC16BE200E85C33 /* Products */;
+ ProjectRef = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 8D1107260486CEB800E47090 /* ScintillaTest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = Scintilla.framework;
+ remoteRef = 2744E5E90FC16BE200E85C33 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D1107290486CEB800E47090 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
+ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
+ 2791F4490FC1A8E9009DBCF9 /* TestData.sql in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D11072C0486CEB800E47090 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072D0486CEB800E47090 /* main.m in Sources */,
+ 271FA52C0F850BE20033D021 /* AppController.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 27AF7EC70FC2C36A007160EF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Scintilla;
+ targetProxy = 27AF7EC60FC2C36A007160EF /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C165DFE840E0CC02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ 1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 1DDD58150DA1D0A300B32029 /* English */,
+ );
+ name = MainMenu.xib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ C01FCF4B08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../../MySQL/Workbench/5.2/ext/scintilla/cocoa/ScintillaFramework/build/Debug\"",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ScintillaTest_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ SCI_LEXER,
+ SCI_NAMESPACE,
+ );
+ HEADER_SEARCH_PATHS = "../..//**";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = ScintillaTest;
+ USER_HEADER_SEARCH_PATHS = "";
+ };
+ name = Debug;
+ };
+ C01FCF4C08A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../../../../MySQL/Workbench/5.2/ext/scintilla/cocoa/ScintillaFramework/build/Debug\"",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ScintillaTest_Prefix.pch;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ SCI_LEXER,
+ SCI_NAMESPACE,
+ );
+ HEADER_SEARCH_PATHS = "../..//**";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = ScintillaTest;
+ USER_HEADER_SEARCH_PATHS = "";
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "";
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ OTHER_LDFLAGS = "";
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ScintillaTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4B08A954540054247B /* Debug */,
+ C01FCF4C08A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ScintillaTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/scintilla/cocoa/ScintillaTest/ScintillaTest_Prefix.pch b/scintilla/cocoa/ScintillaTest/ScintillaTest_Prefix.pch
new file mode 100644
index 0000000..b3d5ee7
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/ScintillaTest_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'ScintillaTest' target in the 'ScintillaTest' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
diff --git a/scintilla/cocoa/ScintillaTest/TestData.sql b/scintilla/cocoa/ScintillaTest/TestData.sql
new file mode 100644
index 0000000..4967885
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/TestData.sql
@@ -0,0 +1,215 @@
+-- MySQL Administrator dump 1.4
+--
+-- ------------------------------------------------------
+-- Server version 5.0.45
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI_QUOTES' */;
+
+/**
+ * Foldable multiline comment.
+ */
+
+-- {
+-- Create schema sakila
+-- }
+
+CREATE DATABASE IF NOT EXISTS sakila;
+USE sakila;
+DROP TABLE IF EXISTS "sakila"."actor_info";
+DROP VIEW IF EXISTS "sakila"."actor_info";
+CREATE TABLE "sakila"."actor_info" (
+ "actor_id" smallint(5) unsigned,
+ "first_name" varchar(45),
+ "last_name" varchar(45),
+ "film_info" varchar(341)
+);
+DROP TABLE IF EXISTS "sakila"."actor";
+CREATE TABLE "sakila"."actor" (
+ "actor_id" smallint(5) unsigned NOT NULL auto_increment,
+ "first_name" varchar(45) NOT NULL,
+ "last_name" varchar(45) NOT NULL,
+ "last_update" timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ PRIMARY KEY ("actor_id"),
+ KEY "idx_actor_last_name" ("last_name")
+) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8;
+INSERT INTO "sakila"."actor" VALUES (1,'PENELOPE','GUINESS','2006-02-15 04:34:33'),
+ (2,'NICK','WAHLBERG','2006-02-15 04:34:33'),
+ (3,'ED','CHASE','2006-02-15 04:34:33'),
+ (4,'JENNIFER','DAVIS','2006-02-15 04:34:33'),
+ (149,'RUSSELL','TEMPLE','2006-02-15 04:34:33'),
+ (150,'JAYNE','NOLTE','2006-02-15 04:34:33'),
+ (151,'GEOFFREY','HESTON','2006-02-15 04:34:33'),
+ (152,'BEN','HARRIS','2006-02-15 04:34:33'),
+ (153,'MINNIE','KILMER','2006-02-15 04:34:33'),
+ (154,'MERYL','GIBSON','2006-02-15 04:34:33'),
+ (155,'IAN','TANDY','2006-02-15 04:34:33'),
+ (156,'FAY','WOOD','2006-02-15 04:34:33'),
+ (157,'GRETA','MALDEN','2006-02-15 04:34:33'),
+ (158,'VIVIEN','BASINGER','2006-02-15 04:34:33'),
+ (159,'LAURA','BRODY','2006-02-15 04:34:33'),
+ (160,'CHRIS','DEPP','2006-02-15 04:34:33'),
+ (161,'HARVEY','HOPE','2006-02-15 04:34:33'),
+ (162,'OPRAH','KILMER','2006-02-15 04:34:33'),
+ (163,'CHRISTOPHER','WEST','2006-02-15 04:34:33'),
+ (164,'HUMPHREY','WILLIS','2006-02-15 04:34:33'),
+ (165,'AL','GARLAND','2006-02-15 04:34:33'),
+ (166,'NICK','DEGENERES','2006-02-15 04:34:33'),
+ (167,'LAURENCE','BULLOCK','2006-02-15 04:34:33'),
+ (168,'WILL','WILSON','2006-02-15 04:34:33'),
+ (169,'KENNETH','HOFFMAN','2006-02-15 04:34:33'),
+ (170,'MENA','HOPPER','2006-02-15 04:34:33'),
+ (171,'OLYMPIA','PFEIFFER','2006-02-15 04:34:33'),
+ (190,'AUDREY','BAILEY','2006-02-15 04:34:33'),
+ (191,'GREGORY','GOODING','2006-02-15 04:34:33'),
+ (192,'JOHN','SUVARI','2006-02-15 04:34:33'),
+ (193,'BURT','TEMPLE','2006-02-15 04:34:33'),
+ (194,'MERYL','ALLEN','2006-02-15 04:34:33'),
+ (195,'JAYNE','SILVERSTONE','2006-02-15 04:34:33'),
+ (196,'BELA','WALKEN','2006-02-15 04:34:33'),
+ (197,'REESE','WEST','2006-02-15 04:34:33'),
+ (198,'MARY','KEITEL','2006-02-15 04:34:33'),
+ (199,'JULIA','FAWCETT','2006-02-15 04:34:33'),
+ (200,'THORA','TEMPLE','2006-02-15 04:34:33');
+
+DROP TRIGGER /*!50030 IF EXISTS */ "sakila"."payment_date";
+
+DELIMITER $$
+
+CREATE DEFINER = "root"@"localhost" TRIGGER "sakila"."payment_date" BEFORE INSERT ON "payment" FOR EACH ROW SET NEW.payment_date = NOW() $$
+
+DELIMITER ;
+
+
+DROP TABLE IF EXISTS "sakila"."sales_by_store";
+DROP VIEW IF EXISTS "sakila"."sales_by_store";
+CREATE ALGORITHM=UNDEFINED DEFINER="root"@"localhost" SQL SECURITY DEFINER VIEW "sakila"."sales_by_store" AS select concat("c"."city",_utf8',',"cy"."country") AS "store",concat("m"."first_name",_utf8' ',"m"."last_name") AS "manager",sum("p"."amount") AS "total_sales" from ((((((("sakila"."payment" "p" join "sakila"."rental" "r" on(("p"."rental_id" = "r"."rental_id"))) join "sakila"."inventory" "i" on(("r"."inventory_id" = "i"."inventory_id"))) join "sakila"."store" "s" on(("i"."store_id" = "s"."store_id"))) join "sakila"."address" "a" on(("s"."address_id" = "a"."address_id"))) join "sakila"."city" "c" on(("a"."city_id" = "c"."city_id"))) join "sakila"."country" "cy" on(("c"."country_id" = "cy"."country_id"))) join "sakila"."staff" "m" on(("s"."manager_staff_id" = "m"."staff_id"))) group by "s"."store_id" order by "cy"."country","c"."city";
+
+--
+-- View structure for view `staff_list`
+--
+
+CREATE VIEW staff_list
+AS
+SELECT s.staff_id AS ID, CONCAT(s.first_name, _utf8' ', s.last_name) AS name, a.address AS address, a.postal_code AS `zip code`, a.phone AS phone,
+ city.city AS city, country.country AS country, s.store_id AS SID
+FROM staff AS s JOIN address AS a ON s.address_id = a.address_id JOIN city ON a.city_id = city.city_id
+ JOIN country ON city.country_id = country.country_id;
+
+--
+-- View structure for view `actor_info`
+--
+
+CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER VIEW actor_info
+AS
+SELECT
+a.actor_id,
+a.first_name,
+a.last_name,
+GROUP_CONCAT(DISTINCT CONCAT(c.name, ': ',
+ (SELECT GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ', ')
+ FROM sakila.film f
+ INNER JOIN sakila.film_category fc
+ ON f.film_id = fc.film_id
+ INNER JOIN sakila.film_actor fa
+ ON f.film_id = fa.film_id
+ WHERE fc.category_id = c.category_id
+ AND fa.actor_id = a.actor_id
+ )
+ )
+ ORDER BY c.name SEPARATOR '; ')
+AS film_info
+FROM sakila.actor a
+LEFT JOIN sakila.film_actor fa
+ ON a.actor_id = fa.actor_id
+LEFT JOIN sakila.film_category fc
+ ON fa.film_id = fc.film_id
+LEFT JOIN sakila.category c
+ ON fc.category_id = c.category_id
+GROUP BY a.actor_id, a.first_name, a.last_name;
+
+DELIMITER $$
+
+CREATE FUNCTION get_customer_balance(p_customer_id INT, p_effective_date DATETIME) RETURNS DECIMAL(5,2)
+ DETERMINISTIC
+ READS SQL DATA
+BEGIN
+
+ #OK, WE NEED TO CALCULATE THE CURRENT BALANCE GIVEN A CUSTOMER_ID AND A DATE
+ #THAT WE WANT THE BALANCE TO BE EFFECTIVE FOR. THE BALANCE IS:
+ # 1) RENTAL FEES FOR ALL PREVIOUS RENTALS
+ # 2) ONE DOLLAR FOR EVERY DAY THE PREVIOUS RENTALS ARE OVERDUE
+ # 3) IF A FILM IS MORE THAN RENTAL_DURATION * 2 OVERDUE, CHARGE THE REPLACEMENT_COST
+ # 4) SUBTRACT ALL PAYMENTS MADE BEFORE THE DATE SPECIFIED
+
+ DECLARE v_rentfees DECIMAL(5,2); #FEES PAID TO RENT THE VIDEOS INITIALLY
+ DECLARE v_overfees INTEGER; #LATE FEES FOR PRIOR RENTALS
+ DECLARE v_payments DECIMAL(5,2); #SUM OF PAYMENTS MADE PREVIOUSLY
+
+ SELECT IFNULL(SUM(film.rental_rate),0) INTO v_rentfees
+ FROM film, inventory, rental
+ WHERE film.film_id = inventory.film_id
+ AND inventory.inventory_id = rental.inventory_id
+ AND rental.rental_date <= p_effective_date
+ AND rental.customer_id = p_customer_id;
+
+ SELECT IFNULL(SUM(IF((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) > film.rental_duration,
+ ((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) - film.rental_duration),0)),0) INTO v_overfees
+ FROM rental, inventory, film
+ WHERE film.film_id = inventory.film_id
+ AND inventory.inventory_id = rental.inventory_id
+ AND rental.rental_date <= p_effective_date
+ AND rental.customer_id = p_customer_id;
+
+
+ SELECT IFNULL(SUM(payment.amount),0) INTO v_payments
+ FROM payment
+
+ WHERE payment.payment_date <= p_effective_date
+ AND payment.customer_id = p_customer_id;
+
+ RETURN v_rentfees + v_overfees - v_payments;
+END $$
+
+DELIMITER ;
+
+DELIMITER $$
+
+CREATE FUNCTION inventory_in_stock(p_inventory_id INT) RETURNS BOOLEAN
+READS SQL DATA
+BEGIN
+ DECLARE v_rentals INT;
+ DECLARE v_out INT;
+
+ #AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
+ #FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
+
+ SELECT COUNT(*) INTO v_rentals
+ FROM rental
+ WHERE inventory_id = p_inventory_id;
+
+ IF v_rentals = 0 THEN
+ RETURN TRUE;
+ END IF;
+
+ SELECT COUNT(rental_id) INTO v_out
+ FROM inventory LEFT JOIN rental USING(inventory_id)
+ WHERE inventory.inventory_id = p_inventory_id
+ AND rental.return_date IS NULL;
+
+ IF v_out > 0 THEN
+ RETURN FALSE;
+ ELSE
+ RETURN TRUE;
+ END IF;
+END $$
+
+DELIMITER ;
+
diff --git a/scintilla/cocoa/ScintillaTest/main.m b/scintilla/cocoa/ScintillaTest/main.m
new file mode 100644
index 0000000..59ff6b2
--- /dev/null
+++ b/scintilla/cocoa/ScintillaTest/main.m
@@ -0,0 +1,15 @@
+/**
+ * main.m
+ * ScintillaTest
+ *
+ * Created by Mike Lischke on 02.04.09.
+ * Copyright Sun Microsystems, Inc 2009. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
diff --git a/scintilla/cocoa/ScintillaView.h b/scintilla/cocoa/ScintillaView.h
new file mode 100644
index 0000000..3e76d3c
--- /dev/null
+++ b/scintilla/cocoa/ScintillaView.h
@@ -0,0 +1,120 @@
+
+/**
+ * Declaration of the native Cocoa View that serves as container for the scintilla parts.
+ *
+ * Created by Mike Lischke.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#import "Platform.h"
+#import "Scintilla.h"
+#import "SciLexer.h"
+
+#import "InfoBarCommunicator.h"
+#import "ScintillaCocoa.h"
+
+@class ScintillaView;
+
+extern NSString *SCIUpdateUINotification;
+
+/**
+ * InnerView is the Cocoa interface to the Scintilla backend. It handles text input and
+ * provides a canvas for painting the output.
+ */
+@interface InnerView : NSView <NSTextInput>
+{
+@private
+ ScintillaView* mOwner;
+ NSCursor* mCurrentCursor;
+ NSTrackingRectTag mCurrentTrackingRect;
+
+ // Set when we are in composition mode and partial input is displayed.
+ NSRange mMarkedTextRange;
+
+ // Caret position when a drag operation started.
+ int mLastPosition;
+}
+
+- (void) dealloc;
+- (void) removeMarkedText;
+- (void) setCursor: (Scintilla::Window::Cursor) cursor;
+
+@property (retain) ScintillaView* owner;
+@end
+
+@interface ScintillaView : NSView <InfoBarCommunicator>
+{
+@private
+ // The back end is kind of a controller and model in one.
+ // It uses the content view for display.
+ Scintilla::ScintillaCocoa* mBackend;
+
+ // This is the actual content to which the backend renders itself.
+ InnerView* mContent;
+
+ NSScroller* mHorizontalScroller;
+ NSScroller* mVerticalScroller;
+
+ // Area to display additional controls (e.g. zoom info, caret position, status info).
+ NSView <InfoBarCommunicator>* mInfoBar;
+ BOOL mInfoBarAtTop;
+ int mInitialInfoBarWidth;
+}
+
+- (void) dealloc;
+- (void) layout;
+
+- (void) sendNotification: (NSString*) notificationName;
+- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
+ value: (float) value;
+- (void) setCallback: (id <InfoBarCommunicator>) callback;
+
+// Scroller handling
+- (BOOL) setVerticalScrollRange: (int) range page: (int) page;
+- (void) setVerticalScrollPosition: (float) position;
+- (BOOL) setHorizontalScrollRange: (int) range page: (int) page;
+- (void) setHorizontalScrollPosition: (float) position;
+
+- (void) scrollerAction: (id) sender;
+- (InnerView*) content;
+
+// NSTextView compatibility layer.
+- (NSString*) string;
+- (void) setString: (NSString*) aString;
+- (void) insertText: (NSString*) aString;
+- (void) setEditable: (BOOL) editable;
+- (BOOL) isEditable;
+- (NSRange) selectedRange;
+
+- (NSString*) selectedString;
+
+// Native call through to the backend.
++ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam
+ lParam: (sptr_t) lParam;
+
+// Back end properties getters and setters.
+- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value;
+- (long) getGeneralProperty: (int) property;
+- (long) getGeneralProperty: (int) property parameter: (long) parameter;
+- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra;
+- (long) getGeneralProperty: (int) property ref: (const void*) ref;
+- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value;
+- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML;
+- (NSColor*) getColorProperty: (int) property parameter: (long) parameter;
+- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value;
+- (const void*) getReferenceProperty: (int) property parameter: (long) parameter;
+- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value;
+- (NSString*) getStringProperty: (int) property parameter: (long) parameter;
+- (void) setLexerProperty: (NSString*) name value: (NSString*) value;
+- (NSString*) getLexerProperty: (NSString*) name;
+
+- (void) setInfoBar: (NSView <InfoBarCommunicator>*) aView top: (BOOL) top;
+- (void) setStatusText: (NSString*) text;
+
+@property Scintilla::ScintillaCocoa* backend;
+
+@end
diff --git a/scintilla/cocoa/ScintillaView.mm b/scintilla/cocoa/ScintillaView.mm
new file mode 100644
index 0000000..1863bd9
--- /dev/null
+++ b/scintilla/cocoa/ScintillaView.mm
@@ -0,0 +1,1376 @@
+
+/**
+ * Implementation of the native Cocoa View that serves as container for the scintilla parts.
+ *
+ * Created by Mike Lischke.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
+ */
+
+#import "ScintillaView.h"
+
+using namespace Scintilla;
+
+// Two additional cursors we need, which aren't provided by Cocoa.
+static NSCursor* reverseArrowCursor;
+static NSCursor* waitCursor;
+
+// The scintilla indicator used for keyboard input.
+#define INPUT_INDICATOR INDIC_MAX - 1
+
+NSString *SCIUpdateUINotification = @"SCIUpdateUI";
+
+@implementation InnerView
+
+@synthesize owner = mOwner;
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSView*) initWithFrame: (NSRect) frame
+{
+ self = [super initWithFrame: frame];
+
+ if (self != nil)
+ {
+ // Some initialization for our view.
+ mCurrentCursor = [[NSCursor arrowCursor] retain];
+ mCurrentTrackingRect = 0;
+ mMarkedTextRange = NSMakeRange(NSNotFound, 0);
+
+ [self registerForDraggedTypes: [NSArray arrayWithObjects:
+ NSStringPboardType, ScintillaRecPboardType, NSFilenamesPboardType, nil]];
+ }
+
+ return self;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * When the view is resized we need to update our tracking rectangle and let the backend know.
+ */
+- (void) setFrame: (NSRect) frame
+{
+ [super setFrame: frame];
+
+ // Make the content also a tracking rectangle for mouse events.
+ if (mCurrentTrackingRect != 0)
+ [self removeTrackingRect: mCurrentTrackingRect];
+ mCurrentTrackingRect = [self addTrackingRect: [self bounds]
+ owner: self
+ userData: nil
+ assumeInside: YES];
+ mOwner.backend->Resize();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the backend if a new cursor must be set for the view.
+ */
+- (void) setCursor: (Window::Cursor) cursor
+{
+ [mCurrentCursor autorelease];
+ switch (cursor)
+ {
+ case Window::cursorText:
+ mCurrentCursor = [NSCursor IBeamCursor];
+ break;
+ case Window::cursorArrow:
+ mCurrentCursor = [NSCursor arrowCursor];
+ break;
+ case Window::cursorWait:
+ mCurrentCursor = waitCursor;
+ break;
+ case Window::cursorHoriz:
+ mCurrentCursor = [NSCursor resizeLeftRightCursor];
+ break;
+ case Window::cursorVert:
+ mCurrentCursor = [NSCursor resizeUpDownCursor];
+ break;
+ case Window::cursorReverseArrow:
+ mCurrentCursor = reverseArrowCursor;
+ break;
+ case Window::cursorUp:
+ default:
+ mCurrentCursor = [NSCursor arrowCursor];
+ break;
+ }
+
+ [mCurrentCursor retain];
+
+ // Trigger recreation of the cursor rectangle(s).
+ [[self window] invalidateCursorRectsForView: self];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * This method is called to give us the opportunity to define our mouse sensitive rectangle.
+ */
+- (void) resetCursorRects
+{
+ [super resetCursorRects];
+
+ // We only have one cursor rect: our bounds.
+ NSRect bounds = [self bounds];
+ [self addCursorRect: [self bounds] cursor: mCurrentCursor];
+ [mCurrentCursor setOnMouseEntered: YES];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Gets called by the runtime when the view needs repainting.
+ */
+- (void) drawRect: (NSRect) rect
+{
+ CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
+
+ mOwner.backend->Draw(rect, context);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Windows uses a client coordinate system where the upper left corner is the origin in a window
+ * (and so does Scintilla). We have to adjust for that. However by returning YES here, we are
+ * already done with that.
+ * Note that because of returning YES here most coordinates we use now (e.g. for painting,
+ * invalidating rectangles etc.) are given with +Y pointing down!
+ */
+- (BOOL) isFlipped
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) isOpaque
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Implement the "click through" behavior by telling the caller we accept the first mouse event too.
+ */
+- (BOOL) acceptsFirstMouse: (NSEvent *) theEvent
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Make this view accepting events as first responder.
+ */
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the framework if it wants to show a context menu for the editor.
+ */
+- (NSMenu*) menuForEvent: (NSEvent*) theEvent
+{
+ return mOwner.backend->CreateContextMenu(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+// Adoption of NSTextInput protocol.
+
+- (NSAttributedString*) attributedSubstringFromRange: (NSRange) range
+{
+ return nil;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSUInteger) characterIndexForPoint: (NSPoint) point
+{
+ return NSNotFound;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSInteger) conversationIdentifier
+{
+ return (NSInteger) self;
+
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) doCommandBySelector: (SEL) selector
+{
+ if ([self respondsToSelector: @selector(selector)])
+ [self performSelector: selector withObject: nil];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSRect) firstRectForCharacterRange: (NSRange) range
+{
+ return NSZeroRect;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) hasMarkedText
+{
+ return mMarkedTextRange.length > 0;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * General text input. Used to insert new text at the current input position, replacing the current
+ * selection if there is any.
+ */
+- (void) insertText: (id) aString
+{
+ // Remove any previously marked text first.
+ [self removeMarkedText];
+ mOwner.backend->InsertText((NSString*) aString);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSRange) markedRange
+{
+ return mMarkedTextRange;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSRange) selectedRange
+{
+ int begin = [mOwner getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0];
+ int end = [mOwner getGeneralProperty: SCI_GETSELECTIONEND parameter: 0];
+ return NSMakeRange(begin, end - begin);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the input manager to set text which might be combined with further input to form
+ * the final text (e.g. composition of ^ and a to â).
+ *
+ * @param aString The text to insert, either what has been marked already or what is selected already
+ * or simply added at the current insertion point. Depending on what is available.
+ * @param range The range of the new text to select (given relative to the insertion point of the new text).
+ */
+- (void) setMarkedText: (id) aString selectedRange: (NSRange) range
+{
+ // Since we did not return any valid attribute for marked text (see validAttributesForMarkedText)
+ // we can safely assume the passed in text is an NSString instance.
+ NSString* newText = (NSString*) aString;
+ int currentPosition = [mOwner getGeneralProperty: SCI_GETCURRENTPOS parameter: 0];
+
+ // Replace marked text if there is one.
+ if (mMarkedTextRange.length > 0)
+ {
+ // We have already marked text. Replace that.
+ [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
+ parameter: mMarkedTextRange.location
+ value: 0];
+ [mOwner setGeneralProperty: SCI_SETSELECTIONEND
+ parameter: mMarkedTextRange.location + mMarkedTextRange.length
+ value: 0];
+ currentPosition = mMarkedTextRange.location;
+ }
+
+ mOwner.backend->InsertText(newText);
+
+ mMarkedTextRange.location = currentPosition;
+ mMarkedTextRange.length = [newText length];
+
+ // Mark the just inserted text. Keep the marked range for later reset.
+ [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT parameter: INPUT_INDICATOR value: 0];
+ [mOwner setGeneralProperty: SCI_INDICATORFILLRANGE
+ parameter: mMarkedTextRange.location
+ value: mMarkedTextRange.length];
+
+ // Select the part which is indicated in the given range.
+ if (range.length > 0)
+ {
+ [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
+ parameter: currentPosition + range.location
+ value: 0];
+ [mOwner setGeneralProperty: SCI_SETSELECTIONEND
+ parameter: currentPosition + range.location + range.length
+ value: 0];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) unmarkText
+{
+ if (mMarkedTextRange.length > 0)
+ {
+ [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT parameter: INPUT_INDICATOR value: 0];
+ [mOwner setGeneralProperty: SCI_INDICATORCLEARRANGE
+ parameter: mMarkedTextRange.location
+ value: mMarkedTextRange.length];
+ mMarkedTextRange = NSMakeRange(NSNotFound, 0);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Removes any currently marked text.
+ */
+- (void) removeMarkedText
+{
+ if (mMarkedTextRange.length > 0)
+ {
+ // We have already marked text. Replace that.
+ [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
+ parameter: mMarkedTextRange.location
+ value: 0];
+ [mOwner setGeneralProperty: SCI_SETSELECTIONEND
+ parameter: mMarkedTextRange.location + mMarkedTextRange.length
+ value: 0];
+ mOwner.backend->InsertText(@"");
+ mMarkedTextRange = NSMakeRange(NSNotFound, 0);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (NSArray*) validAttributesForMarkedText
+{
+ return nil;
+}
+
+// End of the NSTextInput protocol adoption.
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Generic input method. It is used to pass on keyboard input to Scintilla. The control itself only
+ * handles shortcuts. The input is then forwarded to the Cocoa text input system, which in turn does
+ * its own input handling (character composition via NSTextInput protocol):
+ */
+- (void) keyDown: (NSEvent *) theEvent
+{
+ mOwner.backend->KeyboardInput(theEvent);
+ NSArray* events = [NSArray arrayWithObject: theEvent];
+ [self interpretKeyEvents: events];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseDown: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseDown(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseDragged: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseMove(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseUp: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseUp(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseMoved: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseMove(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseEntered: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseEntered(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) mouseExited: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseExited(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) scrollWheel: (NSEvent *) theEvent
+{
+ mOwner.backend->MouseWheel(theEvent);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * The editor is getting the foreground control (the one getting the input focus).
+ */
+- (BOOL) becomeFirstResponder
+{
+ mOwner.backend->WndProc(SCI_SETFOCUS, 1, 0);
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * The editor is losing the input focus.
+ */
+- (BOOL) resignFirstResponder
+{
+ mOwner.backend->WndProc(SCI_SETFOCUS, 0, 0);
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called when an external drag operation enters the view.
+ */
+- (NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
+{
+ return mOwner.backend->DraggingEntered(sender);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called frequently during an external drag operation if we are the target.
+ */
+- (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender
+{
+ return mOwner.backend->DraggingUpdated(sender);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Drag image left the view. Clean up if necessary.
+ */
+- (void) draggingExited: (id <NSDraggingInfo>) sender
+{
+ mOwner.backend->DraggingExited(sender);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
+{
+ return YES;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
+{
+ return mOwner.backend->PerformDragOperation(sender);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Returns operations we allow as drag source.
+ */
+- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) flag
+{
+ return NSDragOperationCopy | NSDragOperationMove;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Drag operation is done. Notify editor.
+ */
+- (void) concludeDragOperation: (id <NSDraggingInfo>) sender
+{
+ // Clean up is the same as if we are no longer the drag target.
+ mOwner.backend->DraggingExited(sender);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+// NSResponder actions.
+
+- (void) selectAll: (id) sender
+{
+ mOwner.backend->SelectAll();
+}
+
+- (void) deleteBackward: (id) sender
+{
+ mOwner.backend->DeleteBackward();
+}
+
+- (void) cut: (id) sender
+{
+ mOwner.backend->Cut();
+}
+
+- (void) copy: (id) sender
+{
+ mOwner.backend->Copy();
+}
+
+- (void) paste: (id) sender
+{
+ mOwner.backend->Paste();
+}
+
+- (void) undo: (id) sender
+{
+ mOwner.backend->Undo();
+}
+
+- (void) redo: (id) sender
+{
+ mOwner.backend->Redo();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) dealloc
+{
+ [mCurrentCursor release];
+ [super dealloc];
+}
+
+@end
+
+//--------------------------------------------------------------------------------------------------
+
+@implementation ScintillaView
+
+@synthesize backend = mBackend;
+
+/**
+ * ScintiallView is a composite control made from an NSView and an embedded NSView that is
+ * used as canvas for the output (by the backend, using its CGContext), plus other elements
+ * (scrollers, info bar).
+ */
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Initialize custom cursor.
+ */
++ (void) initialize
+{
+ if (self == [ScintillaView class])
+ {
+ NSBundle* bundle = [NSBundle bundleForClass: [ScintillaView class]];
+
+ NSString* path = [bundle pathForResource: @"mac_cursor_busy" ofType: @"png" inDirectory: nil];
+ NSImage* image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease];
+ waitCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(2, 2)];
+
+ path = [bundle pathForResource: @"mac_cursor_flipped" ofType: @"png" inDirectory: nil];
+ image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease];
+ reverseArrowCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(12, 2)];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Sends a new notification of the given type to the default notification center.
+ */
+- (void) sendNotification: (NSString*) notificationName
+{
+ NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+ [center postNotificationName: notificationName object: self];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by a connected compontent (usually the info bar) if something changed there.
+ *
+ * @param type The type of the notification.
+ * @param message Carries the new status message if the type is a status message change.
+ * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type.
+ * @param location Carries the new zoom value if the type is a zoom change.
+ */
+- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
+ value: (float) value
+{
+ switch (type)
+ {
+ case IBNZoomChanged:
+ {
+ // Compute point increase/decrease based on default font size.
+ int fontSize = [self getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
+ int zoom = (int) (fontSize * (value - 1));
+ [self setGeneralProperty: SCI_SETZOOM parameter: zoom value: 0];
+ break;
+ }
+ };
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) setCallback: (id <InfoBarCommunicator>) callback
+{
+ // Not used. Only here to satisfy protocol.
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Notification function used by Scintilla to call us back (e.g. for handling clicks on the
+ * folder margin or changes in the editor).
+ */
+static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam)
+{
+ // WM_NOTIFY means we got a parent notification with a special notification structure.
+ // Here we don't really differentiate between parent and own notifications and handle both.
+ ScintillaView* editor;
+ switch (iMessage)
+ {
+ case WM_NOTIFY:
+ {
+ // Parent notification. Details are passed as SCNotification structure.
+ SCNotification* scn = reinterpret_cast<SCNotification*>(lParam);
+ editor = reinterpret_cast<InnerView*>(scn->nmhdr.idFrom).owner;
+ switch (scn->nmhdr.code)
+ {
+ case SCN_MARGINCLICK:
+ {
+ if (scn->margin == 2)
+ {
+ // Click on the folder margin. Toggle the current line if possible.
+ int line = [editor getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position];
+ [editor setGeneralProperty: SCI_TOGGLEFOLD parameter: line value: 0];
+ }
+ break;
+ };
+ case SCN_MODIFIED:
+ {
+ // Decide depending on the modification type what to do.
+ // There can be more than one modification carried by one notification.
+ if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))
+ [editor sendNotification: NSTextDidChangeNotification];
+ break;
+ }
+ case SCN_ZOOM:
+ {
+ // A zoom change happend. Notify info bar if there is one.
+ float zoom = [editor getGeneralProperty: SCI_GETZOOM parameter: 0];
+ int fontSize = [editor getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
+ float factor = (zoom / fontSize) + 1;
+ [editor->mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor];
+ break;
+ }
+ case SCN_UPDATEUI:
+ {
+ // Triggered whenever changes in the UI state need to be reflected.
+ // These can be: caret changes, selection changes etc.
+ NSPoint caretPosition = editor->mBackend->GetCaretPosition();
+ [editor->mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0];
+ [editor sendNotification: SCIUpdateUINotification];
+ break;
+ }
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ // Notifications for the editor itself.
+ ScintillaCocoa* backend = reinterpret_cast<ScintillaCocoa*>(lParam);
+ editor = backend->TopContainer();
+ switch (wParam >> 16)
+ {
+ case SCEN_KILLFOCUS:
+ [editor sendNotification: NSTextDidEndEditingNotification];
+ break;
+ case SCEN_SETFOCUS: // Nothing to do for now.
+ break;
+ }
+ break;
+ }
+ };
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Initialization of the view. Used to setup a few other things we need.
+ */
+- (id) initWithFrame: (NSRect) frame
+{
+ self = [super initWithFrame:frame];
+ if (self)
+ {
+ mContent = [[[InnerView alloc] init] autorelease];
+ mBackend = new ScintillaCocoa(mContent);
+ mContent.owner = self;
+ [self addSubview: mContent];
+
+ // Initialize the scrollers but don't show them yet.
+ // Pick an arbitrary size, just to make NSScroller selecting the proper scroller direction
+ // (horizontal or vertical).
+ NSRect scrollerRect = NSMakeRect(0, 0, 100, 10);
+ mHorizontalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease];
+ [mHorizontalScroller setHidden: YES];
+ [mHorizontalScroller setTarget: self];
+ [mHorizontalScroller setAction: @selector(scrollerAction:)];
+ [self addSubview: mHorizontalScroller];
+
+ scrollerRect.size = NSMakeSize(10, 100);
+ mVerticalScroller = [[[NSScroller alloc] initWithFrame: scrollerRect] autorelease];
+ [mVerticalScroller setHidden: YES];
+ [mVerticalScroller setTarget: self];
+ [mVerticalScroller setAction: @selector(scrollerAction:)];
+ [self addSubview: mVerticalScroller];
+
+ // Establish a connection from the back end to this container so we can handle situations
+ // which require our attention.
+ mBackend->RegisterNotifyCallback(nil, notification);
+
+ // Setup a special indicator used in the editor to provide visual feedback for
+ // input composition, depending on language, keyboard etc.
+ [self setColorProperty: SCI_INDICSETFORE parameter: INPUT_INDICATOR fromHTML: @"#FF9A00"];
+ [self setGeneralProperty: SCI_INDICSETUNDER parameter: INPUT_INDICATOR value: 1];
+ [self setGeneralProperty: SCI_INDICSETSTYLE parameter: INPUT_INDICATOR value: INDIC_ROUNDBOX];
+ [self setGeneralProperty: SCI_INDICSETALPHA parameter: INPUT_INDICATOR value: 100];
+ }
+ return self;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) dealloc
+{
+ [mInfoBar release];
+ delete mBackend;
+ [super dealloc];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) viewDidMoveToWindow
+{
+ [super viewDidMoveToWindow];
+
+ [self layout];
+
+ // Enable also mouse move events for our window (and so this view).
+ [[self window] setAcceptsMouseMovedEvents: YES];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to position and size the parts of the editor (content, scrollers, info bar).
+ */
+- (void) layout
+{
+ int scrollerWidth = [NSScroller scrollerWidth];
+
+ NSSize size = [self frame].size;
+ NSRect hScrollerRect = {0, 0, size.width, scrollerWidth};
+ NSRect vScrollerRect = {size.width - scrollerWidth, 0, scrollerWidth, size.height};
+ NSRect barFrame = {0, size.height - scrollerWidth, size.width, scrollerWidth};
+ BOOL infoBarVisible = mInfoBar != nil && ![mInfoBar isHidden];
+
+ // Horizontal offset of the content. Almost always 0 unless the vertical scroller
+ // is on the left side.
+ int contentX = 0;
+
+ // Vertical scroller frame calculation.
+ if (![mVerticalScroller isHidden])
+ {
+ // Consider user settings (left vs right vertical scrollbar).
+ BOOL isLeft = [[[NSUserDefaults standardUserDefaults] stringForKey: @"NSScrollerPosition"]
+ isEqualToString: @"left"];
+ if (isLeft)
+ {
+ vScrollerRect.origin.x = 0;
+ hScrollerRect.origin.x = scrollerWidth;
+ contentX = scrollerWidth;
+ };
+
+ size.width -= scrollerWidth;
+ hScrollerRect.size.width -= scrollerWidth;
+ }
+
+ // Same for horizontal scroller.
+ if (![mHorizontalScroller isHidden])
+ {
+ // Make room for the h-scroller.
+ size.height -= scrollerWidth;
+ vScrollerRect.size.height -= scrollerWidth;
+ vScrollerRect.origin.y += scrollerWidth;
+ };
+
+ // Info bar frame.
+ if (infoBarVisible)
+ {
+ // Initial value already is as if the bar is at top.
+ if (mInfoBarAtTop)
+ {
+ vScrollerRect.size.height -= scrollerWidth;
+ size.height -= scrollerWidth;
+ }
+ else
+ {
+ // Layout info bar and h-scroller side by side in a friendly manner.
+ int nativeWidth = mInitialInfoBarWidth;
+ int remainingWidth = barFrame.size.width;
+
+ barFrame.origin.y = 0;
+
+ if ([mHorizontalScroller isHidden])
+ {
+ // H-scroller is not visible, so take the full space.
+ vScrollerRect.origin.y += scrollerWidth;
+ vScrollerRect.size.height -= scrollerWidth;
+ size.height -= scrollerWidth;
+ }
+ else
+ {
+ // If the left offset of the h-scroller is > 0 then the v-scroller is on the left side.
+ // In this case we take the full width, otherwise what has been given to the h-scroller
+ // and content up to now.
+ if (hScrollerRect.origin.x == 0)
+ remainingWidth = size.width;
+
+ // Note: remainingWidth can become < 0, which hides the scroller.
+ remainingWidth -= nativeWidth;
+
+ hScrollerRect.origin.x = nativeWidth;
+ hScrollerRect.size.width = remainingWidth;
+ barFrame.size.width = nativeWidth;
+ }
+ }
+ }
+
+ NSRect contentRect = {contentX, vScrollerRect.origin.y, size.width, size.height};
+ [mContent setFrame: contentRect];
+
+ if (infoBarVisible)
+ [mInfoBar setFrame: barFrame];
+ if (![mHorizontalScroller isHidden])
+ [mHorizontalScroller setFrame: hScrollerRect];
+ if (![mVerticalScroller isHidden])
+ [mVerticalScroller setFrame: vScrollerRect];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the backend to adjust the vertical scroller (range and page).
+ *
+ * @param range Determines the total size of the scroll area used in the editor.
+ * @param page Determines how many pixels a page is.
+ * @result Returns YES if anything changed, otherwise NO.
+ */
+- (BOOL) setVerticalScrollRange: (int) range page: (int) page
+{
+ BOOL result = NO;
+ BOOL hideScroller = page >= range;
+
+ if ([mVerticalScroller isHidden] != hideScroller)
+ {
+ result = YES;
+ [mVerticalScroller setHidden: hideScroller];
+ if (!hideScroller)
+ [mVerticalScroller setFloatValue: 0];
+ [self layout];
+ }
+
+ if (!hideScroller)
+ {
+ [mVerticalScroller setEnabled: YES];
+
+ CGFloat currentProportion = [mVerticalScroller knobProportion];
+ CGFloat newProportion = page / (CGFloat) range;
+ if (currentProportion != newProportion)
+ {
+ result = YES;
+ [mVerticalScroller setKnobProportion: newProportion];
+ }
+ }
+
+ return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to set the position of the vertical scroll thumb.
+ *
+ * @param position The relative position in the rang [0..1];
+ */
+- (void) setVerticalScrollPosition: (float) position
+{
+ [mVerticalScroller setFloatValue: position];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Called by the backend to adjust the horizontal scroller (range and page).
+ *
+ * @param range Determines the total size of the scroll area used in the editor.
+ * @param page Determines how many pixels a page is.
+ * @result Returns YES if anything changed, otherwise NO.
+ */
+- (BOOL) setHorizontalScrollRange: (int) range page: (int) page
+{
+ BOOL result = NO;
+ BOOL hideScroller = page >= range;
+
+ if ([mHorizontalScroller isHidden] != hideScroller)
+ {
+ result = YES;
+ [mHorizontalScroller setHidden: hideScroller];
+ [self layout];
+ }
+
+ if (!hideScroller)
+ {
+ [mHorizontalScroller setEnabled: YES];
+
+ CGFloat currentProportion = [mHorizontalScroller knobProportion];
+ CGFloat newProportion = page / (CGFloat) range;
+ if (currentProportion != newProportion)
+ {
+ result = YES;
+ [mHorizontalScroller setKnobProportion: newProportion];
+ }
+ }
+
+ return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to set the position of the vertical scroll thumb.
+ *
+ * @param position The relative position in the rang [0..1];
+ */
+- (void) setHorizontalScrollPosition: (float) position
+{
+ [mHorizontalScroller setFloatValue: position];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Triggered by one of the scrollers when it gets manipulated by the user. Notify the backend
+ * about the change.
+ */
+- (void) scrollerAction: (id) sender
+{
+ float position = [sender floatValue];
+ mBackend->DoScroll(position, [sender hitPart], sender == mHorizontalScroller);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Used to reposition our content depending on the size of the view.
+ */
+- (void) setFrame: (NSRect) newFrame
+{
+ [super setFrame: newFrame];
+ [self layout];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Getter for the currently selected text in raw form (no formatting information included).
+ * If there is no text available an empty string is returned.
+ */
+- (NSString*) selectedString
+{
+ NSString *result = @"";
+
+ char *buffer(0);
+ const int length = mBackend->WndProc(SCI_GETSELTEXT, 0, 0);
+ if (length > 0)
+ {
+ buffer = new char[length + 1];
+ try
+ {
+ mBackend->WndProc(SCI_GETSELTEXT, length + 1, (sptr_t) buffer);
+ mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0);
+
+ result = [NSString stringWithUTF8String: buffer];
+ delete[] buffer;
+ }
+ catch (...)
+ {
+ delete[] buffer;
+ buffer = 0;
+ }
+ }
+
+ return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Getter for the current text in raw form (no formatting information included).
+ * If there is no text available an empty string is returned.
+ */
+- (NSString*) string
+{
+ NSString *result = @"";
+
+ char *buffer(0);
+ const int length = mBackend->WndProc(SCI_GETLENGTH, 0, 0);
+ if (length > 0)
+ {
+ buffer = new char[length + 1];
+ try
+ {
+ mBackend->WndProc(SCI_GETTEXT, length + 1, (sptr_t) buffer);
+ mBackend->WndProc(SCI_SETSAVEPOINT, 0, 0);
+
+ result = [NSString stringWithUTF8String: buffer];
+ delete[] buffer;
+ }
+ catch (...)
+ {
+ delete[] buffer;
+ buffer = 0;
+ }
+ }
+
+ return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Setter for the current text (no formatting included).
+ */
+- (void) setString: (NSString*) aString
+{
+ const char* text = [aString UTF8String];
+ mBackend->WndProc(SCI_SETTEXT, 0, (long) text);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) insertString: (NSString*) aString atOffset: (int)offset
+{
+ const char* text = [aString UTF8String];
+ mBackend->WndProc(SCI_ADDTEXT, offset, (long) text);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (void) setEditable: (BOOL) editable
+{
+ mBackend->WndProc(SCI_SETREADONLY, editable ? 0 : 1, 0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (BOOL) isEditable
+{
+ return mBackend->WndProc(SCI_GETREADONLY, 0, 0) != 0;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+- (InnerView*) content
+{
+ return mContent;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Direct call into the backend to allow uninterpreted access to it. The values to be passed in and
+ * the result heavily depend on the message that is used for the call. Refer to the Scintilla
+ * documentation to learn what can be used here.
+ */
++ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam
+ lParam: (sptr_t) lParam
+{
+ return ScintillaCocoa::DirectFunction(sender->mBackend, message, wParam, lParam);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * This is a helper method to set properties in the backend, with native parameters.
+ *
+ * @param property Main property like SCI_STYLESETFORE for which a value is to be set.
+ * @param parameter Additional info for this property like a parameter or index.
+ * @param value The actual value. It depends on the property what this parameter means.
+ */
+- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value
+{
+ mBackend->WndProc(property, parameter, value);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * This is a helper method to get a property in the backend, with native parameters.
+ *
+ * @param property Main property like SCI_STYLESETFORE for which a value is to get.
+ * @param parameter Additional info for this property like a parameter or index.
+ * @param extra Yet another parameter if needed.
+ * @result A generic value which must be interpreted depending on the property queried.
+ */
+- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra
+{
+ return mBackend->WndProc(property, parameter, extra);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Convenience function to avoid unneeded extra parameter.
+ */
+- (long) getGeneralProperty: (int) property parameter: (long) parameter
+{
+ return mBackend->WndProc(property, parameter, 0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Convenience function to avoid unneeded parameters.
+ */
+- (long) getGeneralProperty: (int) property
+{
+ return mBackend->WndProc(property, 0, 0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Use this variant if you have to pass in a reference to something (e.g. a text range).
+ */
+- (long) getGeneralProperty: (int) property ref: (const void*) ref
+{
+ return mBackend->WndProc(property, 0, (sptr_t) ref);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property setter for colors.
+ */
+- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value
+{
+ if ([value colorSpaceName] != NSDeviceRGBColorSpace)
+ value = [value colorUsingColorSpaceName: NSDeviceRGBColorSpace];
+ long red = [value redComponent] * 255;
+ long green = [value greenComponent] * 255;
+ long blue = [value blueComponent] * 255;
+
+ long color = (blue << 16) + (green << 8) + red;
+ mBackend->WndProc(property, parameter, color);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Another color property setting, which allows to specify the color as string like in HTML
+ * documents (i.e. with leading # and either 3 hex digits or 6).
+ */
+- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML
+{
+ if ([fromHTML length] > 3 && [fromHTML characterAtIndex: 0] == '#')
+ {
+ bool longVersion = [fromHTML length] > 6;
+ int index = 1;
+
+ char value[3] = {0, 0, 0};
+ value[0] = [fromHTML characterAtIndex: index++];
+ if (longVersion)
+ value[1] = [fromHTML characterAtIndex: index++];
+ else
+ value[1] = value[0];
+
+ unsigned rawRed;
+ [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawRed];
+
+ value[0] = [fromHTML characterAtIndex: index++];
+ if (longVersion)
+ value[1] = [fromHTML characterAtIndex: index++];
+ else
+ value[1] = value[0];
+
+ unsigned rawGreen;
+ [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawGreen];
+
+ value[0] = [fromHTML characterAtIndex: index++];
+ if (longVersion)
+ value[1] = [fromHTML characterAtIndex: index++];
+ else
+ value[1] = value[0];
+
+ unsigned rawBlue;
+ [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawBlue];
+
+ long color = (rawBlue << 16) + (rawGreen << 8) + rawRed;
+ mBackend->WndProc(property, parameter, color);
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property getter for colors.
+ */
+- (NSColor*) getColorProperty: (int) property parameter: (long) parameter
+{
+ int color = mBackend->WndProc(property, parameter, 0);
+ float red = (color & 0xFF) / 255.0;
+ float green = ((color >> 8) & 0xFF) / 255.0;
+ float blue = ((color >> 16) & 0xFF) / 255.0;
+ NSColor* result = [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1];
+ return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property setter for references (pointers, addresses).
+ */
+- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value
+{
+ mBackend->WndProc(property, parameter, (sptr_t) value);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property getter for references (pointers, addresses).
+ */
+- (const void*) getReferenceProperty: (int) property parameter: (long) parameter
+{
+ return (const void*) mBackend->WndProc(property, parameter, 0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property setter for string values.
+ */
+- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value
+{
+ const char* rawValue = [value UTF8String];
+ mBackend->WndProc(property, parameter, (sptr_t) rawValue);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property getter for string values.
+ */
+- (NSString*) getStringProperty: (int) property parameter: (long) parameter
+{
+ const char* rawValue = (const char*) mBackend->WndProc(property, parameter, 0);
+ return [NSString stringWithUTF8String: rawValue];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property setter for lexer properties, which are commonly passed as strings.
+ */
+- (void) setLexerProperty: (NSString*) name value: (NSString*) value
+{
+ const char* rawName = [name UTF8String];
+ const char* rawValue = [value UTF8String];
+ mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, (sptr_t) rawValue);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Specialized property getter for references (pointers, addresses).
+ */
+- (NSString*) getLexerProperty: (NSString*) name
+{
+ const char* rawName = [name UTF8String];
+ const char* result = (const char*) mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, 0);
+ return [NSString stringWithUTF8String: result];
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Sets the new control which is displayed as info bar at the top or bottom of the editor.
+ * Set newBar to nil if you want to hide the bar again.
+ * When aligned to bottom position then the info bar and the horizontal scroller share the available
+ * space. The info bar will then only get the width it is currently set to less a minimal amount
+ * reserved for the scroller. At the top position it gets the full width of the control.
+ * The info bar's height is set to the height of the scrollbar.
+ */
+- (void) setInfoBar: (NSView <InfoBarCommunicator>*) newBar top: (BOOL) top
+{
+ if (mInfoBar != newBar)
+ {
+ [mInfoBar removeFromSuperview];
+
+ mInfoBar = newBar;
+ mInfoBarAtTop = top;
+ if (mInfoBar != nil)
+ {
+ [self addSubview: mInfoBar];
+ [mInfoBar setCallback: self];
+
+ // Keep the initial width as reference for layout changes.
+ mInitialInfoBarWidth = [mInfoBar frame].size.width;
+ }
+
+ [self layout];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Sets the edit's info bar status message. This call only has an effect if there is an info bar.
+ */
+- (void) setStatusText: (NSString*) text
+{
+ if (mInfoBar != nil)
+ [mInfoBar notify: IBNStatusChanged message: text location: NSZeroPoint value: 0];
+}
+
+- (NSRange) selectedRange
+{
+ return [mContent selectedRange];
+}
+
+- (void)insertText: (NSString*)text
+{
+ [mContent insertText: text];
+}
+
+@end
+
+//--------------------------------------------------------------------------------------------------
+
diff --git a/scintilla/cocoa/res/info_bar_bg.png b/scintilla/cocoa/res/info_bar_bg.png
new file mode 100644
index 0000000..79010fa
--- /dev/null
+++ b/scintilla/cocoa/res/info_bar_bg.png
Binary files differ
diff --git a/scintilla/cocoa/res/mac_cursor_busy.png b/scintilla/cocoa/res/mac_cursor_busy.png
new file mode 100644
index 0000000..9ac8276
--- /dev/null
+++ b/scintilla/cocoa/res/mac_cursor_busy.png
Binary files differ
diff --git a/scintilla/cocoa/res/mac_cursor_flipped.png b/scintilla/cocoa/res/mac_cursor_flipped.png
new file mode 100644
index 0000000..2c984f2
--- /dev/null
+++ b/scintilla/cocoa/res/mac_cursor_flipped.png
Binary files differ
diff --git a/scintilla/delbin.bat b/scintilla/delbin.bat
new file mode 100644
index 0000000..8d29322
--- /dev/null
+++ b/scintilla/delbin.bat
@@ -0,0 +1 @@
+del /S /Q *.a *.aps *.bsc *.dll *.dsw *.exe *.idb *.ilc *.ild *.ilf *.ilk *.ils *.lib *.map *.ncb *.obj *.o *.opt *.pdb *.plg *.res *.sbr *.tds *.exp >NUL:
diff --git a/scintilla/delcvs.bat b/scintilla/delcvs.bat
new file mode 100644
index 0000000..d3ed21c
--- /dev/null
+++ b/scintilla/delcvs.bat
@@ -0,0 +1 @@
+del /S /Q .cvsignore
diff --git a/scintilla/doc/Design.html b/scintilla/doc/Design.html
new file mode 100644
index 0000000..d426cb3
--- /dev/null
+++ b/scintilla/doc/Design.html
@@ -0,0 +1,249 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla and SciTE
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ Component Design</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Top level structure
+ </h2>
+ <p>
+ Scintilla consists of three major layers of C++ code
+ </p>
+ <ul>
+ <li>
+ Portability Library
+ </li>
+ <li>
+ Core Code
+ </li>
+ <li>
+ Platform Events and API
+ </li>
+ </ul>
+ <p>
+ The primary purpose of this structure is to separate the platform dependent code from the
+ platform independent core code. This makes it easier to port Scintilla to a new platform and
+ ensures that most readers of the code do not have to deal with platform details. To minimise
+ portability problems and avoid code bloat, a conservative subset of C++ is used in Scintilla
+ with no exception handling, run time type information or use of the standard C++
+ library and with limited use of templates.
+ </p>
+ <p>
+ The currently supported platforms, Windows, GTK+/Linux and wxWindows are fairly similar in
+ many ways.
+ Each has windows, menus and bitmaps. These features generally work in similar ways so each
+ has a way to move a window or draw a red line. Sometimes one platform requires a sequence of
+ calls rather than a single call. At other times, the differences are more profound. Reading
+ the Windows clipboard occurs synchronously but reading the GTK+ clipboard requires a request
+ call that will be asynchronously answered with a message containing the clipboard data.
+ The wxWindows platform is available from the <a href="http://wxwindows.org/">wxWindows site</a>
+ </p>
+ <br />
+ <h3>
+ Portability Library
+ </h3>
+ <p>
+ This is a fairly small and thin layer over the platform's native capabilities.
+ </p>
+ <p>
+ The portability library is defined in Platform.h and is implemented once for each platform.
+ PlatWin.cxx defines the Windows variants of the methods and PlatGTK.cxx the GTK+ variants.
+ </p>
+ <p>
+ Several of the classes here hold platform specific object identifiers and act as proxies to
+ these platform objects. Most client code can thus manipulate the platform objects without
+ caring which is the current platform. Sometimes client code needs access to the underlying
+ object identifiers and this is provided by the GetID method. The underlying types of the
+ platform specific identifiers are typedefed to common names to allow them to be transferred
+ around in client code where needed.
+ </p>
+ <h4>
+ Point, PRectangle
+ </h4>
+ <p>
+ These are simple classes provided to hold the commonly used geometric primitives. A
+ PRectangle follows the Mac / Windows convention of not including its bottom and right sides
+ instead of including all its sides as is normal in GTK+. It is not called Rectangle as this may be
+ the name of a macro on Windows.
+ </p>
+ <h4>
+ Colour, ColourPair, Palette
+ </h4>
+ <p>
+ Colour holds a platform specific colour identifier - COLORREF for Windows and GdkColor for
+ GTK+. The red, green and blue components that make up the colour are limited to the 8 bits of
+ precision available on Windows. ColourPairs are used because not all possible colours are
+ always available. Using an 8 bit colour mode, which is a common setting for both Windows and
+ GTK+, only 256 colours are possible on the display. Thus when an application asks for a dull
+ red, say #400000, it may only be allocated an already available colour such as #800000 or
+ #330000. With 16 or 2 colour modes even less choice is available and the application will
+ have to use the limited set of already available colours.
+ </p>
+ A Palette object holds a set of colour pairs and can make the appropriate calls to ask to
+ allocate these colours and to see what the platform has decided will be allowed.
+ <h4>
+ Font
+ </h4>
+ <p>
+ Font holds a platform specific font identifier - HFONT for Windows, GdkFont* for GTK+. It
+ does not own the identifier and so will not delete the platform font object in its
+ destructor. Client code should call Destroy at appropriate times.
+ </p>
+ <h4>
+ Surface
+ </h4>
+ <p>
+ Surface is an abstraction over each platform's concept of somewhere that graphical drawing
+ operations can be done. It may wrap an already created drawing place such as a window or be
+ used to create a bitmap that can be drawn into and later copied onto another surface. On
+ Windows it wraps a HDC and possibly a HBITMAP. On GTK+ it wraps a GdkDrawable* and possibly a
+ GdkPixmap*. Other platform specific objects are created (and correctly destroyed) whenever
+ required to perform drawing actions.
+ </p>
+ <p>
+ Drawing operations provided include drawing filled and unfilled polygons, lines, rectangles,
+ ellipses and text. The height and width of text as well as other details can be measured.
+ Operations can be clipped to a rectangle. Most of the calls are stateless with all parameters
+ being passed at each call. The exception to this is line drawing which is performed by
+ calling MoveTo and then LineTo.
+ </p>
+ <h4>
+ Window
+ </h4>
+ <p>
+ Window acts as a proxy to a platform window allowing operations such as showing, moving,
+ redrawing, and destroying to be performed. It contains a platform specific window identifier
+ - HWND for Windows, GtkWidget* for GTK+.
+ </p>
+ <h4>
+ ListBox
+ </h4>
+ <p>
+ ListBox is a subclass of Window and acts as a proxy to a platform listbox adding methods for
+ operations such as adding, retrieving, and selecting items.
+ </p>
+ <h4>
+ Menu
+ </h4>
+ <p>
+ Menu is a small helper class for constructing popup menus. It contains the platform specific
+ menu identifier - HMENU for Windows, GtkItemFactory* for GTK+. Most of the work in
+ constructing menus requires access to platform events and so is done in the Platform Events
+ and API layer.
+ </p>
+ <h4>
+ Platform
+ </h4>
+ <p>
+ The Platform class is used to access the facilities of the platform. System wide parameters
+ such as double click speed and chrome colour are available from Platform. Utility functions
+ such as DebugPrintf are also available from Platform.
+ </p>
+ <h3>
+ Core Code
+ </h3>
+ <p>
+ The bulk of Scintilla's code is platform independent. This is made up of the CellBuffer,
+ ContractionState, Document, Editor, Indicator, LineMarker, Style, ViewStyle, KeyMap,
+ ScintillaBase, CallTip,
+ and AutoComplete primary classes.
+ </p>
+ <h4>
+ CellBuffer
+ </h4>
+ <p>
+ A CellBuffer holds text and styling information, the undo stack, the assignment of line
+ markers to lines, and the fold structure.
+ </p>
+ <p>
+ A cell contains a character byte and its associated style byte. The current state of the
+ cell buffer is the sequence of cells that make up the text and a sequence of line information
+ containing the starting position of each line and any markers assigned to each line.
+ </p>
+ <p>
+ The undo stack holds a sequence of actions on the cell buffer. Each action is one of a text
+ insertion, a text deletion or an undo start action. The start actions are used to group
+ sequences of text insertions and deletions together so they can be undone together. To
+ perform an undo operation, each insertion or deletion is undone in reverse sequence.
+ Similarly, redo reapplies each action to the buffer in sequence. Whenever a character is
+ inserted in the buffer either directly through a call such as InsertString or through undo or
+ redo, its styling byte is initially set to zero. Client code is responsible for styling each
+ character whenever convenient. Styling information is not stored in undo actions.
+ </p>
+ <h4>
+ Document
+ </h4>
+ <p>
+ A document contains a CellBuffer and deals with some higher level abstractions such as
+ words, DBCS character sequences and line end character sequences. It is responsible for
+ managing the styling process and for notifying other objects when changes occur to the
+ document.
+ </p>
+ <h4>
+ Editor
+ </h4>
+ <p>
+ The Editor object is central to Scintilla. It is responsible for displaying a document and
+ responding to user actions and requests from the container. It uses ContractionState, Indicator,
+ LineMarker, Style, and ViewStyle objects to display the document and a KeyMap class to
+ map key presses to functions.
+ The visibility of each line is kept in the ContractionState which is also responsible for mapping
+ from display lines to documents lines and vice versa.
+ </p>
+ <p>
+ There may be multiple Editor objects attached to one Document object. Changes to a
+ document are broadcast to the editors through the DocWatcher mechanism.
+ </p>
+ <h4>
+ ScintillaBase
+ </h4>
+ <p>
+ ScintillaBase is a subclass of Editor and adds extra windowing features including display of
+ calltips, autocompletion lists and context menus. These features use CallTip and AutoComplete
+ objects. This class is optional so a lightweight implementation of Scintilla may bypass it if
+ the added functionality is not required.
+ </p>
+ <h3>
+ Platform Events and API
+ </h3>
+ <p>
+ Each platform uses different mechanisms for receiving events. On Windows, events are
+ received through messages and COM. On GTK+, callback functions are used.
+ </p>
+ <p>
+ For each platform, a class is derived from ScintillaBase (and thus from Editor). This is
+ ScintillaWin on Windows and ScintillaGTK on GTK+. These classes are responsible for
+ connecting to the platforms event mechanism and also to implement some virtual methods in
+ Editor and ScintillaBase which are different on the platforms. For example, this layer has to
+ support this difference between the synchronous Windows clipboard and the asynchronous GTK+
+ clipboard.
+ </p>
+ <p>
+ The external API is defined in this layer as each platform has different preferred styles of
+ API - messages on Windows and function calls on GTK+. This also allows multiple APIs to be
+ defined on a platform. The currently available API on GTK+ is similar to the Windows API and
+ does not follow platform conventions well. A second API could be implemented here that did
+ follow platform conventions.
+ </p>
+ </body>
+</html>
+
diff --git a/scintilla/doc/Icons.html b/scintilla/doc/Icons.html
new file mode 100644
index 0000000..0d8b8bf
--- /dev/null
+++ b/scintilla/doc/Icons.html
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla icons
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ and SciTE</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Icons
+ </h2>
+ <p>
+ These images may be used under the same license as Scintilla.
+ </p>
+ <p>
+ Drawn by Iago Rubio, Philippe Lhoste, and Neil Hodgson.
+ </p>
+ <p>
+ <a href="http://prdownloads.sourceforge.net/scintilla/icons1.zip?download">zip format</a> (70K)
+ </p>
+ <table>
+ <tr>
+ <td>For autocompletion lists</td>
+ <td colspan="3">For margin markers</td>
+ </tr>
+ <tr>
+ <td>12x12</td>
+ <td>16x16</td>
+ <td>24x24</td>
+ <td>32x32</td>
+ </tr>
+ <tr>
+ <td valign="top"><img src="12.png" /></td>
+ <td valign="top"><img src="16.png" /></td>
+ <td valign="top"><img src="24.png" /></td>
+ <td valign="top"><img src="32.png" /></td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scintilla/doc/Lexer.txt b/scintilla/doc/Lexer.txt
new file mode 100644
index 0000000..5f118e7
--- /dev/null
+++ b/scintilla/doc/Lexer.txt
@@ -0,0 +1,226 @@
+How to write a scintilla lexer
+
+A lexer for a particular language determines how a specified range of
+text shall be colored. Writing a lexer is relatively straightforward
+because the lexer need only color given text. The harder job of
+determining how much text actually needs to be colored is handled by
+Scintilla itself, that is, the lexer's caller.
+
+
+Parameters
+
+The lexer for language LLL has the following prototype:
+
+ static void ColouriseLLLDoc (
+ unsigned int startPos, int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler);
+
+The styler parameter is an Accessor object. The lexer must use this
+object to access the text to be colored. The lexer gets the character
+at position i using styler.SafeGetCharAt(i);
+
+The startPos and length parameters indicate the range of text to be
+recolored; the lexer must determine the proper color for all characters
+in positions startPos through startPos+length.
+
+The initStyle parameter indicates the initial state, that is, the state
+at the character before startPos. States also indicate the coloring to
+be used for a particular range of text.
+
+Note: the character at StartPos is assumed to start a line, so if a
+newline terminates the initStyle state the lexer should enter its
+default state (or whatever state should follow initStyle).
+
+The keywordlists parameter specifies the keywords that the lexer must
+recognize. A WordList class object contains methods that make simplify
+the recognition of keywords. Present lexers use a helper function
+called classifyWordLLL to recognize keywords. These functions show how
+to use the keywordlists parameter to recognize keywords. This
+documentation will not discuss keywords further.
+
+
+The lexer code
+
+The task of a lexer can be summarized briefly: for each range r of
+characters that are to be colored the same, the lexer should call
+
+ styler.ColourTo(i, state)
+
+where i is the position of the last character of the range r. The lexer
+should set the state variable to the coloring state of the character at
+position i and continue until the entire text has been colored.
+
+Note 1: the styler (Accessor) object remembers the i parameter in the
+previous calls to styler.ColourTo, so the single i parameter suffices to
+indicate a range of characters.
+
+Note 2: As a side effect of calling styler.ColourTo(i,state), the
+coloring states of all characters in the range are remembered so that
+Scintilla may set the initStyle parameter correctly on future calls to
+the
+lexer.
+
+
+Lexer organization
+
+There are at least two ways to organize the code of each lexer. Present
+lexers use what might be called a "character-based" approach: the outer
+loop iterates over characters, like this:
+
+ lengthDoc = startPos + length ;
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ chNext = styler.SafeGetCharAt(i + 1);
+ << handle special cases >>
+ switch(state) {
+ // Handlers examine only ch and chNext.
+ // Handlers call styler.ColorTo(i,state) if the state changes.
+ case state_1: << handle ch in state 1 >>
+ case state_2: << handle ch in state 2 >>
+ ...
+ case state_n: << handle ch in state n >>
+ }
+ chPrev = ch;
+ }
+ styler.ColourTo(lengthDoc - 1, state);
+
+
+An alternative would be to use a "state-based" approach. The outer loop
+would iterate over states, like this:
+
+ lengthDoc = startPos+lenth ;
+ for ( unsigned int i = startPos ;; ) {
+ char ch = styler.SafeGetCharAt(i);
+ int new_state = 0 ;
+ switch ( state ) {
+ // scanners set new_state if they set the next state.
+ case state_1: << scan to the end of state 1 >> break ;
+ case state_2: << scan to the end of state 2 >> break ;
+ case default_state:
+ << scan to the next non-default state and set new_state >>
+ }
+ styler.ColourTo(i, state);
+ if ( i >= lengthDoc ) break ;
+ if ( ! new_state ) {
+ ch = styler.SafeGetCharAt(i);
+ << set state based on ch in the default state >>
+ }
+ }
+ styler.ColourTo(lengthDoc - 1, state);
+
+This approach might seem to be more natural. State scanners are simpler
+than character scanners because less needs to be done. For example,
+there is no need to test for the start of a C string inside the scanner
+for a C comment. Also this way makes it natural to define routines that
+could be used by more than one scanner; for example, a scanToEndOfLine
+routine.
+
+However, the special cases handled in the main loop in the
+character-based approach would have to be handled by each state scanner,
+so both approaches have advantages. These special cases are discussed
+below.
+
+Special case: Lead characters
+
+Lead bytes are part of DBCS processing for languages such as Japanese
+using an encoding such as Shift-JIS. In these encodings, extended
+(16-bit) characters are encoded as a lead byte followed by a trail byte.
+
+Lead bytes are rarely of any lexical significance, normally only being
+allowed within strings and comments. In such contexts, lexers should
+ignore ch if styler.IsLeadByte(ch) returns TRUE.
+
+Note: UTF-8 is simpler than Shift-JIS, so no special handling is
+applied for it. All UTF-8 extended characters are >= 128 and none are
+lexically significant in programming languages which, so far, use only
+characters in ASCII for operators, comment markers, etc.
+
+
+Special case: Folding
+
+Folding may be performed in the lexer function. It is better to use a
+separate folder function as that avoids some troublesome interaction
+between styling and folding. The folder function will be run after the
+lexer function if folding is enabled. The rest of this section explains
+how to perform folding within the lexer function.
+
+During initialization, lexers that support folding set
+
+ bool fold = styler.GetPropertyInt("fold");
+
+If folding is enabled in the editor, fold will be TRUE and the lexer
+should call:
+
+ styler.SetLevel(line, level);
+
+at the end of each line and just before exiting.
+
+The line parameter is simply the count of the number of newlines seen.
+It's initial value is styler.GetLine(startPos) and it is incremented
+(after calling styler.SetLevel) whenever a newline is seen.
+
+The level parameter is the desired indentation level in the low 12 bits,
+along with flag bits in the upper four bits. The indentation level
+depends on the language. For C++, it is incremented when the lexer sees
+a '{' and decremented when the lexer sees a '}' (outside of strings and
+comments, of course).
+
+The following flag bits, defined in Scintilla.h, may be set or cleared
+in the flags parameter. The SC_FOLDLEVELWHITEFLAG flag is set if the
+lexer considers that the line contains nothing but whitespace. The
+SC_FOLDLEVELHEADERFLAG flag indicates that the line is a fold point.
+This normally means that the next line has a greater level than present
+line. However, the lexer may have some other basis for determining a
+fold point. For example, a lexer might create a header line for the
+first line of a function definition rather than the last.
+
+The SC_FOLDLEVELNUMBERMASK mask denotes the level number in the low 12
+bits of the level param. This mask may be used to isolate either flags
+or level numbers.
+
+For example, the C++ lexer contains the following code when a newline is
+seen:
+
+ if (fold) {
+ int lev = levelPrev;
+
+ // Set the "all whitespace" bit if the line is blank.
+ if (visChars == 0)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+
+ // Set the "header" bit if needed.
+ if ((levelCurrent > levelPrev) && (visChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ styler.SetLevel(lineCurrent, lev);
+
+ // reinitialize the folding vars describing the present line.
+ lineCurrent++;
+ visChars = 0; // Number of non-whitespace characters on the line.
+ levelPrev = levelCurrent;
+ }
+
+The following code appears in the C++ lexer just before exit:
+
+ // Fill in the real level of the next line, keeping the current flags
+ // as they will be filled in later.
+ if (fold) {
+ // Mask off the level number, leaving only the previous flags.
+ int flagsNext = styler.LevelAt(lineCurrent);
+ flagsNext &= ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+ }
+
+
+Don't worry about performance
+
+The writer of a lexer may safely ignore performance considerations: the
+cost of redrawing the screen is several orders of magnitude greater than
+the cost of function calls, etc. Moreover, Scintilla performs all the
+important optimizations; Scintilla ensures that a lexer will be called
+only to recolor text that actually needs to be recolored. Finally, it
+is not necessary to avoid extra calls to styler.ColourTo: the sytler
+object buffers calls to ColourTo to avoid multiple updates of the
+screen.
+
+Page contributed by Edward K. Ream \ No newline at end of file
diff --git a/scintilla/doc/SciBreak.jpg b/scintilla/doc/SciBreak.jpg
new file mode 100644
index 0000000..b63b09f
--- /dev/null
+++ b/scintilla/doc/SciBreak.jpg
Binary files differ
diff --git a/scintilla/doc/SciCoding.html b/scintilla/doc/SciCoding.html
new file mode 100644
index 0000000..f34fde6
--- /dev/null
+++ b/scintilla/doc/SciCoding.html
@@ -0,0 +1,261 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla and SciTE Code Style Preferences
+ </title>
+ <style>
+ .S0 {
+ color: #808080;
+ }
+ .S1 {
+ font-family: Comic Sans MS;
+ color: #007F00;
+ font-size: 9pt;
+ }
+ .S2 {
+ font-family: Comic Sans MS;
+ color: #007F00;
+ font-size: 9pt;
+ }
+ .S3 {
+ font-family: Comic Sans MS;
+ color: #3F703F;
+ font-size: 9pt;
+ }
+ .S4 {
+ color: #007F7F;
+ }
+ .S5 {
+ font-weight: bold;
+ color: #00007F;
+ }
+ .S6 {
+ color: #7F007F;
+ }
+ .S7 {
+ color: #7F007F;
+ }
+ .S8 {
+ color: #804080;
+ }
+ .S9 {
+ color: #7F7F00;
+ }
+ .S10 {
+ font-weight: bold;
+ color: #000000;
+ }
+ .S12 {
+ font-family: Courier New;
+ color: #000000;
+ background: #E0C0E0;
+ font-size: 10pt;
+ }
+ .S13 {
+ font-family: Courier New;
+ color: #007F00;
+ background: #E0FFE0;
+ font-size: 10pt;
+ }
+ .S14 {
+ font-family: Courier New;
+ color: #3F7F3F;
+ background: #E0F0FF;
+ font-size: 10pt;
+ }
+ .S15 {
+ font-family: Comic Sans MS;
+ color: #3F703F;
+ font-size: 9pt;
+ }
+ SPAN {
+ font-family: Verdana;
+ font-size: 10pt;
+ }
+ </style>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ and SciTE</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Code Style
+ </h2>
+ <h3>
+ Introduction
+ </h3>
+ <p>
+ The source code of Scintilla and SciTE follow my preferences.
+ Some of these decisions are arbitrary and based on my sense of aesthetics
+ but its good to have all the code look the same even if its not exactly how
+ everyone would prefer.
+ </p>
+ <p>
+ Code that does not follow these conventions will be accepted, but will be modified
+ as time goes by to fit the conventions. Scintilla code follows the conventions more
+ closely than SciTE except for lexers which are relatively independent modules.
+ Lexers that are maintained by others are left as they are submitted except that
+ warnings will be fixed so the whole project can compile cleanly.
+ </p>
+ <p>
+ The <a href="http://astyle.sourceforge.net/">AStyle</a> formatting
+ program with a '-tapO' argument formats code in much the right way although
+ there are a few bugs in AStyle. The scite/scripts/Fixer.py script will run AStyle
+ over a C++ source file and fix up some of those bugs.
+ </p>
+ <h3>
+ Language features
+ </h3>
+ <p>
+ Design goals for Scintilla and SciTE include portability to currently available C++
+ compilers on diverse platforms with high performance and low resource usage.
+ Scintilla has stricter portability requirements to SciTE as it may be ported to
+ low capability platforms such as Windows CE or PalmOS but it is less likely
+ SciTE will be.
+ </p>
+ <p>
+ To achieve portability, only a subset of C++ features are used. Exceptions are
+ not available on some platforms such as Windows CE so exceptions are not used
+ and thus the standard C++ library can not be used.
+ Template support differs between compilers so is not used in Scintilla but there
+ are some simple uses in SciTE.
+ Run-time type information adds to memory use so is turned off.
+ Name spaces are not used.
+ </p>
+ <p>
+ The goto statement is not used because of bad memories from my first job
+ maintaining FORTRAN programs. The union feature is not used as it can lead to
+ non-type-safe value access.
+ </p>
+ <h3>
+ Casting
+ </h3>
+ <p>
+ Do not use old C style casts like (char *)s. Instead use the most strict form of C++
+ cast possible like const_cast&lt;char *&gt;(s). Use static_cast and const_cast
+ where possible rather than reinterpret_cast. Because the code is compiled with
+ run-time type information turned off, dynamic_cast will not work.
+ </p>
+ <p>
+ The benefit to using the new style casts is that they explicitly detail what evil is
+ occurring and act as signals that something potentially unsafe is being done.
+ </p>
+ <p>
+ Code that treats const seriously is easier to reason about both for humans
+ and compilers, so use const parameters and avoid const_cast.
+ </p>
+ <h3>
+ Warnings
+ </h3>
+ <p>
+ To help ensure code is well written and portable, it is compiled with almost all
+ warnings turned on. This sometimes results in warnings about code that is
+ completely good (false positives) but changing the code to avoid the warnings
+ is generally fast and has little impact on readability.
+ </p>
+ <p>
+ Initialise all variables and minimise the scope of variables. If a variable is defined
+ just before its use then it can't be misused by code before that point.
+ Use loop declarations that are compatible with both the C++ standard and currently
+ available compilers.
+ </p>
+ <h3>
+ Allocation
+ </h3>
+ <p>
+ As exceptions are not used, memory exhaustion can occur.
+ This should be checked for and handled but there is quite a lot of Scintilla and
+ SciTE code that doesn't yet.
+ Fixed length buffers are often used as these are simple and avoid the need to
+ worry about memory exhaustion but then require that buffer lengths are
+ respected.
+ </p>
+ <p>
+ The C++ new and delete operators are preferred over C's malloc and free
+ as new and delete are type safe.
+ </p>
+ <h3>
+ Bracketing
+ </h3>
+ <p>
+ Start brackets, '{', should be located on the line of the control structure they
+ start and end brackets, '}', should be at the indented start of a line. When there is
+ an else clause, this occurs on the same line as the '}'.
+ This format uses less lines than alternatives, allowing more code to be seen on screen.
+ Fully bracketed control
+ structures are preferred because this makes it more likely that modifications will
+ be correct and it allows Scintilla's folder to work. No braces on returned
+ expressions as return is a keyword, not a function call.
+ </p>
+<SPAN class=S0></SPAN><SPAN class=S5>bool</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>fn</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>t</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>else</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>u</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>return</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>!</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
+</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
+</SPAN> <h3>
+ Spacing
+ </h3>
+ <p>
+ Spaces on both sides of '=' and comparison operators and no attempt to line up '='.
+ No space before or after '(', when used in calls, but a space after every ','.
+ No spaces between tokens in short expressions but may be present in
+ longer expressions. Space before '{'. No space before ';'.
+ No space after '*' when used to mean pointer and no space after '[' or ']'.
+ One space between keywords and '('.
+ </p>
+<SPAN class=S0></SPAN><SPAN class=S5>void</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>StoreConditionally</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>c</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>const</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>char</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>c</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>&amp;&amp;</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>==</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>trustSegment</SPAN><SPAN class=S10>[</SPAN><SPAN class=S6>"html"</SPAN><SPAN class=S10>]))</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>+</SPAN><SPAN class=S4>1</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>Store</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S6>"html"</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
+</SPAN><SPAN class=S10>}</SPAN>
+ <h3>
+ Names
+ </h3>
+ <p>
+ Identifiers use mixed case and no underscores.
+ Class, function and method names start with an uppercase letter and use
+ further upper case letters to distinguish words. Variables start with a lower
+ case letter and use upper case letters to distinguish words.
+ Loop counters and similar variables can have simple names like 'i'.
+ Function calls should be differentiated from method calls with an initial '::'
+ global scope modifier.
+ </p>
+<SPAN class=S0></SPAN><SPAN class=S5>class</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>StorageZone</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+</SPAN><SPAN class=S5>public</SPAN><SPAN class=S10>:</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>void</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>Store</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>const</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>char</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>Media</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>GetBaseMedia</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>zoneDefault</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>for</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>=</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>-&gt;</SPAN><SPAN class=S11>cursor</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>[</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>],</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>++)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>-&gt;</SPAN><SPAN class=S11>Persist</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>[</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>]);</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
+</SPAN><SPAN class=S10>};</SPAN>
+ <h3>
+ Submitting a lexer
+ </h3>
+
+ <p>Add a public feature request to the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=352439">Feature Request Tracker</a>.</p>
+ <p>Send all the modified and new files as full text (not patches) in an archive (.zip or .tgz).</p>
+ <p>Define all of the lexical states in a modified Scintilla.iface.</p>
+ <p>Ensure there are no warnings under the compiler you use. Warnings from other compilers
+ will be noted on the feature request.</p>
+ <p>sc.ch is an int: do not pass this around as a char.</p>
+ </body>
+</html>
diff --git a/scintilla/doc/SciRest.jpg b/scintilla/doc/SciRest.jpg
new file mode 100644
index 0000000..4b05223
--- /dev/null
+++ b/scintilla/doc/SciRest.jpg
Binary files differ
diff --git a/scintilla/doc/SciTEIco.png b/scintilla/doc/SciTEIco.png
new file mode 100644
index 0000000..d0cc869
--- /dev/null
+++ b/scintilla/doc/SciTEIco.png
Binary files differ
diff --git a/scintilla/doc/SciWord.jpg b/scintilla/doc/SciWord.jpg
new file mode 100644
index 0000000..60e70e8
--- /dev/null
+++ b/scintilla/doc/SciWord.jpg
Binary files differ
diff --git a/scintilla/doc/ScintillaDoc.html b/scintilla/doc/ScintillaDoc.html
new file mode 100644
index 0000000..cfde86f
--- /dev/null
+++ b/scintilla/doc/ScintillaDoc.html
@@ -0,0 +1,6247 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator"
+ content="HTML Tidy for Windows (vers 1st August 2002), see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+
+ <title>Scintilla Documentation</title>
+
+ <style type="text/css">
+<!--
+/*<![CDATA[*/
+ CODE { font-weight: bold; font-family: Consolas,Bitstream Vera Sans Mono,Courier New,monospace; }
+ A:visited { color: blue; }
+ A:hover { text-decoration: underline ! important; }
+ A.message { text-decoration: none; font-weight: bold; font-family: Consolas,Bitstream Vera Sans Mono,Courier New,monospace; }
+ A.toc { text-decoration: none; }
+ A.jump { text-decoration: none; }
+/*]]>*/
+-->
+ </style>
+ </head>
+
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0"
+ summary="Banner">
+ <tr>
+ <td><img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" /></td>
+
+ <td><a href="index.html"
+ style="color:white;text-decoration:none;font-size:200%">Scintilla</a></td>
+ </tr>
+ </table>
+
+ <h1>Scintilla Documentation</h1>
+
+ <p>Last edited 4/April/2010 NH</p>
+
+ <p>There is <a class="jump" href="Design.html">an overview of the internal design of
+ Scintilla</a>.<br />
+ <a class="jump" href="ScintillaUsage.html">Some notes on using Scintilla</a>.<br />
+ <a class="jump" href="Steps.html">How to use the Scintilla Edit Control on Windows</a>.<br />
+ <a class="jump" href="http://www.scintilla.org/dmapp.zip">A simple sample using Scintilla from
+ C++ on Windows</a>.<br />
+ <a class="jump" href="http://www.scintilla.org/SciTry.vb">A simple sample using Scintilla from
+ Visual Basic</a>.<br />
+ <a class="jump" href="http://www.scintilla.org/bait.zip">Bait is a tiny sample using Scintilla
+ on GTK+</a>.<br />
+ <a class="jump" href="Lexer.txt">A detailed description of how to write a lexer, including a
+ discussion of folding</a>.<br />
+ <a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-container_lexer.html">
+ How to implement a lexer in the container</a>.<br />
+ <a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-folding.html">
+ How to implement folding</a>.<br />
+ The <a class="jump" href="SciCoding.html">coding style</a> used in Scintilla and SciTE is
+ worth following if you want to contribute code to Scintilla but is not compulsory.</p>
+
+ <h2>Introduction</h2>
+
+ <p>The Windows version of Scintilla is a Windows Control. As such, its primary programming
+ interface is through Windows messages. Early versions of Scintilla emulated much of the API
+ defined by the standard Windows Edit and RichEdit controls but those APIs are now deprecated in
+ favour of Scintilla's own, more consistent API. In addition to messages performing the actions
+ of a normal Edit control, Scintilla allows control of syntax styling, folding, markers, autocompletion
+ and call tips.</p>
+
+ <p>The GTK+ version also uses messages in a similar way to the Windows version. This is
+ different to normal GTK+ practice but made it easier to implement rapidly.</p>
+
+ <p>Scintilla does not properly support right-to-left languages like Arabic and Hebrew.
+ While text in these languages may appear correct, it is not possible to interact with this text
+ as is normal with other editing components.</p>
+
+ <p>This documentation describes the individual messages and notifications used by Scintilla. It
+ does not describe how to link them together to form a useful editor. For now, the best way to
+ work out how to develop using Scintilla is to see how SciTE uses it. SciTE exercises most of
+ Scintilla's facilities.</p>
+
+ <p>In the descriptions that follow, the messages are described as function calls with zero, one
+ or two arguments. These two arguments are the standard <code>wParam</code> and
+ <code>lParam</code> familiar to Windows programmers. These parameters are integers that
+ are large enough to hold pointers, and the return value is also an integer large enough to contain a
+ pointer.
+ Although the commands only use the
+ arguments described, because all messages have two arguments whether Scintilla uses them or
+ not, it is strongly recommended that any unused arguments are set to 0. This allows future
+ enhancement of messages without the risk of breaking existing code. Common argument types
+ are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Common argument types">
+ <tbody valign="top">
+ <tr>
+ <th align="left">bool</th>
+
+ <td>Arguments expect the values 0 for <code>false</code> and 1 for
+ <code>true</code>.</td>
+ </tr>
+
+ <tr>
+ <th align="left">int</th>
+
+ <td>Arguments are 32-bit signed integers.</td>
+ </tr>
+
+ <tr>
+ <th align="left">const&nbsp;char&nbsp;*</th>
+
+ <td>Arguments point at text that is being passed to Scintilla but not modified. The text
+ may be zero terminated or another argument may specify the character count, the
+ description will make this clear.</td>
+ </tr>
+
+ <tr>
+ <th align="left">char *</th>
+
+ <td>Arguments point at text buffers that Scintilla will fill with text. In some cases,
+ another argument will tell Scintilla the buffer size. In others, you must make sure that
+ the buffer is big enough to hold the requested text. If a NULL pointer (0) is passed
+ then, for SCI_* calls, the length that should be allocated is returned.</td>
+ </tr>
+
+ <tr>
+ <th align="left" id="colour">colour</th>
+
+ <td>Colours are set using the RGB format (Red, Green, Blue). The intensity of each colour
+ is set in the range 0 to 255. If you have three such intensities, they are combined as:
+ red | (green &lt;&lt; 8) | (blue &lt;&lt; 16). If you set all intensities to 255, the
+ colour is white. If you set all intensities to 0, the colour is black. When you set a
+ colour, you are making a request. What you will get depends on the capabilities of the
+ system and the current screen mode.</td>
+ </tr>
+
+ <tr>
+ <th align="left" id="alpha">alpha</th>
+
+ <td>Translucency is set using an alpha value.
+ Alpha ranges from 0 (SC_ALPHA_TRANSPARENT) which is completely transparent to
+ 255 (SC_ALPHA_OPAQUE) which is opaque. The value 256 (SC_ALPHA_NOALPHA)
+ is opaque and uses code that is not alpha-aware and may be faster. Not all platforms support
+ translucency and only some Scintilla features implement translucency.
+ The default alpha value for most features is SC_ALPHA_NOALPHA.</td>
+ </tr>
+
+ <tr>
+ <th align="left">&lt;unused&gt;</th>
+
+ <td>This is an unused argument. Setting it to 0 will ensure compatibility with future
+ enhancements.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h2 id="MessageCategories">Contents</h2>
+
+ <table cellpadding="4" cellspacing="2" border="0" summary="Message categories">
+ <tbody>
+ <tr>
+ <td>o <a class="toc" href="#TextRetrievalAndModification">Text retrieval and
+ modification</a></td>
+
+ <td>o <a class="toc" href="#Searching">Searching and replacing</a></td>
+
+ <td>o <a class="toc" href="#Overtype">Overtype</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#CutCopyAndPaste">Cut, copy and paste</a></td>
+
+ <td>o <a class="toc" href="#ErrorHandling">Error handling</a></td>
+
+ <td>o <a class="toc" href="#UndoAndRedo">Undo and Redo</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#SelectionAndInformation">Selection and information</a></td>
+
+ <td>o <a class="toc" href="#MultipleSelectionAndVirtualSpace">Multiple Selection and Virtual Space</a></td>
+
+ <td>o <a class="toc" href="#ScrollingAndAutomaticScrolling">Scrolling and automatic
+ scrolling</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#WhiteSpace">White space</a></td>
+
+ <td>o <a class="toc" href="#Cursor">Cursor</a></td>
+
+ <td>o <a class="toc" href="#MouseCapture">Mouse capture</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#LineEndings">Line endings</a></td>
+
+ <td>o <a class="toc" href="#Styling">Styling</a></td>
+
+ <td>o <a class="toc" href="#StyleDefinition">Style definition</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#CaretAndSelectionStyles">Caret, selection, and hotspot styles</a></td>
+
+ <td>o <a class="toc" href="#Margins">Margins</a></td>
+
+ <td>o <a class="toc" href="#Annotations">Annotations</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#OtherSettings">Other settings</a></td>
+
+ <td>o <a class="toc" href="#BraceHighlighting">Brace highlighting</a></td>
+
+ <td>o <a class="toc" href="#TabsAndIndentationGuides">Tabs and Indentation
+ Guides</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#Markers">Markers</a></td>
+
+ <td>o <a class="toc" href="#Indicators">Indicators</a></td>
+
+ <td>o <a class="toc" href="#Autocompletion">Autocompletion</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#UserLists">User lists</a></td>
+
+ <td>o <a class="toc" href="#CallTips">Call tips</a></td>
+
+ <td>o <a class="toc" href="#KeyboardCommands">Keyboard commands</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#KeyBindings">Key bindings</a></td>
+
+ <td>o <a class="toc" href="#PopupEditMenu">Popup edit menu</a></td>
+
+ <td>o <a class="toc" href="#MacroRecording">Macro recording</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#Printing">Printing</a></td>
+
+ <td>o <a class="toc" href="#DirectAccess">Direct access</a></td>
+
+ <td>o <a class="toc" href="#MultipleViews">Multiple views</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#Folding">Folding</a></td>
+
+ <td>o <a class="toc" href="#LineWrapping">Line wrapping</a></td>
+
+ <td>o <a class="toc" href="#Zooming">Zooming</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#LongLines">Long lines</a></td>
+
+ <td>o <a class="toc" href="#Lexer">Lexer</a></td>
+
+ <td>o <a class="toc" href="#Notifications">Notifications</a></td>
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#GTK">GTK+</a></td>
+
+ <td>o <a class="toc" href="#DeprecatedMessages">Deprecated messages</a></td>
+
+ <td>o <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never
+ supported by Scintilla</a></td>
+
+ </tr>
+
+ <tr>
+ <td>o <a class="toc" href="#BuildingScintilla">Building Scintilla</a></td>
+
+ </tr>
+ </tbody>
+ </table>
+
+ <p>Messages with names of the form <code>SCI_SETxxxxx</code> often have a companion
+ <code>SCI_GETxxxxx</code>. To save tedious repetition, if the <code>SCI_GETxxxxx</code> message
+ returns the value set by the <code>SCI_SETxxxxx</code> message, the <code>SET</code> routine is
+ described and the <code>GET</code> routine is left to your imagination.</p>
+
+ <h2 id="TextRetrievalAndModification">Text retrieval and modification</h2>
+
+ <p>Each byte in a Scintilla document is followed by an associated byte of styling
+ information. The combination of a character byte and a style byte is called a cell. Style bytes
+ are interpreted an index into an array of styles.
+ Style bytes may be split into an index and a set of indicator bits
+ but this use is discouraged and indicators should now use
+ <a class="message" href ="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE</a>
+ and related calls.
+ The default split is with the index in the low 5 bits and 3 high bits as <a class="jump"
+ href="#Indicators">indicators</a>. This allows 32 fundamental styles, which is enough for most
+ languages, and three independent indicators so that, for example, syntax errors, deprecated
+ names and bad indentation could all be displayed at once. The number of bits used for styles
+ can be altered with <a class="message"
+ href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> up to a maximum of 8 bits.
+ The remaining bits can be used for indicators.</p>
+
+ <p>In this document, 'character' normally refers to a byte even when multi-byte characters are used.
+ Lengths measure the numbers of bytes, not the amount of characters in those bytes.</p>
+
+ <p>Positions within the Scintilla document refer to a character or the gap before that
+ character. The first character in a document is 0, the second 1 and so on. If a document
+ contains <code>nLen</code> characters, the last character is numbered <code>nLen</code>-1.
+ The caret exists between character positions and can be located from before the first character (0)
+ to after the last character (<code>nLen</code>).</p>
+
+ <p>There are places where the caret can not go where two character bytes make up one character.
+ This occurs when a DBCS character from a language like Japanese is included in the document or
+ when line ends are marked with the CP/M standard of a carriage return followed by a line feed.
+ The <code>INVALID_POSITION</code> constant (-1) represents an invalid position within the
+ document.</p>
+
+ <p>All lines of text in Scintilla are the same height, and this height is calculated from the
+ largest font in any current style. This restriction is for performance; if lines differed in
+ height then calculations involving positioning of text would require the text to be styled
+ first.</p>
+ <code><a class="message" href="#SCI_GETTEXT">SCI_GETTEXT(int length, char *text)</a><br />
+ <a class="message" href="#SCI_SETTEXT">SCI_SETTEXT(&lt;unused&gt;, const char *text)</a><br />
+ <a class="message" href="#SCI_SETSAVEPOINT">SCI_SETSAVEPOINT</a><br />
+ <a class="message" href="#SCI_GETLINE">SCI_GETLINE(int line, char *text)</a><br />
+ <a class="message" href="#SCI_REPLACESEL">SCI_REPLACESEL(&lt;unused&gt;, const char
+ *text)</a><br />
+ <a class="message" href="#SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</a><br />
+ <a class="message" href="#SCI_GETREADONLY">SCI_GETREADONLY</a><br />
+ <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, Sci_TextRange
+ *tr)</a><br />
+ <a class="message" href="#SCI_ALLOCATE">SCI_ALLOCATE(int bytes, &lt;unused&gt;)</a><br />
+ <a class="message" href="#SCI_ADDTEXT">SCI_ADDTEXT(int length, const char *s)</a><br />
+ <a class="message" href="#SCI_ADDSTYLEDTEXT">SCI_ADDSTYLEDTEXT(int length, cell *s)</a><br />
+ <a class="message" href="#SCI_APPENDTEXT">SCI_APPENDTEXT(int length, const char *s)</a><br />
+ <a class="message" href="#SCI_INSERTTEXT">SCI_INSERTTEXT(int pos, const char *text)</a><br />
+ <a class="message" href="#SCI_CLEARALL">SCI_CLEARALL</a><br />
+ <a class="message" href="#SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</a><br />
+ <a class="message" href="#SCI_GETCHARAT">SCI_GETCHARAT(int position)</a><br />
+ <a class="message" href="#SCI_GETSTYLEAT">SCI_GETSTYLEAT(int position)</a><br />
+ <a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(&lt;unused&gt;, Sci_TextRange
+ *tr)</a><br />
+ <a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS(int bits)</a><br />
+ <a class="message" href="#SCI_GETSTYLEBITS">SCI_GETSTYLEBITS</a><br />
+ <a class="message" href="#SCI_TARGETASUTF8">SCI_TARGETASUTF8(&lt;unused&gt;, char *s)</a><br />
+ <a class="message" href="#SCI_ENCODEDFROMUTF8">SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)</a><br />
+ <a class="message" href="#SCI_SETLENGTHFORENCODE">SCI_SETLENGTHFORENCODE(int bytes)</a><br />
+ </code>
+
+ <p><b id="SCI_GETTEXT">SCI_GETTEXT(int length, char *text)</b><br />
+ This returns <code>length</code>-1 characters of text from the start of the document plus one
+ terminating 0 character. To collect all the text in a document, use <code>SCI_GETLENGTH</code>
+ to get the number of characters in the document (<code>nLen</code>), allocate a character
+ buffer of length <code>nLen+1</code> bytes, then call <code>SCI_GETTEXT(nLen+1, char
+ *text)</code>. If the text argument is 0 then the length that should be allocated to store the
+ entire document is returned.
+ If you then save the text, you should use <code>SCI_SETSAVEPOINT</code> to mark
+ the text as unmodified.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
+ class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
+ href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
+ href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
+ href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a></code></p>
+
+ <p><b id="SCI_SETTEXT">SCI_SETTEXT(&lt;unused&gt;, const char *text)</b><br />
+ This replaces all the text in the document with the zero terminated text string you pass
+ in.</p>
+
+ <p><b id="SCI_SETSAVEPOINT">SCI_SETSAVEPOINT</b><br />
+ This message tells Scintilla that the current state of the document is unmodified. This is
+ usually done when the file is saved or loaded, hence the name "save point". As Scintilla
+ performs undo and redo operations, it notifies the container that it has entered or left the
+ save point with <code><a class="message"
+ href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a></code> and <code><a class="message"
+ href="#SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</a></code> <a class="jump"
+ href="#Notifications">notification messages</a>, allowing the container to know if the file
+ should be considered dirty or not.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</a>, <a
+ class="message" href="#SCI_GETMODIFY">SCI_GETMODIFY</a></code></p>
+
+ <p><b id="SCI_GETLINE">SCI_GETLINE(int line, char *text)</b><br />
+ This fills the buffer defined by text with the contents of the nominated line (lines start at
+ 0). The buffer is not terminated by a 0 character. It is up to you to make sure that the buffer
+ is long enough for the text, use <a class="message"
+ href="#SCI_LINELENGTH"><code>SCI_LINELENGTH(int line)</code></a>. The returned value is the
+ number of characters copied to the buffer. The returned text includes any end of line
+ characters. If you ask for a line number outside the range of lines in the document, 0
+ characters are copied. If the text argument is 0 then the length that should be allocated
+ to store the entire line is returned.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a
+ class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a class="message"
+ href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>, <a class="message"
+ href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
+ href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>
+
+ <p><b id="SCI_REPLACESEL">SCI_REPLACESEL(&lt;unused&gt;, const char *text)</b><br />
+ The currently selected text between the <a class="jump" href="#SelectionAndInformation">anchor
+ and the current position</a> is replaced by the 0 terminated text string. If the anchor and
+ current position are the same, the text is inserted at the caret position. The caret is
+ positioned after the inserted text and the caret is scrolled into view.</p>
+
+ <p><b id="SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</b><br />
+ <b id="SCI_GETREADONLY">SCI_GETREADONLY</b><br />
+ These messages set and get the read-only flag for the document. If you mark a document as read
+ only, attempts to modify the text cause the <a class="message"
+ href="#SCN_MODIFYATTEMPTRO"><code>SCN_MODIFYATTEMPTRO</code></a> notification.</p>
+
+ <p><b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, <a class="jump"
+ href="#Sci_TextRange">Sci_TextRange</a> *tr)</b><br />
+ This collects the text between the positions <code>cpMin</code> and <code>cpMax</code> and
+ copies it to <code>lpstrText</code> (see <code>struct Sci_TextRange</code> in
+ <code>Scintilla.h</code>). If <code>cpMax</code> is -1, text is returned to the end of the
+ document. The text is 0 terminated, so you must supply a buffer that is at least 1 character
+ longer than the number of characters you wish to read. The return value is the length of the
+ returned text not including the terminating 0.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
+ class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
+ href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
+ href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
+ href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>
+
+ <p><b id="SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(&lt;unused&gt;, <a class="jump"
+ href="#Sci_TextRange">Sci_TextRange</a> *tr)</b><br />
+ This collects styled text into a buffer using two bytes for each cell, with the character at
+ the lower address of each pair and the style byte at the upper address. Characters between the
+ positions <code>cpMin</code> and <code>cpMax</code> are copied to <code>lpstrText</code> (see
+ <code>struct Sci_TextRange</code> in <code>Scintilla.h</code>). Two 0 bytes are added to the end of
+ the text, so the buffer that <code>lpstrText</code> points at must be at least
+ <code>2*(cpMax-cpMin)+2</code> bytes long. No check is made for sensible values of
+ <code>cpMin</code> or <code>cpMax</code>. Positions outside the document return character codes
+ and style bytes of 0.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
+ class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
+ href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
+ href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>, <a class="message"
+ href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>
+
+ <p><b id="SCI_ALLOCATE">SCI_ALLOCATE(int bytes, &lt;unused&gt;)</b><br />
+ Allocate a document buffer large enough to store a given number of bytes.
+ The document will not be made smaller than its current contents.</p>
+
+ <p><b id="SCI_ADDTEXT">SCI_ADDTEXT(int length, const char *s)</b><br />
+ This inserts the first <code>length</code> characters from the string <code>s</code>
+ at the current position. This will include any 0's in the string that you might have expected
+ to stop the insert operation. The current position is set at the end of the inserted text,
+ but it is not scrolled into view.</p>
+
+ <p><b id="SCI_ADDSTYLEDTEXT">SCI_ADDSTYLEDTEXT(int length, cell *s)</b><br />
+ This behaves just like <code>SCI_ADDTEXT</code>, but inserts styled text.</p>
+
+ <p><b id="SCI_APPENDTEXT">SCI_APPENDTEXT(int length, const char *s)</b><br />
+ This adds the first <code>length</code> characters from the string <code>s</code> to the end
+ of the document. This will include any 0's in the string that you might have expected to stop
+ the operation. The current selection is not changed and the new text is not scrolled into
+ view.</p>
+
+ <p><b id="SCI_INSERTTEXT">SCI_INSERTTEXT(int pos, const char *text)</b><br />
+ This inserts the zero terminated <code>text</code> string at position <code>pos</code> or at
+ the current position if <code>pos</code> is -1. If the current position is after the insertion point
+ then it is moved along with its surrounding text but no scrolling is performed.</p>
+
+ <p><b id="SCI_CLEARALL">SCI_CLEARALL</b><br />
+ Unless the document is read-only, this deletes all the text.</p>
+
+ <p><b id="SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</b><br />
+ When wanting to completely restyle the document, for example after choosing a lexer, the
+ <code>SCI_CLEARDOCUMENTSTYLE</code> can be used to clear all styling information and reset the
+ folding state.</p>
+
+ <p><b id="SCI_GETCHARAT">SCI_GETCHARAT(int pos)</b><br />
+ This returns the character at <code>pos</code> in the document or 0 if <code>pos</code> is
+ negative or past the end of the document.</p>
+
+ <p><b id="SCI_GETSTYLEAT">SCI_GETSTYLEAT(int pos)</b><br />
+ This returns the style at <code>pos</code> in the document, or 0 if <code>pos</code> is
+ negative or past the end of the document.</p>
+
+ <p><b id="SCI_SETSTYLEBITS">SCI_SETSTYLEBITS(int bits)</b><br />
+ <b id="SCI_GETSTYLEBITS">SCI_GETSTYLEBITS</b><br />
+ This pair of routines sets and reads back the number of bits in each cell to use for styling,
+ to a maximum of 8 style bits. The remaining bits can be used as indicators. The standard
+ setting is <code>SCI_SETSTYLEBITS(5)</code>.
+ The number of styling bits needed by the current lexer can be found with
+ <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a>.</p>
+
+ <p><b id="Sci_TextRange">Sci_TextRange</b> and <b id="Sci_CharacterRange">Sci_CharacterRange</b><br />
+ These structures are defined to be exactly the same shape as the Win32 <code>TEXTRANGE</code>
+ and <code>CHARRANGE</code>, so that older code that treats Scintilla as a RichEdit will
+ work.</p>
+<pre>
+struct Sci_CharacterRange {
+ long cpMin;
+ long cpMax;
+};
+
+struct Sci_TextRange {
+ struct Sci_CharacterRange chrg;
+ char *lpstrText;
+};
+</pre>
+
+ <h3 id="EncodedAccess">GTK+-specific: Access to encoded text</h3>
+
+ <p><b id="SCI_TARGETASUTF8">SCI_TARGETASUTF8(&lt;unused&gt;, char *s)</b><br />
+ This method retrieves the value of the target encoded as UTF-8 which is the default
+ encoding of GTK+ so is useful for retrieving text for use in other parts of the user interface,
+ such as find and replace dialogs. The length of the encoded text in bytes is returned.
+ </p>
+
+ <p><b id="SCI_ENCODEDFROMUTF8">SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)</b><br />
+ <b id="SCI_SETLENGTHFORENCODE">SCI_SETLENGTHFORENCODE(int bytes)</b><br />
+ <code>SCI_ENCODEDFROMUTF8</code> converts a UTF-8 string into the document's
+ encoding which is useful for taking the results of a find dialog, for example, and receiving
+ a string of bytes that can be searched for in the document. Since the text can contain nul bytes,
+ the <code>SCI_SETLENGTHFORENCODE</code> method can be used to set the
+ length that will be converted. If set to -1, the length is determined by finding a nul byte.
+ The length of the converted string is returned.
+ </p>
+
+
+ <h2 id="Searching">Searching</h2>
+ <p>
+ There are methods to search for text and for regular expressions. The regular expression support
+ is limited and should only be used for simple cases and initial development. A different regular expression
+ library can be <a class="jump" href="#AlternativeRegEx">integrated into Scintilla</a>
+ or can be called from the container using direct access to the buffer contents through
+ <a class="message" href="#SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</a>.
+ </p>
+ <code><a class="message" href="#SCI_FINDTEXT">SCI_FINDTEXT(int flags, Sci_TextToFind
+ *ttf)</a><br />
+ <a class="message" href="#SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</a><br />
+ <a class="message" href="#SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char
+ *text)</a><br />
+ <a class="message" href="#SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char
+ *text)</a><br />
+ <a class="jump" href="#SearchAndReplaceUsingTheTarget">Search and replace using the
+ target</a><br />
+ </code>
+
+ <p><b id="searchFlags"><code>searchFlags</code></b><br />
+ Several of the search routines use flag options, which include a simple regular expression
+ search. Combine the flag options by adding them:</p>
+
+ <table border="0" summary="Search flags">
+ <tbody>
+ <tr>
+ <td><code>SCFIND_MATCHCASE</code></td>
+
+ <td>A match only occurs with text that matches the case of the search string.</td>
+ </tr>
+
+ <tr>
+ <td><code>SCFIND_WHOLEWORD</code></td>
+
+ <td>A match only occurs if the characters before and after are not word characters.</td>
+ </tr>
+
+ <tr>
+ <td><code>SCFIND_WORDSTART</code></td>
+
+ <td>A match only occurs if the character before is not a word character.</td>
+ </tr>
+
+ <tr>
+ <td><code>SCFIND_REGEXP</code></td>
+
+ <td>The search string should be interpreted as a regular expression.</td>
+ </tr>
+ <tr>
+ <td><code>SCFIND_POSIX</code></td>
+
+ <td>Treat regular expression in a more POSIX compatible manner
+ by interpreting bare ( and ) for tagged sections rather than \( and \).</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>If <code>SCFIND_REGEXP</code> is not included in the <code>searchFlags</code>, you can
+ search backwards to find the previous occurrence of a search string by setting the end of the
+ search range before the start. If <code>SCFIND_REGEXP</code> is included, searches are always
+ from a lower position to a higher position, even if the search range is backwards.</p>
+
+ <p>In a regular expression, special characters interpreted are:</p>
+
+ <table border="0" summary="Regular expression synopsis">
+ <tbody>
+ <tr>
+ <td><code>.</code></td>
+
+ <td>Matches any character</td>
+ </tr>
+
+ <tr>
+ <td><code>\(</code></td>
+
+ <td>This marks the start of a region for tagging a match.</td>
+ </tr>
+
+ <tr>
+ <td><code>\)</code></td>
+
+ <td>This marks the end of a tagged region.</td>
+ </tr>
+
+ <tr>
+ <td><code>\n</code></td>
+
+ <td>Where <code>n</code> is 1 through 9 refers to the first through ninth tagged region
+ when replacing. For example, if the search string was <code>Fred\([1-9]\)XXX</code> and
+ the replace string was <code>Sam\1YYY</code>, when applied to <code>Fred2XXX</code> this
+ would generate <code>Sam2YYY</code>.</td>
+ </tr>
+
+ <tr>
+ <td><code>\&lt;</code></td>
+
+ <td>This matches the start of a word using Scintilla's definitions of words.</td>
+ </tr>
+
+ <tr>
+ <td><code>\&gt;</code></td>
+
+ <td>This matches the end of a word using Scintilla's definition of words.</td>
+ </tr>
+
+ <tr>
+ <td><code>\x</code></td>
+
+ <td>This allows you to use a character x that would otherwise have a special meaning. For
+ example, \[ would be interpreted as [ and not as the start of a character set.</td>
+ </tr>
+
+ <tr>
+ <td><code>[...]</code></td>
+
+ <td>This indicates a set of characters, for example, [abc] means any of the characters a,
+ b or c. You can also use ranges, for example [a-z] for any lower case character.</td>
+ </tr>
+
+ <tr>
+ <td><code>[^...]</code></td>
+
+ <td>The complement of the characters in the set. For example, [^A-Za-z] means any
+ character except an alphabetic character.</td>
+ </tr>
+
+ <tr>
+ <td><code>^</code></td>
+
+ <td>This matches the start of a line (unless used inside a set, see above).</td>
+ </tr>
+
+ <tr>
+ <td><code>$</code></td>
+
+ <td>This matches the end of a line.</td>
+ </tr>
+
+ <tr>
+ <td><code>*</code></td>
+
+ <td>This matches 0 or more times. For example, <code>Sa*m</code> matches <code>Sm</code>,
+ <code>Sam</code>, <code>Saam</code>, <code>Saaam</code> and so on.</td>
+ </tr>
+
+ <tr>
+ <td><code>+</code></td>
+
+ <td>This matches 1 or more times. For example, <code>Sa+m</code> matches
+ <code>Sam</code>, <code>Saam</code>, <code>Saaam</code> and so on.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_FINDTEXT">SCI_FINDTEXT(int searchFlags, <a class="jump"
+ href="#Sci_TextToFind">Sci_TextToFind</a> *ttf)</b><br />
+ This message searches for text in the document. It does not use or move the current selection.
+ The <a class="jump" href="#searchFlags"><code>searchFlags</code></a> argument controls the
+ search type, which includes regular expression searches.</p>
+
+ <p>The <code>Sci_TextToFind</code> structure is defined in <code>Scintilla.h</code>; set
+ <code>chrg.cpMin</code> and <code>chrg.cpMax</code> with the range of positions in the document
+ to search. If <code>SCFIND_REGEXP</code> is not included in the flags, you can search backwards by
+ setting <code>chrg.cpMax</code> less than <code>chrg.cpMin</code>. If <code>SCFIND_REGEXP</code>
+ is included, the search is always forwards (even if <code>chrg.cpMax</code> is less than <code>chrg.cpMin</code>).
+ Set the <code>lpstrText</code> member of <code>Sci_TextToFind</code> to point at a zero terminated
+ text string holding the search pattern. If your language makes the use of <code>Sci_TextToFind</code>
+ difficult, you should consider using <code>SCI_SEARCHINTARGET</code> instead.</p>
+
+ <p>The return value is -1 if the search fails or the position of the start of the found text if
+ it succeeds. The <code>chrgText.cpMin</code> and <code>chrgText.cpMax</code> members of
+ <code>Sci_TextToFind</code> are filled in with the start and end positions of the found text.</p>
+
+ <p>See also: <code><a class="message"
+ href="#SCI_SEARCHINTARGET">SCI_SEARCHINTARGET</a></code></p>
+
+ <p><b id="Sci_TextToFind">Sci_TextToFind</b><br />
+ This structure is defined to have exactly the same shape as the Win32 structure
+ <code>FINDTEXTEX</code> for old code that treated Scintilla as a RichEdit control.</p>
+<pre>
+struct Sci_TextToFind {
+ struct <a class="jump" href="#Sci_CharacterRange">Sci_CharacterRange</a> chrg; // range to search
+ char *lpstrText; // the search pattern (zero terminated)
+ struct Sci_CharacterRange chrgText; // returned as position of matching text
+};
+</pre>
+
+ <p><b id="SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</b><br />
+ <b id="SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char *text)</b><br />
+ <b id="SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text)</b><br />
+ These messages provide relocatable search support. This allows multiple incremental
+ interactive searches to be macro recorded while still setting the selection to found text so
+ the find/select operation is self-contained. These three messages send <a class="message"
+ href="#SCN_MACRORECORD"><code>SCN_MACRORECORD</code></a> <a class="jump"
+ href="#Notifications">notifications</a> if macro recording is enabled.</p>
+
+ <p><code>SCI_SEARCHANCHOR</code> sets the search start point used by
+ <code>SCI_SEARCHNEXT</code> and <code>SCI_SEARCHPREV</code> to the start of the current
+ selection, that is, the end of the selection that is nearer to the start of the document. You
+ should always call this before calling either of <code>SCI_SEARCHNEXT</code> or
+ <code>SCI_SEARCHPREV</code>.</p>
+
+ <p><code>SCI_SEARCHNEXT</code> and <code>SCI_SEARCHPREV</code> search for the next and previous
+ occurrence of the zero terminated search string pointed at by text. The search is modified by
+ the <a class="jump" href="#searchFlags"><code>searchFlags</code></a>. If you request a regular
+ expression, <code>SCI_SEARCHPREV</code> finds the first occurrence of the search string in the
+ document, not the previous one before the anchor point.</p>
+
+ <p>The return value is -1 if nothing is found, otherwise the return value is the start position
+ of the matching text. The selection is updated to show the matched text, but is not scrolled
+ into view.</p>
+
+ <p>See also: <a class="message" href="#SCI_SEARCHINTARGET"><code>SCI_SEARCHINTARGET</code></a>,
+ <a class="message" href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a></p>
+
+ <h3 id="SearchAndReplaceUsingTheTarget">Search and replace using the target</h3>
+
+ <p>Using <a class="message" href="#SCI_REPLACESEL"><code>SCI_REPLACESEL</code></a>,
+ modifications cause scrolling and other visible changes, which may take some time and cause
+ unwanted display updates. If performing many changes, such as a replace all command, the target
+ can be used instead. First, set the target, ie. the range to be replaced. Then call
+ <code>SCI_REPLACETARGET</code> or <code>SCI_REPLACETARGETRE</code>.</p>
+
+ <p>Searching can be performed within the target range with <code>SCI_SEARCHINTARGET</code>,
+ which uses a counted string to allow searching for null characters. It returns the
+ position of the start of the matching text range or -1 for failure, in which case the target is not moved. The flags used by
+ <code>SCI_SEARCHINTARGET</code> such as <code>SCFIND_MATCHCASE</code>,
+ <code>SCFIND_WHOLEWORD</code>, <code>SCFIND_WORDSTART</code>, and <code>SCFIND_REGEXP</code>
+ can be set with <code>SCI_SETSEARCHFLAGS</code>. <code>SCI_SEARCHINTARGET</code> may be simpler
+ for some clients to use than <a class="message"
+ href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a>, as that requires using a pointer to a
+ structure.</p>
+ <code><a class="message" href="#SCI_SETTARGETSTART">SCI_SETTARGETSTART(int pos)</a><br />
+ <a class="message" href="#SCI_GETTARGETSTART">SCI_GETTARGETSTART</a><br />
+ <a class="message" href="#SCI_SETTARGETEND">SCI_SETTARGETEND(int pos)</a><br />
+ <a class="message" href="#SCI_GETTARGETEND">SCI_GETTARGETEND</a><br />
+ <a class="message" href="#SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</a><br />
+ <a class="message" href="#SCI_SETSEARCHFLAGS">SCI_SETSEARCHFLAGS(int searchFlags)</a><br />
+ <a class="message" href="#SCI_GETSEARCHFLAGS">SCI_GETSEARCHFLAGS</a><br />
+ <a class="message" href="#SCI_SEARCHINTARGET">SCI_SEARCHINTARGET(int length, const char
+ *text)</a><br />
+ <a class="message" href="#SCI_REPLACETARGET">SCI_REPLACETARGET(int length, const char
+ *text)</a><br />
+ <a class="message" href="#SCI_REPLACETARGETRE">SCI_REPLACETARGETRE(int length, const char
+ *text)</a><br />
+ <a class="message" href="#SCI_GETTAG">SCI_GETTAG(int tagNumber, char *tagValue)</a><br />
+ </code>
+
+ <p><b id="SCI_SETTARGETSTART">SCI_SETTARGETSTART(int pos)</b><br />
+ <b id="SCI_GETTARGETSTART">SCI_GETTARGETSTART</b><br />
+ <b id="SCI_SETTARGETEND">SCI_SETTARGETEND(int pos)</b><br />
+ <b id="SCI_GETTARGETEND">SCI_GETTARGETEND</b><br />
+ These functions set and return the start and end of the target. When searching in non-regular
+ expression mode, you can set start greater than end to find the last matching text in the
+ target rather than the first matching text. The target is also set by a successful
+ <code>SCI_SEARCHINTARGET</code>.</p>
+
+ <p><b id="SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</b><br />
+ Set the target start and end to the start and end positions of the selection.</p>
+
+ <p><b id="SCI_SETSEARCHFLAGS">SCI_SETSEARCHFLAGS(int searchFlags)</b><br />
+ <b id="SCI_GETSEARCHFLAGS">SCI_GETSEARCHFLAGS</b><br />
+ These get and set the <a class="jump" href="#searchFlags"><code>searchFlags</code></a> used by
+ <code>SCI_SEARCHINTARGET</code>. There are several option flags including a simple regular
+ expression search.</p>
+
+ <p><b id="SCI_SEARCHINTARGET">SCI_SEARCHINTARGET(int length, const char *text)</b><br />
+ This searches for the first occurrence of a text string in the target defined by
+ <code>SCI_SETTARGETSTART</code> and <code>SCI_SETTARGETEND</code>. The text string is not zero
+ terminated; the size is set by <code>length</code>. The search is modified by the search flags
+ set by <code>SCI_SETSEARCHFLAGS</code>. If the search succeeds, the target is set to the found
+ text and the return value is the position of the start of the matching text. If the search
+ fails, the result is -1.</p>
+
+ <p><b id="SCI_REPLACETARGET">SCI_REPLACETARGET(int length, const char *text)</b><br />
+ If <code>length</code> is -1, <code>text</code> is a zero terminated string, otherwise
+ <code>length</code> sets the number of character to replace the target with.
+ After replacement, the target range refers to the replacement text.
+ The return value
+ is the length of the replacement string.<br />
+ Note that the recommended way to delete text in the document is to set the target to the text to be removed,
+ and to perform a replace target with an empty string.</p>
+
+ <p><b id="SCI_REPLACETARGETRE">SCI_REPLACETARGETRE(int length, const char *text)</b><br />
+ This replaces the target using regular expressions. If <code>length</code> is -1,
+ <code>text</code> is a zero terminated string, otherwise <code>length</code> is the number of
+ characters to use. The replacement string is formed from the text string with any sequences of
+ <code>\1</code> through <code>\9</code> replaced by tagged matches from the most recent regular
+ expression search.
+ After replacement, the target range refers to the replacement text.
+ The return value is the length of the replacement string.</p>
+
+ <p><b id="SCI_GETTAG">SCI_GETTAG(int tagNumber, char *tagValue)</b><br />
+ Discover what text was matched by tagged expressions in a regular expression search.
+ This is useful if the application wants to interpret the replacement string itself.</p>
+
+ <p>See also: <a class="message" href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a></p>
+
+ <h2 id="Overtype">Overtype</h2>
+
+ <p><b id="SCI_SETOVERTYPE">SCI_SETOVERTYPE(bool overType)</b><br />
+ <b id="SCI_GETOVERTYPE">SCI_GETOVERTYPE</b><br />
+ When overtype is enabled, each typed character replaces the character to the right of the text
+ caret. When overtype is disabled, characters are inserted at the caret.
+ <code>SCI_GETOVERTYPE</code> returns <code>TRUE</code> (1) if overtyping is active, otherwise
+ <code>FALSE</code> (0) will be returned. Use <code>SCI_SETOVERTYPE</code> to set the overtype
+ mode.</p>
+
+ <h2 id="CutCopyAndPaste">Cut, copy and paste</h2>
+
+ <code><a class="message" href="#SCI_CUT">SCI_CUT</a><br />
+ <a class="message" href="#SCI_COPY">SCI_COPY</a><br />
+ <a class="message" href="#SCI_PASTE">SCI_PASTE</a><br />
+ <a class="message" href="#SCI_CLEAR">SCI_CLEAR</a><br />
+ <a class="message" href="#SCI_CANPASTE">SCI_CANPASTE</a><br />
+ <a class="message" href="#SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</a><br />
+ <a class="message" href="#SCI_COPYTEXT">SCI_COPYTEXT(int length,
+ const char *text)</a><br />
+ <a class="message" href="#SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</a><br />
+ <a class="message" href="#SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</a><br />
+ <a class="message" href="#SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS</a><br />
+ </code>
+
+ <p><b id="SCI_CUT">SCI_CUT</b><br />
+ <b id="SCI_COPY">SCI_COPY</b><br />
+ <b id="SCI_PASTE">SCI_PASTE</b><br />
+ <b id="SCI_CLEAR">SCI_CLEAR</b><br />
+ <b id="SCI_CANPASTE">SCI_CANPASTE</b><br />
+ <b id="SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</b><br />
+ These commands perform the standard tasks of cutting and copying data to the clipboard,
+ pasting from the clipboard into the document, and clearing the document.
+ <code>SCI_CANPASTE</code> returns non-zero if the document isn't read-only and if the selection
+ doesn't contain protected text. If you need a "can copy" or "can cut", use
+ <code>SCI_GETSELECTIONSTART()-SCI_GETSELECTIONEND()</code>, which will be non-zero if you can
+ copy or cut to the clipboard.</p>
+
+ <p>GTK+ does not really support <code>SCI_CANPASTE</code> and always returns <code>TRUE</code>
+ unless the document is read-only.</p>
+
+ <p>On X, the clipboard is asynchronous and may require several messages between
+ the destination and source applications. Data from SCI_PASTE will not arrive in the
+ document immediately.</p>
+
+ <p><code>SCI_COPYALLOWLINE</code> works the same as SCI_COPY except that if the
+ selection is empty then the current line is copied. On Windows, an extra "MSDEVLineSelect" marker
+ is added to the clipboard which is then used in <code>SCI_PASTE</code> to paste
+ the whole line before the current line.</p>
+
+ <b id="SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</b><br />
+ <b id="SCI_COPYTEXT">SCI_COPYTEXT(int length, const char *text)</b><br />
+ <p><code>SCI_COPYRANGE</code> copies a range of text from the document to
+ the system clipboard and <code>SCI_COPYTEXT</code> copies a supplied piece of
+ text to the system clipboard.</p>
+
+ <p><b id="SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</b><br />
+ <b id="SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS</b><br />
+ If this property is set then when text is pasted any line ends are converted to match the document's
+ end of line mode as set with
+ <a class="message" href="#SCI_SETEOLMODE">SCI_SETEOLMODE</a>.
+ Currently only changeable on Windows. On GTK+ pasted text is always converted.</p>
+
+ <h2 id="ErrorHandling">Error handling</h2>
+
+ <p><b id="SCI_SETSTATUS">SCI_SETSTATUS(int status)</b><br />
+ <b id="SCI_GETSTATUS">SCI_GETSTATUS</b><br />
+ If an error occurs, Scintilla may set an internal error number that can be retrieved with
+ <code>SCI_GETSTATUS</code>.
+ To clear the error status call <code>SCI_SETSTATUS(0)</code>.
+ The currently defined statuses are:
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Status values">
+ <tbody valign="top">
+ <tr>
+ <th align="left">SC_STATUS_OK</th>
+ <td>0</td>
+ <td>No failures</td>
+ </tr>
+
+ <tr>
+ <th align="left">SC_STATUS_FAILURE</th>
+ <td>1</td>
+ <td>Generic failure</td>
+ </tr>
+
+ <tr>
+ <th align="left">SC_STATUS_BADALLOC</th>
+ <td>2</td>
+ <td>Memory is exhausted</td>
+ </tr>
+
+ </tbody>
+ </table>
+
+ </p>
+
+ <h2 id="UndoAndRedo">Undo and Redo</h2>
+
+ <p>Scintilla has multiple level undo and redo. It will continue to collect undoable actions
+ until memory runs out. Scintilla saves actions that change the document. Scintilla does not
+ save caret and selection movements, view scrolling and the like. Sequences of typing or
+ deleting are compressed into single transactions to make it easier to undo and redo at a sensible
+ level of detail. Sequences of actions can be combined into transactions that are undone as a unit.
+ These sequences occur between <code>SCI_BEGINUNDOACTION</code> and
+ <code>SCI_ENDUNDOACTION</code> messages. These transactions can be nested and only the top-level
+ sequences are undone as units.</p>
+ <code><a class="message" href="#SCI_UNDO">SCI_UNDO</a><br />
+ <a class="message" href="#SCI_CANUNDO">SCI_CANUNDO</a><br />
+ <a class="message" href="#SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</a><br />
+ <a class="message" href="#SCI_REDO">SCI_REDO</a><br />
+ <a class="message" href="#SCI_CANREDO">SCI_CANREDO</a><br />
+ <a class="message" href="#SCI_SETUNDOCOLLECTION">SCI_SETUNDOCOLLECTION(bool
+ collectUndo)</a><br />
+ <a class="message" href="#SCI_GETUNDOCOLLECTION">SCI_GETUNDOCOLLECTION</a><br />
+ <a class="message" href="#SCI_BEGINUNDOACTION">SCI_BEGINUNDOACTION</a><br />
+ <a class="message" href="#SCI_ENDUNDOACTION">SCI_ENDUNDOACTION</a><br />
+ <a class="message" href="#SCI_ADDUNDOACTION">SCI_ADDUNDOACTION(int token, int flags)</a><br />
+ </code>
+
+ <p><b id="SCI_UNDO">SCI_UNDO</b><br />
+ <b id="SCI_CANUNDO">SCI_CANUNDO</b><br />
+ <code>SCI_UNDO</code> undoes one action, or if the undo buffer has reached a
+ <code>SCI_ENDUNDOACTION</code> point, all the actions back to the corresponding
+ <code>SCI_BEGINUNDOACTION</code>.</p>
+
+ <p><code>SCI_CANUNDO</code> returns 0 if there is nothing to undo, and 1 if there is. You would
+ typically use the result of this message to enable/disable the Edit menu Undo command.</p>
+
+ <p><b id="SCI_REDO">SCI_REDO</b><br />
+ <b id="SCI_CANREDO">SCI_CANREDO</b><br />
+ <code>SCI_REDO</code> undoes the effect of the last <code>SCI_UNDO</code> operation.</p>
+
+ <p><code>SCI_CANREDO</code> returns 0 if there is no action to redo and 1 if there are undo
+ actions to redo. You could typically use the result of this message to enable/disable the Edit
+ menu Redo command.</p>
+
+ <p><b id="SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</b><br />
+ This command tells Scintilla to forget any saved undo or redo history. It also sets the save
+ point to the start of the undo buffer, so the document will appear to be unmodified. This does
+ not cause the <code><a class="message"
+ href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a></code> notification to be sent to the
+ container.</p>
+
+ <p>See also: <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a></p>
+
+ <p><b id="SCI_SETUNDOCOLLECTION">SCI_SETUNDOCOLLECTION(bool collectUndo)</b><br />
+ <b id="SCI_GETUNDOCOLLECTION">SCI_GETUNDOCOLLECTION</b><br />
+ You can control whether Scintilla collects undo information with
+ <code>SCI_SETUNDOCOLLECTION</code>. Pass in <code>true</code> (1) to collect information and
+ <code>false</code> (0) to stop collecting. If you stop collection, you should also use
+ <code>SCI_EMPTYUNDOBUFFER</code> to avoid the undo buffer being unsynchronized with the data in
+ the buffer.</p>
+
+ <p>You might wish to turn off saving undo information if you use the Scintilla to store text
+ generated by a program (a Log view) or in a display window where text is often deleted and
+ regenerated.</p>
+
+ <p><b id="SCI_BEGINUNDOACTION">SCI_BEGINUNDOACTION</b><br />
+ <b id="SCI_ENDUNDOACTION">SCI_ENDUNDOACTION</b><br />
+ Send these two messages to Scintilla to mark the beginning and end of a set of operations that
+ you want to undo all as one operation but that you have to generate as several operations.
+ Alternatively, you can use these to mark a set of operations that you do not want to have
+ combined with the preceding or following operations if they are undone.</p>
+
+ <p><b id="SCI_ADDUNDOACTION">SCI_ADDUNDOACTION(int token, int flags)</b><br />
+ The container can add its own actions into the undo stack by calling
+ <code>SCI_ADDUNDOACTION</code> and an <code>SCN_MODIFIED</code>
+ notification will be sent to the container with the
+ <a class="message" href="#SC_MOD_CONTAINER"><code>SC_MOD_CONTAINER</code></a>
+ flag when it is time to undo (<code>SC_PERFORMED_UNDO</code>) or
+ redo (<code>SC_PERFORMED_REDO</code>) the action. The token argument supplied is
+ returned in the <code>token</code> field of the notification.</p>
+ <p>For example, if the container wanted to allow undo and redo of a 'toggle bookmark' command then
+ it could call <code>SCI_ADDUNDOACTION(line, 0)</code> each time the command is performed.
+ Then when it receives a notification to undo or redo it toggles a bookmark on the line given by
+ the token field. If there are different types of commands or parameters that need to be stored into the undo
+ stack then the container should maintain a stack of its own for the document and use the current
+ position in that stack as the argument to <code>SCI_ADDUNDOACTION(line)</code>.
+ <code>SCI_ADDUNDOACTION</code> commands are not combined together
+ into a single undo transaction unless grouped with <code>SCI_BEGINUNDOACTION</code>
+ and <code>SCI_ENDUNDOACTION</code>.</p>
+
+ <p>The flags argument can be <code>UNDO_MAY_COALESCE</code> (1) if the container action may be
+ coalesced along with any insertion and deletion actions into a single compound action, otherwise 0.
+ Coalescing treats coalescible container actions as transparent so will still only group together insertions that
+ look like typing or deletions that look like multiple uses of the Backspace or Delete keys.
+ </p>
+ <h2 id="SelectionAndInformation">Selection and information</h2>
+
+ <p>Scintilla maintains a selection that stretches between two points, the anchor and the
+ current position. If the anchor and the current position are the same, there is no selected
+ text. Positions in the document range from 0 (before the first character), to the document size
+ (after the last character). If you use messages, there is nothing to stop you setting a
+ position that is in the middle of a CRLF pair, or in the middle of a 2 byte character. However,
+ keyboard commands will not move the caret into such positions.</p>
+ <code><a class="message" href="#SCI_GETTEXTLENGTH">SCI_GETTEXTLENGTH</a><br />
+ <a class="message" href="#SCI_GETLENGTH">SCI_GETLENGTH</a><br />
+ <a class="message" href="#SCI_GETLINECOUNT">SCI_GETLINECOUNT</a><br />
+ <a class="message" href="#SCI_SETFIRSTVISIBLELINE">SCI_SETFIRSTVISIBLELINE(int lineDisplay)</a><br />
+ <a class="message" href="#SCI_GETFIRSTVISIBLELINE">SCI_GETFIRSTVISIBLELINE</a><br />
+ <a class="message" href="#SCI_LINESONSCREEN">SCI_LINESONSCREEN</a><br />
+ <a class="message" href="#SCI_GETMODIFY">SCI_GETMODIFY</a><br />
+ <a class="message" href="#SCI_SETSEL">SCI_SETSEL(int anchorPos, int currentPos)</a><br />
+ <a class="message" href="#SCI_GOTOPOS">SCI_GOTOPOS(int position)</a><br />
+ <a class="message" href="#SCI_GOTOLINE">SCI_GOTOLINE(int line)</a><br />
+ <a class="message" href="#SCI_SETCURRENTPOS">SCI_SETCURRENTPOS(int position)</a><br />
+ <a class="message" href="#SCI_GETCURRENTPOS">SCI_GETCURRENTPOS</a><br />
+ <a class="message" href="#SCI_SETANCHOR">SCI_SETANCHOR(int position)</a><br />
+ <a class="message" href="#SCI_GETANCHOR">SCI_GETANCHOR</a><br />
+ <a class="message" href="#SCI_SETSELECTIONSTART">SCI_SETSELECTIONSTART(int position)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONSTART">SCI_GETSELECTIONSTART</a><br />
+ <a class="message" href="#SCI_SETSELECTIONEND">SCI_SETSELECTIONEND(int position)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONEND">SCI_GETSELECTIONEND</a><br />
+ <a class="message" href="#SCI_SELECTALL">SCI_SELECTALL</a><br />
+ <a class="message" href="#SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION(int position)</a><br />
+ <a class="message" href="#SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE(int line)</a><br />
+ <a class="message" href="#SCI_GETLINEENDPOSITION">SCI_GETLINEENDPOSITION(int line)</a><br />
+ <a class="message" href="#SCI_LINELENGTH">SCI_LINELENGTH(int line)</a><br />
+ <a class="message" href="#SCI_GETCOLUMN">SCI_GETCOLUMN(int position)</a><br />
+ <a class="message" href="#SCI_FINDCOLUMN">SCI_FINDCOLUMN(int line, int column)</a><br />
+ <a class="message" href="#SCI_POSITIONFROMPOINT">SCI_POSITIONFROMPOINT(int x, int y)</a><br />
+ <a class="message" href="#SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE(int x, int
+ y)</a><br />
+ <a class="message" href="#SCI_CHARPOSITIONFROMPOINT">SCI_CHARPOSITIONFROMPOINT(int x, int y)</a><br />
+ <a class="message" href="#SCI_CHARPOSITIONFROMPOINTCLOSE">SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int
+ y)</a><br />
+ <a class="message" href="#SCI_POINTXFROMPOSITION">SCI_POINTXFROMPOSITION(&lt;unused&gt;, int
+ position)</a><br />
+ <a class="message" href="#SCI_POINTYFROMPOSITION">SCI_POINTYFROMPOSITION(&lt;unused&gt;, int
+ position)</a><br />
+ <a class="message" href="#SCI_HIDESELECTION">SCI_HIDESELECTION(bool hide)</a><br />
+ <a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT(&lt;unused&gt;, char *text)</a><br />
+ <a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE(int textLen, char *text)</a><br />
+ <a class="message" href="#SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE</a><br />
+ <a class="message" href="#SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int mode)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE</a><br />
+ <a class="message" href="#SCI_GETLINESELSTARTPOSITION">SCI_GETLINESELSTARTPOSITION(int line)</a><br />
+ <a class="message" href="#SCI_GETLINESELENDPOSITION">SCI_GETLINESELENDPOSITION(int line)</a><br />
+ <a class="message" href="#SCI_MOVECARETINSIDEVIEW">SCI_MOVECARETINSIDEVIEW</a><br />
+ <a class="message" href="#SCI_WORDENDPOSITION">SCI_WORDENDPOSITION(int position, bool
+ onlyWordCharacters)</a><br />
+ <a class="message" href="#SCI_WORDSTARTPOSITION">SCI_WORDSTARTPOSITION(int position, bool
+ onlyWordCharacters)</a><br />
+ <a class="message" href="#SCI_POSITIONBEFORE">SCI_POSITIONBEFORE(int position)</a><br />
+ <a class="message" href="#SCI_POSITIONAFTER">SCI_POSITIONAFTER(int position)</a><br />
+ <a class="message" href="#SCI_TEXTWIDTH">SCI_TEXTWIDTH(int styleNumber, const char *text)</a><br />
+ <a class="message" href="#SCI_TEXTHEIGHT">SCI_TEXTHEIGHT(int line)</a><br />
+ <a class="message" href="#SCI_CHOOSECARETX">SCI_CHOOSECARETX</a><br />
+ </code>
+
+ <p><b id="SCI_GETTEXTLENGTH">SCI_GETTEXTLENGTH</b><br />
+ <b id="SCI_GETLENGTH">SCI_GETLENGTH</b><br />
+ Both these messages return the length of the document in bytes.</p>
+
+ <p><b id="SCI_GETLINECOUNT">SCI_GETLINECOUNT</b><br />
+ This returns the number of lines in the document. An empty document contains 1 line. A
+ document holding only an end of line sequence has 2 lines.</p>
+
+ <p><b id="SCI_SETFIRSTVISIBLELINE">SCI_SETFIRSTVISIBLELINE(int lineDisplay)</b><br />
+ <b id="SCI_GETFIRSTVISIBLELINE">SCI_GETFIRSTVISIBLELINE</b><br />
+ These messages retrieve and set the line number of the first visible line in the Scintilla view. The first line
+ in the document is numbered 0. The value is a visible line rather than a document line.</p>
+
+ <p><b id="SCI_LINESONSCREEN">SCI_LINESONSCREEN</b><br />
+ This returns the number of complete lines visible on the screen. With a constant line height,
+ this is the vertical space available divided by the line separation. Unless you arrange to size
+ your window to an integral number of lines, there may be a partial line visible at the bottom
+ of the view.</p>
+
+ <p><b id="SCI_GETMODIFY">SCI_GETMODIFY</b><br />
+ This returns non-zero if the document is modified and 0 if it is unmodified. The modified
+ status of a document is determined by the undo position relative to the save point. The save
+ point is set by <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a>,
+ usually when you have saved data to a file.</p>
+
+ <p>If you need to be notified when the document becomes modified, Scintilla notifies the
+ container that it has entered or left the save point with the <a class="message"
+ href="#SCN_SAVEPOINTREACHED"><code>SCN_SAVEPOINTREACHED</code></a> and <a class="message"
+ href="#SCN_SAVEPOINTLEFT"><code>SCN_SAVEPOINTLEFT</code></a> <a class="jump"
+ href="#Notifications">notification messages</a>.</p>
+
+ <p><b id="SCI_SETSEL">SCI_SETSEL(int anchorPos, int currentPos)</b><br />
+ This message sets both the anchor and the current position. If <code>currentPos</code> is
+ negative, it means the end of the document. If <code>anchorPos</code> is negative, it means
+ remove any selection (i.e. set the anchor to the same position as <code>currentPos</code>). The
+ caret is scrolled into view after this operation.</p>
+
+ <p><b id="SCI_GOTOPOS">SCI_GOTOPOS(int pos)</b><br />
+ This removes any selection, sets the caret at <code>pos</code> and scrolls the view to make
+ the caret visible, if necessary. It is equivalent to
+ <code>SCI_SETSEL(pos, pos)</code>. The anchor position is set the same as the current
+ position.</p>
+
+ <p><b id="SCI_GOTOLINE">SCI_GOTOLINE(int line)</b><br />
+ This removes any selection and sets the caret at the start of line number <code>line</code>
+ and scrolls the view (if needed) to make it visible. The anchor position is set the same as the
+ current position. If <code>line</code> is outside the lines in the document (first line is 0),
+ the line set is the first or last.</p>
+
+ <p><b id="SCI_SETCURRENTPOS">SCI_SETCURRENTPOS(int pos)</b><br />
+ This sets the current position and creates a selection between the anchor and the current
+ position. The caret is not scrolled into view.</p>
+
+ <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>
+
+ <p><b id="SCI_GETCURRENTPOS">SCI_GETCURRENTPOS</b><br />
+ This returns the current position.</p>
+
+ <p><b id="SCI_SETANCHOR">SCI_SETANCHOR(int pos)</b><br />
+ This sets the anchor position and creates a selection between the anchor position and the
+ current position. The caret is not scrolled into view.</p>
+
+ <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>
+
+ <p><b id="SCI_GETANCHOR">SCI_GETANCHOR</b><br />
+ This returns the current anchor position.</p>
+
+ <p><b id="SCI_SETSELECTIONSTART">SCI_SETSELECTIONSTART(int pos)</b><br />
+ <b id="SCI_SETSELECTIONEND">SCI_SETSELECTIONEND(int pos)</b><br />
+ These set the selection based on the assumption that the anchor position is less than the
+ current position. They do not make the caret visible. The table shows the positions of the
+ anchor and the current position after using these messages.</p>
+
+ <table cellpadding="3" cellspacing="0" border="1" summary="SetSelection caret positioning">
+ <thead align="center">
+ <tr>
+ <th>
+ </th>
+
+ <th>anchor</th>
+
+ <th>current</th>
+ </tr>
+ </thead>
+
+ <tbody align="center">
+ <tr>
+ <th><code>SCI_SETSELECTIONSTART</code></th>
+
+ <td><code>pos</code></td>
+
+ <td><code>Max(pos, current)</code></td>
+ </tr>
+
+ <tr>
+ <th><code>SCI_SETSELECTIONEND</code></th>
+
+ <td><code>Min(anchor, pos)</code></td>
+
+ <td><code>pos</code></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>
+
+ <p><b id="SCI_GETSELECTIONSTART">SCI_GETSELECTIONSTART</b><br />
+ <b id="SCI_GETSELECTIONEND">SCI_GETSELECTIONEND</b><br />
+ These return the start and end of the selection without regard to which end is the current
+ position and which is the anchor. <code>SCI_GETSELECTIONSTART</code> returns the smaller of the
+ current position or the anchor position. <code>SCI_GETSELECTIONEND</code> returns the larger of
+ the two values.</p>
+
+ <p><b id="SCI_SELECTALL">SCI_SELECTALL</b><br />
+ This selects all the text in the document. The current position is not scrolled into view.</p>
+
+ <p><b id="SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION(int pos)</b><br />
+ This message returns the line that contains the position <code>pos</code> in the document. The
+ return value is 0 if <code>pos</code> &lt;= 0. The return value is the last line if
+ <code>pos</code> is beyond the end of the document.</p>
+
+ <p><b id="SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE(int line)</b><br />
+ This returns the document position that corresponds with the start of the line. If
+ <code>line</code> is negative, the position of the line holding the start of the selection is
+ returned. If <code>line</code> is greater than the lines in the document, the return value is
+ -1. If <code>line</code> is equal to the number of lines in the document (i.e. 1 line past the
+ last line), the return value is the end of the document.</p>
+
+ <p><b id="SCI_GETLINEENDPOSITION">SCI_GETLINEENDPOSITION(int line)</b><br />
+ This returns the position at the end of the line, before any line end characters. If <code>line</code>
+ is the last line in the document (which does not have any end of line characters), the result is the size of the
+ document. If <code>line</code> is negative or <code>line</code> &gt;= <a class="message"
+ href="#SCI_GETLINECOUNT"><code>SCI_GETLINECOUNT()</code></a>, the result is undefined.</p>
+
+ <p><b id="SCI_LINELENGTH">SCI_LINELENGTH(int line)</b><br />
+ This returns the length of the line, including any line end characters. If <code>line</code>
+ is negative or beyond the last line in the document, the result is 0. If you want the length of
+ the line not including any end of line characters, use <a class="message"
+ href="#SCI_GETLINEENDPOSITION"><code>SCI_GETLINEENDPOSITION(line)</code></a> - <a class="message"
+ href="#SCI_POSITIONFROMLINE"><code>SCI_POSITIONFROMLINE(line)</code></a>.</p>
+ <b id="SCI_GETSELTEXT">SCI_GETSELTEXT(&lt;unused&gt;, char *text)</b><br />
+ This copies the currently selected text and a terminating 0 byte to the <code>text</code>
+ buffer. The buffer size should be determined by calling with a NULL pointer for the <code>text</code> argument
+ <code>SCI_GETSELTEXT(0,0)</code>.
+ This allows for rectangular and discontiguous selections as well as simple selections.
+ See <a class="toc" href="#MultipleSelectionAndVirtualSpace">Multiple Selection</a> for information on
+ how multiple and rectangular selections and virtual space are copied.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>,
+ <a class="message" href="#SCI_GETLINE">SCI_GETLINE</a>,
+ <a class="message" href="#SCI_GETTEXT">SCI_GETTEXT</a>,
+ <a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>,
+ <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>
+ </code></p>
+
+ <p><b id="SCI_GETCURLINE">SCI_GETCURLINE(int textLen, char *text)</b><br />
+ This retrieves the text of the line containing the caret and returns the position within the
+ line of the caret. Pass in <code>char* text</code> pointing at a buffer large enough to hold
+ the text you wish to retrieve and a terminating 0 character.
+ Set <code>textLen</code> to the
+ length of the buffer which must be at least 1 to hold the terminating 0 character.
+ If the text argument is 0 then the length that should be allocated
+ to store the entire current line is returned.</p>
+
+ <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
+ class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
+ href="#SCI_GETTEXT">SCI_GETTEXT</a>, <a class="message"
+ href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
+ href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a></code></p>
+
+ <p><b id="SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE</b><br />
+ This returns 1 if the current selection is in rectangle mode, 0 if not.</p>
+
+ <p><b id="SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int mode)</b><br />
+ <b id="SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE</b><br />
+ The two functions set and get the selection mode, which can be
+ stream (<code>SC_SEL_STREAM</code>=0) or
+ rectangular (<code>SC_SEL_RECTANGLE</code>=1) or
+ by lines (<code>SC_SEL_LINES</code>=2)
+ or thin rectangular (<code>SC_SEL_THIN</code>=3).
+ When set in these modes, regular caret moves will extend or reduce the selection,
+ until the mode is cancelled by a call with same value or with <code>SCI_CANCEL</code>.
+ The get function returns the current mode even if the selection was made by mouse
+ or with regular extended moves.
+ <code>SC_SEL_THIN</code> is the mode after a rectangular selection has been typed into and ensures
+ that no characters are selected.</p>
+
+ <p><b id="SCI_GETLINESELSTARTPOSITION">SCI_GETLINESELSTARTPOSITION(int line)</b><br />
+ <b id="SCI_GETLINESELENDPOSITION">SCI_GETLINESELENDPOSITION(int line)</b><br />
+ Retrieve the position of the start and end of the selection at the given line with
+ INVALID_POSITION returned if no selection on this line.</p>
+
+ <p><b id="SCI_MOVECARETINSIDEVIEW">SCI_MOVECARETINSIDEVIEW</b><br />
+ If the caret is off the top or bottom of the view, it is moved to the nearest line that is
+ visible to its current position. Any selection is lost.</p>
+
+ <p><b id="SCI_WORDENDPOSITION">SCI_WORDENDPOSITION(int position, bool
+ onlyWordCharacters)</b><br />
+ <b id="SCI_WORDSTARTPOSITION">SCI_WORDSTARTPOSITION(int position, bool
+ onlyWordCharacters)</b><br />
+ These messages return the start and end of words using the same definition of words as used
+ internally within Scintilla. You can set your own list of characters that count as words with
+ <a class="message" href="#SCI_SETWORDCHARS"><code>SCI_SETWORDCHARS</code></a>. The position
+ sets the start or the search, which is forwards when searching for the end and backwards when
+ searching for the start.</p>
+
+ <p>Set <code>onlyWordCharacters</code> to <code>true</code> (1) to stop searching at the first
+ non-word character in the search direction. If <code>onlyWordCharacters</code> is
+ <code>false</code> (0), the first character in the search direction sets the type of the search
+ as word or non-word and the search stops at the first non-matching character. Searches are also
+ terminated by the start or end of the document.</p>
+
+ <p>If "w" represents word characters and "." represents non-word characters and "|" represents
+ the position and <code>true</code> or <code>false</code> is the state of
+ <code>onlyWordCharacters</code>:</p>
+
+ <table cellpadding="3" cellspacing="0" border="1" summary="Word start and end positions">
+ <thead align="center">
+ <tr>
+ <th>Initial state</th>
+
+ <th>end, true</th>
+
+ <th>end, false</th>
+
+ <th>start, true</th>
+
+ <th>start, false</th>
+ </tr>
+ </thead>
+
+ <tbody align="center">
+ <tr>
+ <td>..ww..|..ww..</td>
+
+ <td>..ww..|..ww..</td>
+
+ <td>..ww....|ww..</td>
+
+ <td>..ww..|..ww..</td>
+
+ <td>..ww|....ww..</td>
+ </tr>
+
+ <tr>
+ <td>....ww|ww....</td>
+
+ <td>....wwww|....</td>
+
+ <td>....wwww|....</td>
+
+ <td>....|wwww....</td>
+
+ <td>....|wwww....</td>
+ </tr>
+
+ <tr>
+ <td>..ww|....ww..</td>
+
+ <td>..ww|....ww..</td>
+
+ <td>..ww....|ww..</td>
+
+ <td>..|ww....ww..</td>
+
+ <td>..|ww....ww..</td>
+ </tr>
+
+ <tr>
+ <td>..ww....|ww..</td>
+
+ <td>..ww....ww|..</td>
+
+ <td>..ww....ww|..</td>
+
+ <td>..ww....|ww..</td>
+
+ <td>..ww|....ww..</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_POSITIONBEFORE">SCI_POSITIONBEFORE(int position)</b><br />
+ <b id="SCI_POSITIONAFTER">SCI_POSITIONAFTER(int position)</b><br />
+ These messages return the position before and after another position
+ in the document taking into account the current code page. The minimum
+ position returned is 0 and the maximum is the last position in the document.
+ If called with a position within a multi byte character will return the position
+ of the start/end of that character.</p>
+
+ <p><b id="SCI_TEXTWIDTH">SCI_TEXTWIDTH(int styleNumber, const char *text)</b><br />
+ This returns the pixel width of a string drawn in the given <code>styleNumber</code> which can
+ be used, for example, to decide how wide to make the line number margin in order to display a
+ given number of numerals.</p>
+
+ <p><b id="SCI_TEXTHEIGHT">SCI_TEXTHEIGHT(int line)</b><br />
+ This returns the height in pixels of a particular line. Currently all lines are the same
+ height.</p>
+
+ <p><b id="SCI_GETCOLUMN">SCI_GETCOLUMN(int pos)</b><br />
+ This message returns the column number of a position <code>pos</code> within the document
+ taking the width of tabs into account. This returns the column number of the last tab on the
+ line before <code>pos</code>, plus the number of characters between the last tab and
+ <code>pos</code>. If there are no tab characters on the line, the return value is the number of
+ characters up to the position on the line. In both cases, double byte characters count as a
+ single character. This is probably only useful with monospaced fonts.</p>
+
+ <p><b id="SCI_FINDCOLUMN">SCI_FINDCOLUMN(int line, int column)</b><br />
+ This message returns the position of a <code>column</code> on a <code>line</code>
+ taking the width of tabs into account. It treats a multi-byte character as a single column.
+ Column numbers, like lines start at 0.</p>
+
+ <p><b id="SCI_POSITIONFROMPOINT">SCI_POSITIONFROMPOINT(int x, int y)</b><br />
+ <b id="SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE(int x, int y)</b><br />
+ <code>SCI_POSITIONFROMPOINT</code> finds the closest character position to a point and
+ <code>SCI_POSITIONFROMPOINTCLOSE</code> is similar but returns -1 if the point is outside the
+ window or not close to any characters.</p>
+
+ <p><b id="SCI_CHARPOSITIONFROMPOINT">SCI_CHARPOSITIONFROMPOINT(int x, int y)</b><br />
+ <b id="SCI_CHARPOSITIONFROMPOINTCLOSE">SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int y)</b><br />
+ <code>SCI_CHARPOSITIONFROMPOINT</code> finds the closest character to a point and
+ <code>SCI_CHARPOSITIONFROMPOINTCLOSE</code> is similar but returns -1 if the point is outside the
+ window or not close to any characters. This is similar to the previous methods but finds characters rather than
+ inter-character positions.</p>
+
+ <p><b id="SCI_POINTXFROMPOSITION">SCI_POINTXFROMPOSITION(&lt;unused&gt;, int pos)</b><br />
+ <b id="SCI_POINTYFROMPOSITION">SCI_POINTYFROMPOSITION(&lt;unused&gt;, int pos)</b><br />
+ These messages return the x and y display pixel location of text at position <code>pos</code>
+ in the document.</p>
+
+ <p><b id="SCI_HIDESELECTION">SCI_HIDESELECTION(bool hide)</b><br />
+ The normal state is to make the selection visible by drawing it as set by <a class="message"
+ href="#SCI_SETSELFORE"><code>SCI_SETSELFORE</code></a> and <a class="message"
+ href="#SCI_SETSELBACK"><code>SCI_SETSELBACK</code></a>. However, if you hide the selection, it
+ is drawn as normal text.</p>
+
+ <p><b id="SCI_CHOOSECARETX">SCI_CHOOSECARETX</b><br />
+ Scintilla remembers the x value of the last position horizontally moved to explicitly by the
+ user and this value is then used when moving vertically such as by using the up and down keys.
+ This message sets the current x position of the caret as the remembered value.</p>
+
+ <h2 id="MultipleSelectionAndVirtualSpace">Multiple Selection and Virtual Space</h2>
+
+ <code>
+ <a class="message" href="#SCI_SETMULTIPLESELECTION">SCI_SETMULTIPLESELECTION(bool multipleSelection)</a><br />
+ <a class="message" href="#SCI_GETMULTIPLESELECTION">SCI_GETMULTIPLESELECTION</a><br />
+ <a class="message" href="#SCI_SETADDITIONALSELECTIONTYPING">SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)</a><br />
+ <a class="message" href="#SCI_GETADDITIONALSELECTIONTYPING">SCI_GETADDITIONALSELECTIONTYPING</a><br />
+ <a class="message" href="#SCI_SETMULTIPASTE">SCI_SETMULTIPASTE(int multiPaste)</a><br />
+ <a class="message" href="#SCI_GETMULTIPASTE">SCI_GETMULTIPASTE</a><br />
+ <a class="message" href="#SCI_SETVIRTUALSPACEOPTIONS">SCI_SETVIRTUALSPACEOPTIONS(int virtualSpaceOptions)</a><br />
+ <a class="message" href="#SCI_GETVIRTUALSPACEOPTIONS">SCI_GETVIRTUALSPACEOPTIONS</a><br />
+ <a class="message" href="#SCI_SETRECTANGULARSELECTIONMODIFIER">SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)</a><br />
+ <a class="message" href="#SCI_GETRECTANGULARSELECTIONMODIFIER">SCI_GETRECTANGULARSELECTIONMODIFIER</a><br />
+ <br />
+
+ <a class="message" href="#SCI_GETSELECTIONS">SCI_GETSELECTIONS</a><br />
+ <a class="message" href="#SCI_CLEARSELECTIONS">SCI_CLEARSELECTIONS</a><br />
+ <a class="message" href="#SCI_SETSELECTION">SCI_SETSELECTION(int caret, int anchor)</a><br />
+ <a class="message" href="#SCI_ADDSELECTION">SCI_ADDSELECTION(int caret, int anchor)</a><br />
+ <a class="message" href="#SCI_SETMAINSELECTION">SCI_SETMAINSELECTION(int selection)</a><br />
+ <a class="message" href="#SCI_GETMAINSELECTION">SCI_GETMAINSELECTION</a><br />
+ <br />
+
+ <a class="message" href="#SCI_SETSELECTIONNCARET">SCI_SETSELECTIONNCARET(int selection, int pos)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNCARET">SCI_GETSELECTIONNCARET(int selection)</a><br />
+ <a class="message" href="#SCI_SETSELECTIONNCARETVIRTUALSPACE">SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNCARETVIRTUALSPACE">SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)</a><br />
+ <a class="message" href="#SCI_SETSELECTIONNANCHOR">SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNANCHOR">SCI_GETSELECTIONNANCHOR(int selection)</a><br />
+ <a class="message" href="#SCI_SETSELECTIONNANCHORVIRTUALSPACE">SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNANCHORVIRTUALSPACE">SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)</a><br />
+ <a class="message" href="#SCI_SETSELECTIONNSTART">SCI_SETSELECTIONNSTART(int selection, int pos)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNSTART">SCI_GETSELECTIONNSTART(int selection)</a><br />
+ <a class="message" href="#SCI_SETSELECTIONNEND">SCI_SETSELECTIONNEND(int selection, int pos)</a><br />
+ <a class="message" href="#SCI_GETSELECTIONNEND">SCI_GETSELECTIONNEND(int selection)</a><br />
+ <br />
+
+ <a class="message" href="#SCI_SETRECTANGULARSELECTIONCARET">SCI_SETRECTANGULARSELECTIONCARET(int pos)</a><br />
+ <a class="message" href="#SCI_GETRECTANGULARSELECTIONCARET">SCI_GETRECTANGULARSELECTIONCARET</a><br />
+ <a class="message" href="#SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)</a><br />
+ <a class="message" href="#SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE</a><br />
+ <a class="message" href="#SCI_SETRECTANGULARSELECTIONANCHOR">SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)</a><br />
+ <a class="message" href="#SCI_GETRECTANGULARSELECTIONANCHOR">SCI_GETRECTANGULARSELECTIONANCHOR</a><br />
+ <a class="message" href="#SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)</a><br />
+ <a class="message" href="#SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE</a><br />
+ <br />
+
+ <a class="message" href="#SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(int alpha)</a><br />
+ <a class="message" href="#SCI_GETADDITIONALSELALPHA">SCI_GETADDITIONALSELALPHA</a><br />
+ <a class="message" href="#SCI_SETADDITIONALSELFORE">SCI_SETADDITIONALSELFORE(int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_SETADDITIONALSELBACK">SCI_SETADDITIONALSELBACK(int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_SETADDITIONALCARETFORE">SCI_SETADDITIONALCARETFORE(int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_GETADDITIONALCARETFORE">SCI_GETADDITIONALCARETFORE</a><br />
+ <a class="message" href="#SCI_SETADDITIONALCARETSBLINK">SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)</a><br />
+ <a class="message" href="#SCI_GETADDITIONALCARETSBLINK">SCI_GETADDITIONALCARETSBLINK</a><br />
+ <a class="message" href="#SCI_SETADDITIONALCARETSVISIBLE">SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)</a><br />
+ <a class="message" href="#SCI_GETADDITIONALCARETSVISIBLE">SCI_GETADDITIONALCARETSVISIBLE</a><br />
+ <br />
+
+ <a class="message" href="#SCI_SWAPMAINANCHORCARET">SCI_SWAPMAINANCHORCARET</a><br />
+ <a class="message" href="#SCI_ROTATESELECTION">SCI_ROTATESELECTION</a><br />
+ </code>
+
+ <p>
+ There may be multiple selections active at one time.
+ More selections are made by holding down the Ctrl key while dragging with the mouse.
+ The most recent selection is the main selection and determines which part of the document is shown automatically.
+ Any selection apart from the main selection is called an additional selection.
+ The calls in the previous section operate on the main selection.
+ There is always at least one selection.
+ </p>
+
+ <p>
+ Rectangular selections are handled as multiple selections although the original rectangular range is remembered so that
+ subsequent operations may be handled differently for rectangular selections. For example, pasting a rectangular selection
+ places each piece in a vertical column.
+ </p>
+
+ <p>
+ Virtual space is space beyond the end of each line. The caret may be moved into virtual space but no real space will be
+ added to the document until there is some text typed or some other text insertion command is used.
+ </p>
+
+ <p>When discontiguous selections are copied to the clipboard, each selection is added to the clipboard text
+ in order with no delimiting characters.
+ For rectangular selections the document's line end is added after each line's text. Rectangular selections
+ are always copied from top line to bottom, not in the in order of selection.Virtual space is not copied.</p>
+
+ <p>
+ <b id="SCI_SETMULTIPLESELECTION">SCI_SETMULTIPLESELECTION(bool multipleSelection)</b><br />
+ <b id="SCI_GETMULTIPLESELECTION">SCI_GETMULTIPLESELECTION</b><br />
+ Enable or disable multiple selection.</p>
+
+ <p>
+ <b id="SCI_SETADDITIONALSELECTIONTYPING">SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)</b><br />
+ <b id="SCI_GETADDITIONALSELECTIONTYPING">SCI_GETADDITIONALSELECTIONTYPING</b><br />
+ Whether typing, backspace, or delete works with multiple selections simultaneously.</p>
+
+ <p>
+ <b id="SCI_SETMULTIPASTE">SCI_SETMULTIPASTE(int multiPaste)</b><br />
+ <b id="SCI_GETMULTIPASTE">SCI_GETMULTIPASTE</b><br />
+ When pasting into multiple selections, the pasted text can go into just the main selection with <code>SC_MULTIPASTE_ONCE</code>=0
+ or into each selection with <code>SC_MULTIPASTE_EACH</code>=1. <code>SC_MULTIPASTE_ONCE</code> is the default.</p>
+
+ <p>
+ <b id="SCI_SETVIRTUALSPACEOPTIONS">SCI_SETVIRTUALSPACEOPTIONS(int virtualSpace)</b><br />
+ <b id="SCI_GETVIRTUALSPACEOPTIONS">SCI_GETVIRTUALSPACEOPTIONS</b><br />
+ Virtual space can be enabled or disabled for rectangular selections or in other circumstances or in both.
+ There are two bit flags <code>SCVS_RECTANGULARSELECTION</code>=1 and
+ <code>SCVS_USERACCESSIBLE</code>=2 which can be set independently.
+ <code>SCVS_NONE</code>=0, the default, disables all use of virtual space.</p>
+
+ <p>
+ <b id="SCI_SETRECTANGULARSELECTIONMODIFIER">SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)</b><br />
+ <b id="SCI_GETRECTANGULARSELECTIONMODIFIER">SCI_GETRECTANGULARSELECTIONMODIFIER</b><br />
+ On GTK+, the key used to indicate that a rectangular selection should be created when combined with a mouse drag can be set.
+ The three possible values are <code>SCMOD_CTRL</code>=2 (default), <code>SCMOD_ALT</code>=4 or <code>SCMOD_SUPER</code>=8.
+ Since <code>SCMOD_ALT</code> is often already used by a window manager, the window manager may need configuring to allow this choice.
+ <code>SCMOD_SUPER</code> is often a system dependent modifier key such as the Left Windows key on a Windows keyboard or the
+ Command key on a Mac.</p>
+
+ <p>
+ <b id="SCI_GETSELECTIONS">SCI_GETSELECTIONS</b><br />
+ Return the number of selections currently active.</p>
+
+ <p>
+ <b id="SCI_CLEARSELECTIONS">SCI_CLEARSELECTIONS</b><br />
+ Set a single empty selection at 0 as the only selection.</p>
+
+ <p>
+ <b id="SCI_SETSELECTION">SCI_SETSELECTION(int caret, int anchor)</b><br />
+ Set a single selection from <code>anchor</code> to <code>caret</code> as the only selection.</p>
+
+ <p>
+ <b id="SCI_ADDSELECTION">SCI_ADDSELECTION(int caret, int anchor)</b><br />
+ Add a new selection from <code>anchor</code> to <code>caret</code> as the main selection retaining all other
+ selections as additional selections.
+ Since there is always at least one selection, to set a list of selections, the first selection should be
+ added with <code>SCI_SETSELECTION</code> and later selections added with <code>SCI_ADDSELECTION</code></p>
+
+ <p>
+ <b id="SCI_SETMAINSELECTION">SCI_SETMAINSELECTION(int selection)</b><br />
+ <b id="SCI_GETMAINSELECTION">SCI_GETMAINSELECTION</b><br />
+ One of the selections is the main selection which is used to determine what range of text is automatically visible.
+ The main selection may be displayed in different colours or with a differently styled caret.
+ Only an already existing selection can be made main.</p>
+
+ <p>
+ <b id="SCI_SETSELECTIONNCARET">SCI_SETSELECTIONNCARET(int selection, int pos)</b><br />
+ <b id="SCI_GETSELECTIONNCARET">SCI_GETSELECTIONNCARET(int selection)</b><br />
+ <b id="SCI_SETSELECTIONNCARETVIRTUALSPACE">SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)</b><br />
+ <b id="SCI_GETSELECTIONNCARETVIRTUALSPACE">SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)</b><br />
+ <b id="SCI_SETSELECTIONNANCHOR">SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)</b><br />
+ <b id="SCI_GETSELECTIONNANCHOR">SCI_GETSELECTIONNANCHOR(int selection)</b><br />
+ <b id="SCI_SETSELECTIONNANCHORVIRTUALSPACE">SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)</b><br />
+ <b id="SCI_GETSELECTIONNANCHORVIRTUALSPACE">SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)</b><br />
+ Set or query the position and amount of virtual space for the caret and anchor of each already existing selection.</p>
+
+ <p>
+ <b id="SCI_SETSELECTIONNSTART">SCI_SETSELECTIONNSTART(int selection, int pos)</b><br />
+ <b id="SCI_GETSELECTIONNSTART">SCI_GETSELECTIONNSTART(int selection)</b><br />
+ <b id="SCI_SETSELECTIONNEND">SCI_SETSELECTIONNEND(int selection, int pos)</b><br />
+ <b id="SCI_GETSELECTIONNEND">SCI_GETSELECTIONNEND(int selection)</b><br />
+ Set or query the start and end position of each already existing selection.
+ Mostly of use to query each range for its text.</p>
+
+ <p>
+ <b id="SCI_SETRECTANGULARSELECTIONCARET">SCI_SETRECTANGULARSELECTIONCARET(int pos)</b><br />
+ <b id="SCI_GETRECTANGULARSELECTIONCARET">SCI_GETRECTANGULARSELECTIONCARET</b><br />
+ <b id="SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)</b><br />
+ <b id="SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE</b><br />
+ <b id="SCI_SETRECTANGULARSELECTIONANCHOR">SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)</b><br />
+ <b id="SCI_GETRECTANGULARSELECTIONANCHOR">SCI_GETRECTANGULARSELECTIONANCHOR</b><br />
+ <b id="SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)</b><br />
+ <b id="SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE</b><br />
+ Set or query the position and amount of virtual space for the caret and anchor of the rectangular selection.
+ After setting the rectangular selection, this is broken down into multiple selections, one for each line.</p>
+
+ <p>
+ <b id="SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(int alpha)</b><br />
+ <b id="SCI_GETADDITIONALSELALPHA">SCI_GETADDITIONALSELALPHA</b><br />
+ <b id="SCI_SETADDITIONALSELFORE">SCI_SETADDITIONALSELFORE(int <a class="jump" href="#colour">colour</a>)</b><br />
+ <b id="SCI_SETADDITIONALSELBACK">SCI_SETADDITIONALSELBACK(int <a class="jump" href="#colour">colour</a>)</b><br />
+ Modify the appearence of additional selections so that they can be differentiated from the main selection which has its appearence set with
+ <a class="message" href="#SCI_SETSELALPHA"><code>SCI_SETSELALPHA</code></a>,
+ <a class="message" href="#SCI_GETSELALPHA"><code>SCI_GETSELALPHA</code></a>,
+ <a class="message" href="#SCI_SETSELFORE"><code>SCI_SETSELFORE</code></a>, and
+ <a class="message" href="#SCI_SETSELBACK"><code>SCI_SETSELBACK</code></a>.</p>
+
+ <p>
+ <b id="SCI_SETADDITIONALCARETFORE">SCI_SETADDITIONALCARETFORE(int <a class="jump" href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETADDITIONALCARETFORE">SCI_GETADDITIONALCARETFORE</b><br />
+ <b id="SCI_SETADDITIONALCARETSBLINK">SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)</b><br />
+ <b id="SCI_GETADDITIONALCARETSBLINK">SCI_GETADDITIONALCARETSBLINK</b><br />
+ Modify the appearence of additional carets so that they can be differentiated from the main caret which has its appearence set with
+ <a class="message" href="#SCI_SETCARETFORE"><code>SCI_SETCARETFORE</code></a>,
+ <a class="message" href="#SCI_GETCARETFORE"><code>SCI_GETCARETFORE</code></a>,
+ <a class="message" href="#SCI_SETCARETPERIOD"><code>SCI_SETCARETPERIOD</code></a>, and
+ <a class="message" href="#SCI_GETCARETPERIOD"><code>SCI_GETCARETPERIOD</code></a>.</p>
+
+ <p>
+ <b id="SCI_SETADDITIONALCARETSVISIBLE">SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)</b><br />
+ <b id="SCI_GETADDITIONALCARETSVISIBLE">SCI_GETADDITIONALCARETSVISIBLE</b><br />
+ Determine whether to show additional carets (defaults to <code>true</code>).
+
+ <p>
+ <b id="SCI_SWAPMAINANCHORCARET">SCI_SWAPMAINANCHORCARET</b><br />
+ <b id="SCI_ROTATESELECTION">SCI_ROTATESELECTION</b><br />
+ These commands may be assigned to keys to make it possible to manipulate multiple selections.
+ <code>SCI_SWAPMAINANCHORCARET</code> moves the caret to the opposite end of the main selection.
+ <code>SCI_ROTATESELECTION</code> makes the next selection be the main selection.
+ </p>
+
+ <h2 id="ScrollingAndAutomaticScrolling">Scrolling and automatic scrolling</h2>
+ <code><a class="message" href="#SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</a><br />
+ <a class="message" href="#SCI_SCROLLCARET">SCI_SCROLLCARET</a><br />
+ <a class="message" href="#SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int
+ caretSlop)</a><br />
+ <a class="message" href="#SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int
+ caretSlop)</a><br />
+ <a class="message" href="#SCI_SETVISIBLEPOLICY">SCI_SETVISIBLEPOLICY(int caretPolicy, int
+ caretSlop)</a><br />
+ <a class="message" href="#SCI_SETHSCROLLBAR">SCI_SETHSCROLLBAR(bool visible)</a><br />
+ <a class="message" href="#SCI_GETHSCROLLBAR">SCI_GETHSCROLLBAR</a><br />
+ <a class="message" href="#SCI_SETVSCROLLBAR">SCI_SETVSCROLLBAR(bool visible)</a><br />
+ <a class="message" href="#SCI_GETVSCROLLBAR">SCI_GETVSCROLLBAR</a><br />
+ <a class="message" href="#SCI_GETXOFFSET">SCI_GETXOFFSET</a><br />
+ <a class="message" href="#SCI_SETXOFFSET">SCI_SETXOFFSET(int xOffset)</a><br />
+ <a class="message" href="#SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH(int pixelWidth)</a><br />
+ <a class="message" href="#SCI_GETSCROLLWIDTH">SCI_GETSCROLLWIDTH</a><br />
+ <a class="message" href="#SCI_SETSCROLLWIDTHTRACKING">SCI_SETSCROLLWIDTHTRACKING(bool tracking)</a><br />
+ <a class="message" href="#SCI_GETSCROLLWIDTHTRACKING">SCI_GETSCROLLWIDTHTRACKING</a><br />
+ <a class="message" href="#SCI_SETENDATLASTLINE">SCI_SETENDATLASTLINE(bool
+ endAtLastLine)</a><br />
+ <a class="message" href="#SCI_GETENDATLASTLINE">SCI_GETENDATLASTLINE</a><br />
+ </code>
+
+ <p><b id="SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</b><br />
+ This will attempt to scroll the display by the number of columns and lines that you specify.
+ Positive line values increase the line number at the top of the screen (i.e. they move the text
+ upwards as far as the user is concerned), Negative line values do the reverse.</p>
+
+ <p>The column measure is the width of a space in the default style. Positive values increase
+ the column at the left edge of the view (i.e. they move the text leftwards as far as the user
+ is concerned). Negative values do the reverse.</p>
+
+ <p>See also: <a class="message" href="#SCI_SETXOFFSET"><code>SCI_SETXOFFSET</code></a></p>
+
+ <p><b id="SCI_SCROLLCARET">SCI_SCROLLCARET</b><br />
+ If the current position (this is the caret if there is no selection) is not visible, the view
+ is scrolled to make it visible according to the current caret policy.</p>
+
+ <p><b id="SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
+ <b id="SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
+ These set the caret policy. The value of <code>caretPolicy</code> is a combination of
+ <code>CARET_SLOP</code>, <code>CARET_STRICT</code>, <code>CARET_JUMPS</code> and
+ <code>CARET_EVEN</code>.</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Caret policy">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>CARET_SLOP</code></th>
+
+ <td>If set, we can define a slop value: <code>caretSlop</code>. This value defines an
+ unwanted zone (UZ) where the caret is... unwanted. This zone is defined as a number of
+ pixels near the vertical margins, and as a number of lines near the horizontal margins.
+ By keeping the caret away from the edges, it is seen within its context. This makes it
+ likely that the identifier that the caret is on can be completely seen, and that the
+ current line is seen with some of the lines following it, which are often dependent on
+ that line.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>CARET_STRICT</code></th>
+
+ <td>If set, the policy set by <code>CARET_SLOP</code> is enforced... strictly. The caret
+ is centred on the display if <code>caretSlop</code> is not set, and cannot go in the UZ
+ if <code>caretSlop</code> is set.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>CARET_JUMPS</code></th>
+
+ <td>If set, the display is moved more energetically so the caret can move in the same
+ direction longer before the policy is applied again. '3UZ' notation is used to indicate
+ three time the size of the UZ as a distance to the margin.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>CARET_EVEN</code></th>
+
+ <td>If not set, instead of having symmetrical UZs, the left and bottom UZs are extended
+ up to right and top UZs respectively. This way, we favour the displaying of useful
+ information: the beginning of lines, where most code reside, and the lines after the
+ caret, for example, the body of a function.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <table cellpadding="3" cellspacing="0" border="1" summary="Caret positioning">
+ <thead align="center">
+ <tr>
+ <th>slop</th>
+
+ <th>strict</th>
+
+ <th>jumps</th>
+
+ <th>even</th>
+
+ <th>Caret can go to the margin</th>
+
+ <th>On reaching limit (going out of visibility<br />
+ or going into the UZ) display is...</th>
+ </tr>
+ </thead>
+
+ <tbody align="center">
+ <tr>
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret on top/on right</td>
+ </tr>
+
+ <tr>
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>Yes</td>
+
+ <td>moved by one position</td>
+ </tr>
+
+ <tr>
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret on top/on right</td>
+ </tr>
+
+ <tr>
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>Yes</td>
+
+ <td>centred on the caret</td>
+ </tr>
+
+ <tr>
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>-</td>
+
+ <td>0</td>
+
+ <td>Caret is always on top/on right of display</td>
+
+ <td>-</td>
+ </tr>
+
+ <tr>
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>-</td>
+
+ <td>1</td>
+
+ <td>No, caret is always centred</td>
+
+ <td>-</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret out of the asymmetrical UZ</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret out of the UZ</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret at 3UZ of the top or right margin</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>Yes</td>
+
+ <td>moved to put caret at 3UZ of the margin</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>-</td>
+
+ <td>0</td>
+
+ <td>Caret is always at UZ of top/right margin</td>
+
+ <td>-</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>1</td>
+
+ <td>No, kept out of UZ</td>
+
+ <td>moved by one position</td>
+ </tr>
+
+ <tr>
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>1</td>
+
+ <td>0</td>
+
+ <td>No, kept out of UZ</td>
+
+ <td>moved to put caret at 3UZ of the margin</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_SETVISIBLEPOLICY">SCI_SETVISIBLEPOLICY(int caretPolicy, int caretSlop)</b><br />
+ This determines how the vertical positioning is determined when <a class="message"
+ href="#SCI_ENSUREVISIBLEENFORCEPOLICY"><code>SCI_ENSUREVISIBLEENFORCEPOLICY</code></a> is
+ called. It takes <code>VISIBLE_SLOP</code> and <code>VISIBLE_STRICT</code> flags for the policy
+ parameter. It is similar in operation to <a class="message"
+ href="#SCI_SETYCARETPOLICY"><code>SCI_SETYCARETPOLICY(int caretPolicy, int
+ caretSlop)</code></a>.</p>
+
+ <p><b id="SCI_SETHSCROLLBAR">SCI_SETHSCROLLBAR(bool visible)</b><br />
+ <b id="SCI_GETHSCROLLBAR">SCI_GETHSCROLLBAR</b><br />
+ The horizontal scroll bar is only displayed if it is needed for the assumed width.
+ If you never wish to see it, call
+ <code>SCI_SETHSCROLLBAR(0)</code>. Use <code>SCI_SETHSCROLLBAR(1)</code> to enable it again.
+ <code>SCI_GETHSCROLLBAR</code> returns the current state. The default state is to display it
+ when needed.</p>
+ <p>See also: <a class="message" href="#SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH</a>.</p>
+
+ <p><b id="SCI_SETVSCROLLBAR">SCI_SETVSCROLLBAR(bool visible)</b><br />
+ <b id="SCI_GETVSCROLLBAR">SCI_GETVSCROLLBAR</b><br />
+ By default, the vertical scroll bar is always displayed when required. You can choose to hide
+ or show it with <code>SCI_SETVSCROLLBAR</code> and get the current state with
+ <code>SCI_GETVSCROLLBAR</code>.</p>
+
+ <p><b id="SCI_SETXOFFSET">SCI_SETXOFFSET(int xOffset)</b><br />
+ <b id="SCI_GETXOFFSET">SCI_GETXOFFSET</b><br />
+ The <code>xOffset</code> is the horizontal scroll position in pixels of the start of the text
+ view. A value of 0 is the normal position with the first text column visible at the left of the
+ view.</p>
+
+ <p>See also: <a class="message" href="#SCI_LINESCROLL"><code>SCI_LINESCROLL</code></a></p>
+
+ <p><b id="SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH(int pixelWidth)</b><br />
+ <b id="SCI_GETSCROLLWIDTH">SCI_GETSCROLLWIDTH</b><br />
+ For performance, Scintilla does not measure the display width of the document to determine
+ the properties of the horizontal scroll bar. Instead, an assumed width is used.
+ These messages set and get the document width in pixels assumed by Scintilla.
+ The default value is 2000.
+ To ensure the width of the currently visible lines can be scrolled use
+ <a class="message" href="#SCI_SETSCROLLWIDTHTRACKING"><code>SCI_SETSCROLLWIDTHTRACKING</code></a></p>
+
+ <p><b id="SCI_SETSCROLLWIDTHTRACKING">SCI_SETSCROLLWIDTHTRACKING(bool tracking)</b><br />
+ <b id="SCI_GETSCROLLWIDTHTRACKING">SCI_GETSCROLLWIDTHTRACKING</b><br />
+ If scroll width tracking is enabled then the scroll width is adjusted to ensure that all of the lines currently
+ displayed can be completely scrolled. This mode never adjusts the scroll width to be narrower.</p>
+
+ <p><b id="SCI_SETENDATLASTLINE">SCI_SETENDATLASTLINE(bool endAtLastLine)</b><br />
+ <b id="SCI_GETENDATLASTLINE">SCI_GETENDATLASTLINE</b><br />
+ <code>SCI_SETENDATLASTLINE</code> sets the scroll range so that maximum scroll position has
+ the last line at the bottom of the view (default). Setting this to <code>false</code> allows
+ scrolling one page below the last line.</p>
+
+ <h2 id="WhiteSpace">White space</h2>
+ <code><a class="message" href="#SCI_SETVIEWWS">SCI_SETVIEWWS(int wsMode)</a><br />
+ <a class="message" href="#SCI_GETVIEWWS">SCI_GETVIEWWS</a><br />
+ <a class="message" href="#SCI_SETWHITESPACEFORE">SCI_SETWHITESPACEFORE(bool
+ useWhitespaceForeColour, int colour)</a><br />
+ <a class="message" href="#SCI_SETWHITESPACEBACK">SCI_SETWHITESPACEBACK(bool
+ useWhitespaceBackColour, int colour)</a><br />
+ <a class="message" href="#SCI_SETWHITESPACESIZE">SCI_SETWHITESPACESIZE(int
+ size)</a><br />
+ <a class="message" href="#SCI_GETWHITESPACESIZE">SCI_GETWHITESPACESIZE</a><br />
+ <a class="message" href="#SCI_SETEXTRAASCENT">SCI_SETEXTRAASCENT(int extraAscent)</a><br />
+ <a class="message" href="#SCI_GETEXTRAASCENT">SCI_GETEXTRAASCENT</a><br />
+ <a class="message" href="#SCI_SETEXTRADESCENT">SCI_SETEXTRADESCENT(int extraDescent)</a><br />
+ <a class="message" href="#SCI_GETEXTRADESCENT">SCI_GETEXTRADESCENT</a><br />
+ </code>
+
+ <p><b id="SCI_SETVIEWWS">SCI_SETVIEWWS(int wsMode)</b><br />
+ <b id="SCI_GETVIEWWS">SCI_GETVIEWWS</b><br />
+ White space can be made visible which may be useful for languages in which white space is
+ significant, such as Python. Space characters appear as small centred dots and tab characters
+ as light arrows pointing to the right. There are also ways to control the display of <a
+ class="jump" href="#LineEndings">end of line characters</a>. The two messages set and get the
+ white space display mode. The <code>wsMode</code> argument can be one of:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="White space policy">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>SCWS_INVISIBLE</code></th>
+
+ <td>0</td>
+
+ <td>The normal display mode with white space displayed as an empty background
+ colour.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>SCWS_VISIBLEALWAYS</code></th>
+
+ <td>1</td>
+
+ <td>White space characters are drawn as dots and arrows,</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>SCWS_VISIBLEAFTERINDENT</code></th>
+
+ <td>2</td>
+
+ <td>White space used for indentation is displayed normally but after the first visible
+ character, it is shown as dots and arrows.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>The effect of using any other <code>wsMode</code> value is undefined.</p>
+
+ <p><b id="SCI_SETWHITESPACEFORE">SCI_SETWHITESPACEFORE(bool useWhitespaceForeColour, int <a
+ class="jump" href="#colour">colour</a>)</b><br />
+ <b id="SCI_SETWHITESPACEBACK">SCI_SETWHITESPACEBACK(bool useWhitespaceBackColour, int <a
+ class="jump" href="#colour">colour</a>)</b><br />
+ By default, the colour of visible white space is determined by the lexer in use. The
+ foreground and/or background colour of all visible white space can be set globally, overriding
+ the lexer's colours with <code>SCI_SETWHITESPACEFORE</code> and
+ <code>SCI_SETWHITESPACEBACK</code>.</p>
+
+ <b id="SCI_SETWHITESPACESIZE">SCI_SETWHITESPACESIZE(int size)</b><br />
+ <b id="SCI_GETWHITESPACESIZE">SCI_GETWHITESPACESIZE</b><br />
+ <code>SCI_SETWHITESPACESIZE</code> sets the size of the dots used for mark space characters.
+ The <code>SCI_GETWHITESPACESIZE</code> message retrieves the current size.
+ <p>
+
+ <p>
+ <b id="SCI_SETEXTRAASCENT">SCI_SETEXTRAASCENT(int extraAscent)</b><br />
+ <b id="SCI_GETEXTRAASCENT">SCI_GETEXTRAASCENT</b><br />
+ <b id="SCI_SETEXTRADESCENT">SCI_SETEXTRADESCENT(int extraDescent)</b><br />
+ <b id="SCI_GETEXTRADESCENT">SCI_GETEXTRADESCENT</b><br />
+ Text is drawn with the base of each character on a 'baseline'. The height of a line is found from the maximum
+ that any style extends above the baseline (its 'ascent'), added to the maximum that any style extends below the
+ baseline (its 'descent').
+ Space may be added to the maximum ascent (<code>SCI_SETEXTRAASCENT</code>) and the
+ maximum descent (<code>SCI_SETEXTRADESCENT</code>) to allow for more space between lines.
+ This may done to make the text easier to read or to accomodate underlines or highlights.
+ <p>
+
+ <h2 id="Cursor">Cursor</h2>
+
+ <p><b id="SCI_SETCURSOR">SCI_SETCURSOR(int curType)</b><br />
+ <b id="SCI_GETCURSOR">SCI_GETCURSOR</b><br />
+ The cursor is normally chosen in a context sensitive way, so it will be different over the
+ margin than when over the text. When performing a slow action, you may wish to change to a wait
+ cursor. You set the cursor type with <code>SCI_SETCURSOR</code>. The <code>curType</code>
+ argument can be:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Mouse cursors">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>SC_CURSORNORMAL</code></th>
+
+ <td>-1</td>
+
+ <td>The normal cursor is displayed.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>SC_CURSORWAIT</code></th>
+
+ <td>&nbsp;4</td>
+
+ <td>The wait cursor is displayed when the mouse is over or owned by the Scintilla
+ window.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>Cursor values 1 through 7 have defined cursors, but only <code>SC_CURSORWAIT</code> is
+ usefully controllable. Other values of <code>curType</code> cause a pointer to be displayed.
+ The <code>SCI_GETCURSOR</code> message returns the last cursor type you set, or
+ <code>SC_CURSORNORMAL</code> (-1) if you have not set a cursor type.</p>
+
+ <h2 id="MouseCapture">Mouse capture</h2>
+
+ <p><b id="SCI_SETMOUSEDOWNCAPTURES">SCI_SETMOUSEDOWNCAPTURES(bool captures)</b><br />
+ <b id="SCI_GETMOUSEDOWNCAPTURES">SCI_GETMOUSEDOWNCAPTURES</b><br />
+ When the mouse is pressed inside Scintilla, it is captured so future mouse movement events are
+ sent to Scintilla. This behavior may be turned off with
+ <code>SCI_SETMOUSEDOWNCAPTURES(0)</code>.</p>
+
+ <h2 id="LineEndings">Line endings</h2>
+
+ <p>Scintilla can interpret any of the three major line end conventions, Macintosh (\r), Unix
+ (\n) and CP/M / DOS / Windows (\r\n). When the user presses the Enter key, one of these line
+ end strings is inserted into the buffer. The default is \r\n in Windows and \n in Unix, but
+ this can be changed with the <code>SCI_SETEOLMODE</code> message. You can also convert the
+ entire document to one of these line endings with <code>SCI_CONVERTEOLS</code>. Finally, you
+ can choose to display the line endings with <code>SCI_SETVIEWEOL</code>.</p>
+ <code><a class="message" href="#SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</a><br />
+ <a class="message" href="#SCI_GETEOLMODE">SCI_GETEOLMODE</a><br />
+ <a class="message" href="#SCI_CONVERTEOLS">SCI_CONVERTEOLS(int eolMode)</a><br />
+ <a class="message" href="#SCI_SETVIEWEOL">SCI_SETVIEWEOL(bool visible)</a><br />
+ <a class="message" href="#SCI_GETVIEWEOL">SCI_GETVIEWEOL</a><br />
+ </code>
+
+ <p><b id="SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</b><br />
+ <b id="SCI_GETEOLMODE">SCI_GETEOLMODE</b><br />
+ <code>SCI_SETEOLMODE</code> sets the characters that are added into the document when the user
+ presses the Enter key. You can set <code>eolMode</code> to one of <code>SC_EOL_CRLF</code> (0),
+ <code>SC_EOL_CR</code> (1), or <code>SC_EOL_LF</code> (2). The <code>SCI_GETEOLMODE</code>
+ message retrieves the current state.</p>
+
+ <p><b id="SCI_CONVERTEOLS">SCI_CONVERTEOLS(int eolMode)</b><br />
+ This message changes all the end of line characters in the document to match
+ <code>eolMode</code>. Valid values are: <code>SC_EOL_CRLF</code> (0), <code>SC_EOL_CR</code>
+ (1), or <code>SC_EOL_LF</code> (2).</p>
+
+ <p><b id="SCI_SETVIEWEOL">SCI_SETVIEWEOL(bool visible)</b><br />
+ <b id="SCI_GETVIEWEOL">SCI_GETVIEWEOL</b><br />
+ Normally, the end of line characters are hidden, but <code>SCI_SETVIEWEOL</code> allows you to
+ display (or hide) them by setting <code>visible</code> <code>true</code> (or
+ <code>false</code>). The visible rendering of the end of line characters is similar to
+ <code>(CR)</code>, <code>(LF)</code>, or <code>(CR)(LF)</code>. <code>SCI_GETVIEWEOL</code>
+ returns the current state.</p>
+
+ <h2 id="Styling">Styling</h2>
+
+ <p>The styling messages allow you to assign styles to text. The standard Scintilla settings
+ divide the 8 style bits available for each character into 5 bits (0 to 4 = <a class="jump"
+ href="#StyleDefinition">styles 0 to 31</a>) that set a style and three bits (5 to 7) that
+ define <a class="jump" href="#Indicators">indicators</a>. You can change the balance between
+ styles and indicators with <a class="message"
+ href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a>. If your styling needs can be met by
+ one of the standard lexers, or if you can write your own, then a lexer is probably the easiest
+ way to style your document. If you choose to use the container to do the styling you can use
+ the <a class="message" href="#SCI_SETLEXER"><code>SCI_SETLEXER</code></a> command to select
+ <code>SCLEX_CONTAINER</code>, in which case the container is sent a <a class="message"
+ href="#SCN_STYLENEEDED"><code>SCN_STYLENEEDED</code></a> <a class="jump"
+ href="#Notifications">notification</a> each time text needs styling for display. As another
+ alternative, you might use idle time to style the document. Even if you use a lexer, you might
+ use the styling commands to mark errors detected by a compiler. The following commands can be
+ used.</p>
+ <code><a class="message" href="#SCI_GETENDSTYLED">SCI_GETENDSTYLED</a><br />
+ <a class="message" href="#SCI_STARTSTYLING">SCI_STARTSTYLING(int position, int mask)</a><br />
+ <a class="message" href="#SCI_SETSTYLING">SCI_SETSTYLING(int length, int style)</a><br />
+ <a class="message" href="#SCI_SETSTYLINGEX">SCI_SETSTYLINGEX(int length, const char
+ *styles)</a><br />
+ <a class="message" href="#SCI_SETLINESTATE">SCI_SETLINESTATE(int line, int value)</a><br />
+ <a class="message" href="#SCI_GETLINESTATE">SCI_GETLINESTATE(int line)</a><br />
+ <a class="message" href="#SCI_GETMAXLINESTATE">SCI_GETMAXLINESTATE</a><br />
+ </code>
+
+ <p><b id="SCI_GETENDSTYLED">SCI_GETENDSTYLED</b><br />
+ Scintilla keeps a record of the last character that is likely to be styled correctly. This is
+ moved forwards when characters after it are styled and moved backwards if changes are made to
+ the text of the document before it. Before drawing text, this position is checked to see if any
+ styling is needed and, if so, a <code><a class="message"
+ href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a></code> notification message is sent to the
+ container. The container can send <code>SCI_GETENDSTYLED</code> to work out where it needs to
+ start styling. Scintilla will always ask to style whole lines.</p>
+
+ <p><b id="SCI_STARTSTYLING">SCI_STARTSTYLING(int pos, int mask)</b><br />
+ This prepares for styling by setting the styling position <code>pos</code> to start at and a
+ <code>mask</code> indicating which bits of the style bytes can be set. The mask allows styling
+ to occur over several passes, with, for example, basic styling done on an initial pass to
+ ensure that the text of the code is seen quickly and correctly, and then a second slower pass,
+ detecting syntax errors and using indicators to show where these are. For example, with the
+ standard settings of 5 style bits and 3 indicator bits, you would use a <code>mask</code> value
+ of 31 (0x1f) if you were setting text styles and did not want to change the indicators. After
+ <code>SCI_STARTSTYLING</code>, send multiple <code>SCI_SETSTYLING</code> messages for each
+ lexical entity to style.</p>
+
+ <p><b id="SCI_SETSTYLING">SCI_SETSTYLING(int length, int style)</b><br />
+ This message sets the style of <code>length</code> characters starting at the styling position
+ and then increases the styling position by <code>length</code>, ready for the next call. If
+ <code>sCell</code> is the style byte, the operation is:<br />
+ <code>if ((sCell &amp; mask) != style) sCell = (sCell &amp; ~mask) | (style &amp;
+ mask);</code><br />
+ </p>
+
+ <p><b id="SCI_SETSTYLINGEX">SCI_SETSTYLINGEX(int length, const char *styles)</b><br />
+ As an alternative to <code>SCI_SETSTYLING</code>, which applies the same style to each byte,
+ you can use this message which specifies the styles for each of <code>length</code> bytes from
+ the styling position and then increases the styling position by <code>length</code>, ready for
+ the next call. The <code>length</code> styling bytes pointed at by <code>styles</code> should
+ not contain any bits not set in mask.</p>
+
+ <p><b id="SCI_SETLINESTATE">SCI_SETLINESTATE(int line, int value)</b><br />
+ <b id="SCI_GETLINESTATE">SCI_GETLINESTATE(int line)</b><br />
+ As well as the 8 bits of lexical state stored for each character there is also an integer
+ stored for each line. This can be used for longer lived parse states such as what the current
+ scripting language is in an ASP page. Use <code>SCI_SETLINESTATE</code> to set the integer
+ value and <code>SCI_GETLINESTATE</code> to get the value.
+ Changing the value produces a <a class="message" href="#SC_MOD_CHANGELINESTATE">SC_MOD_CHANGELINESTATE</a> notification.
+ </p>
+
+ <p><b id="SCI_GETMAXLINESTATE">SCI_GETMAXLINESTATE</b><br />
+ This returns the last line that has any line state.</p>
+
+ <h2 id="StyleDefinition">Style definition</h2>
+
+ <p>While the style setting messages mentioned above change the style numbers associated with
+ text, these messages define how those style numbers are interpreted visually. There are 256
+ lexer styles that can be set, numbered 0 to <code>STYLE_MAX</code> (255). Unless you use <a
+ class="message" href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> to change the number
+ of style bits, styles 0 to 31 are used to set the text attributes. There are also some
+ predefined numbered styles starting at 32, The following <code>STYLE_</code>* constants are
+ defined.</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Preset styles">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>STYLE_DEFAULT</code></th>
+
+ <td>32</td>
+
+ <td>This style defines the attributes that all styles receive when the
+ <code>SCI_STYLECLEARALL</code> message is used.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_LINENUMBER</code></th>
+
+ <td>33</td>
+
+ <td>This style sets the attributes of the text used to display line numbers in a line
+ number margin. The background colour set for this style also sets the background colour
+ for all margins that do not have any folding mask bits set. That is, any margin for which
+ <code>mask &amp; SC_MASK_FOLDERS</code> is 0. See <a class="message"
+ href="#SCI_SETMARGINMASKN"><code>SCI_SETMARGINMASKN</code></a> for more about masks.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_BRACELIGHT</code></th>
+
+ <td>34</td>
+
+ <td>This style sets the attributes used when highlighting braces with the <a
+ class="message" href="#BraceHighlighting"><code>SCI_BRACEHIGHLIGHT</code></a> message and
+ when highlighting the corresponding indentation with <a class="message"
+ href="#SCI_SETHIGHLIGHTGUIDE"><code>SCI_SETHIGHLIGHTGUIDE</code></a>.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_BRACEBAD</code></th>
+
+ <td>35</td>
+
+ <td>This style sets the display attributes used when marking an unmatched brace with the
+ <a class="message" href="#BraceHighlighting"><code>SCI_BRACEBADLIGHT</code></a>
+ message.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_CONTROLCHAR</code></th>
+
+ <td>36</td>
+
+ <td>This style sets the font used when drawing control characters.
+ Only the font, size, bold, italics, and character set attributes are used and not
+ the colour attributes. See
+ also: <a class="message"
+ href="#SCI_SETCONTROLCHARSYMBOL"><code>SCI_SETCONTROLCHARSYMBOL</code></a>.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_INDENTGUIDE</code></th>
+
+ <td>37</td>
+
+ <td>This style sets the foreground and background colours used when drawing the
+ indentation guides.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_CALLTIP</code></th>
+
+ <td>38</td>
+
+ <td> Call tips normally use the font attributes defined by <code>STYLE_DEFAULT</code>.
+ Use of <a class="message" href="#SCI_CALLTIPUSESTYLE"><code>SCI_CALLTIPUSESTYLE</code></a>
+ causes call tips to use this style instead. Only the font face name, font size,
+ foreground and background colours and character set attributes are used.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_LASTPREDEFINED</code></th>
+
+ <td>39</td>
+
+ <td>To make it easier for client code to discover the range of styles that are
+ predefined, this is set to the style number of the last predefined style. This is
+ currently set to 39 and the last style with an identifier is 38, which reserves space
+ for one future predefined style.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>STYLE_MAX</code></th>
+
+ <td>255</td>
+
+ <td>This is not a style but is the number of the maximum style that can be set. Styles
+ between <code>STYLE_LASTPREDEFINED</code> and <code>STYLE_MAX</code> would be appropriate
+ if you used <a class="message" href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a>
+ to set more than 5 style bits.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>For each style you can set the font name, size and use of bold, italic and underline,
+ foreground and background colour and the character set. You can also choose to hide text with a
+ given style, display all characters as upper or lower case and fill from the last character on
+ a line to the end of the line (for embedded languages). There is also an experimental attribute
+ to make text read-only.</p>
+
+ <p>It is entirely up to you how you use styles. If you want to use syntax colouring you might
+ use style 0 for white space, style 1 for numbers, style 2 for keywords, style 3 for strings,
+ style 4 for preprocessor, style 5 for operators, and so on.</p>
+ <code><a class="message" href="#SCI_STYLERESETDEFAULT">SCI_STYLERESETDEFAULT</a><br />
+ <a class="message" href="#SCI_STYLECLEARALL">SCI_STYLECLEARALL</a><br />
+ <a class="message" href="#SCI_STYLESETFONT">SCI_STYLESETFONT(int styleNumber, char
+ *fontName)</a><br />
+ <a class="message" href="#SCI_STYLEGETFONT">SCI_STYLEGETFONT(int styleNumber, char *fontName)</a><br />
+ <a class="message" href="#SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int
+ sizeInPoints)</a><br />
+ <a class="message" href="#SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool
+ bold)</a><br />
+ <a class="message" href="#SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool
+ italic)</a><br />
+ <a class="message" href="#SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETUNDERLINE">SCI_STYLESETUNDERLINE(int styleNumber, bool
+ underline)</a><br />
+ <a class="message" href="#SCI_STYLEGETUNDERLINE">SCI_STYLEGETUNDERLINE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETFORE">SCI_STYLESETFORE(int styleNumber, int
+ colour)</a><br />
+ <a class="message" href="#SCI_STYLEGETFORE">SCI_STYLEGETFORE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETBACK">SCI_STYLESETBACK(int styleNumber, int
+ colour)</a><br />
+ <a class="message" href="#SCI_STYLEGETBACK">SCI_STYLEGETBACK(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETEOLFILLED">SCI_STYLESETEOLFILLED(int styleNumber, bool
+ eolFilled)</a><br />
+ <a class="message" href="#SCI_STYLEGETEOLFILLED">SCI_STYLEGETEOLFILLED(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETCHARACTERSET">SCI_STYLESETCHARACTERSET(int styleNumber,
+ int charSet)</a><br />
+ <a class="message" href="#SCI_STYLEGETCHARACTERSET">SCI_STYLEGETCHARACTERSET(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETCASE">SCI_STYLESETCASE(int styleNumber, int
+ caseMode)</a><br />
+ <a class="message" href="#SCI_STYLEGETCASE">SCI_STYLEGETCASE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETVISIBLE">SCI_STYLESETVISIBLE(int styleNumber, bool
+ visible)</a><br />
+ <a class="message" href="#SCI_STYLEGETVISIBLE">SCI_STYLEGETVISIBLE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETCHANGEABLE">SCI_STYLESETCHANGEABLE(int styleNumber, bool
+ changeable)</a><br />
+ <a class="message" href="#SCI_STYLEGETCHANGEABLE">SCI_STYLEGETCHANGEABLE(int styleNumber)</a><br />
+ <a class="message" href="#SCI_STYLESETHOTSPOT">SCI_STYLESETHOTSPOT(int styleNumber, bool
+ hotspot)</a><br />
+ <a class="message" href="#SCI_STYLEGETHOTSPOT">SCI_STYLEGETHOTSPOT(int styleNumber)</a><br />
+ </code>
+
+ <p><b id="SCI_STYLERESETDEFAULT">SCI_STYLERESETDEFAULT</b><br />
+ This message resets <code>STYLE_DEFAULT</code> to its state when Scintilla was
+ initialised.</p>
+
+ <p><b id="SCI_STYLECLEARALL">SCI_STYLECLEARALL</b><br />
+ This message sets all styles to have the same attributes as <code>STYLE_DEFAULT</code>. If you
+ are setting up Scintilla for syntax colouring, it is likely that the lexical styles you set
+ will be very similar. One way to set the styles is to:<br />
+ 1. Set <code>STYLE_DEFAULT</code> to the common features of all styles.<br />
+ 2. Use <code>SCI_STYLECLEARALL</code> to copy this to all styles.<br />
+ 3. Set the style attributes that make your lexical styles different.</p>
+
+ <p><b id="SCI_STYLESETFONT">SCI_STYLESETFONT(int styleNumber, const char *fontName)</b><br />
+ <b id="SCI_STYLEGETFONT">SCI_STYLEGETFONT(int styleNumber, char *fontName)</b><br />
+ <b id="SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)</b><br />
+ <b id="SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</b><br />
+ <b id="SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool bold)</b><br />
+ <b id="SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</b><br />
+ <b id="SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool italic)</b><br />
+ <b id="SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</b><br />
+ These messages (plus <a class="message"
+ href="#SCI_STYLESETCHARACTERSET"><code>SCI_STYLESETCHARACTERSET</code></a>) set the font
+ attributes that are used to match the fonts you request to those available. The
+ <code>fontName</code> is a zero terminated string holding the name of a font. Under Windows,
+ only the first 32 characters of the name are used and the name is not case sensitive. For
+ internal caching, Scintilla tracks fonts by name and does care about the casing of font names,
+ so please be consistent. On GTK+ 2.x, either GDK or Pango can be used to display text.
+ Pango antialiases text, works well with Unicode and is better supported in recent versions of GTK+
+ but GDK is faster.
+ Prepend a '!' character to the font name to use Pango.</p>
+
+ <p><b id="SCI_STYLESETUNDERLINE">SCI_STYLESETUNDERLINE(int styleNumber, bool
+ underline)</b><br />
+ <b id="SCI_STYLEGETUNDERLINE">SCI_STYLEGETUNDERLINE(int styleNumber)</b><br />
+ You can set a style to be underlined. The underline is drawn in the foreground colour. All
+ characters with a style that includes the underline attribute are underlined, even if they are
+ white space.</p>
+
+ <p><b id="SCI_STYLESETFORE">SCI_STYLESETFORE(int styleNumber, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_STYLEGETFORE">SCI_STYLEGETFORE(int styleNumber)</b><br />
+ <b id="SCI_STYLESETBACK">SCI_STYLESETBACK(int styleNumber, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_STYLEGETBACK">SCI_STYLEGETBACK(int styleNumber)</b><br />
+ Text is drawn in the foreground colour. The space in each character cell that is not occupied
+ by the character is drawn in the background colour.</p>
+
+ <p><b id="SCI_STYLESETEOLFILLED">SCI_STYLESETEOLFILLED(int styleNumber, bool
+ eolFilled)</b><br />
+ <b id="SCI_STYLEGETEOLFILLED">SCI_STYLEGETEOLFILLED(int styleNumber)</b><br />
+ If the last character in the line has a style with this attribute set, the remainder of the
+ line up to the right edge of the window is filled with the background colour set for the last
+ character. This is useful when a document contains embedded sections in another language such
+ as HTML pages with embedded JavaScript. By setting <code>eolFilled</code> to <code>true</code>
+ and a consistent background colour (different from the background colour set for the HTML
+ styles) to all JavaScript styles then JavaScript sections will be easily distinguished from
+ HTML.</p>
+
+ <p><b id="SCI_STYLESETCHARACTERSET">SCI_STYLESETCHARACTERSET(int styleNumber, int
+ charSet)</b><br />
+ <b id="SCI_STYLEGETCHARACTERSET">SCI_STYLEGETCHARACTERSET(int styleNumber)</b><br />
+ You can set a style to use a different character set than the default. The places where such
+ characters sets are likely to be useful are comments and literal strings. For example,
+ <code>SCI_STYLESETCHARACTERSET(SCE_C_STRING, SC_CHARSET_RUSSIAN)</code> would ensure that
+ strings in Russian would display correctly in C and C++ (<code>SCE_C_STRING</code> is the style
+ number used by the C and C++ lexer to display literal strings; it has the value 6). This
+ feature works differently on Windows and GTK+.</p>
+
+ <p>The character sets supported on Windows are:<br />
+ <code>SC_CHARSET_ANSI</code>, <code>SC_CHARSET_ARABIC</code>, <code>SC_CHARSET_BALTIC</code>,
+ <code>SC_CHARSET_CHINESEBIG5</code>, <code>SC_CHARSET_DEFAULT</code>,
+ <code>SC_CHARSET_EASTEUROPE</code>, <code>SC_CHARSET_GB2312</code>,
+ <code>SC_CHARSET_GREEK</code>, <code>SC_CHARSET_HANGUL</code>, <code>SC_CHARSET_HEBREW</code>,
+ <code>SC_CHARSET_JOHAB</code>, <code>SC_CHARSET_MAC</code>, <code>SC_CHARSET_OEM</code>,
+ <code>SC_CHARSET_RUSSIAN</code> (code page 1251),
+ <code>SC_CHARSET_SHIFTJIS</code>, <code>SC_CHARSET_SYMBOL</code>, <code>SC_CHARSET_THAI</code>,
+ <code>SC_CHARSET_TURKISH</code>, and <code>SC_CHARSET_VIETNAMESE</code>.</p>
+
+ <p>The character sets supported on GTK+ are:<br />
+ <code>SC_CHARSET_ANSI</code>, <code>SC_CHARSET_CYRILLIC</code> (code page 1251),
+ <code>SC_CHARSET_EASTEUROPE</code>,
+ <code>SC_CHARSET_GB2312</code>, <code>SC_CHARSET_HANGUL</code>,
+ <code>SC_CHARSET_RUSSIAN</code> (KOI8-R), <code>SC_CHARSET_SHIFTJIS</code>, and
+ <code>SC_CHARSET_8859_15</code>.</p>
+
+ <p><b id="SCI_STYLESETCASE">SCI_STYLESETCASE(int styleNumber, int caseMode)</b><br />
+ <b id="SCI_STYLEGETCASE">SCI_STYLEGETCASE(int styleNumber)</b><br />
+ The value of caseMode determines how text is displayed. You can set upper case
+ (<code>SC_CASE_UPPER</code>, 1) or lower case (<code>SC_CASE_LOWER</code>, 2) or display
+ normally (<code>SC_CASE_MIXED</code>, 0). This does not change the stored text, only how it is
+ displayed.</p>
+
+ <p><b id="SCI_STYLESETVISIBLE">SCI_STYLESETVISIBLE(int styleNumber, bool visible)</b><br />
+ <b id="SCI_STYLEGETVISIBLE">SCI_STYLEGETVISIBLE(int styleNumber)</b><br />
+ Text is normally visible. However, you can completely hide it by giving it a style with the
+ <code>visible</code> set to 0. This could be used to hide embedded formatting instructions or
+ hypertext keywords in HTML or XML.</p>
+
+ <p><b id="SCI_STYLESETCHANGEABLE">SCI_STYLESETCHANGEABLE(int styleNumber, bool
+ changeable)</b><br />
+ <b id="SCI_STYLEGETCHANGEABLE">SCI_STYLEGETCHANGEABLE(int styleNumber)</b><br />
+ This is an experimental and incompletely implemented style attribute. The default setting is
+ <code>changeable</code> set <code>true</code> but when set <code>false</code> it makes text
+ read-only. Currently it only stops the caret from being within not-changeable text and does not
+ yet stop deleting a range that contains not-changeable text.</p>
+
+ <p><b id="SCI_STYLESETHOTSPOT">SCI_STYLESETHOTSPOT(int styleNumber, bool
+ hotspot)</b><br />
+ <b id="SCI_STYLEGETHOTSPOT">SCI_STYLEGETHOTSPOT(int styleNumber)</b><br />
+ This style is used to mark ranges of text that can detect mouse clicks.
+ The cursor changes to a hand over hotspots, and the foreground, and background colours
+ may change and an underline appear to indicate that these areas are sensitive to clicking.
+ This may be used to allow hyperlinks to other documents.</p>
+
+ <h2 id="CaretAndSelectionStyles">Caret, selection, and hotspot styles</h2>
+
+ <p>The selection is shown by changing the foreground and/or background colours. If one of these
+ is not set then that attribute is not changed for the selection. The default is to show the
+ selection by changing the background to light gray and leaving the foreground the same as when
+ it was not selected. When there is no selection, the current insertion point is marked by the
+ text caret. This is a vertical line that is normally blinking on and off to attract the users
+ attention.</p>
+ <code><a class="message" href="#SCI_SETSELFORE">SCI_SETSELFORE(bool useSelectionForeColour,
+ int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_SETSELBACK">SCI_SETSELBACK(bool useSelectionBackColour,
+ int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_SETSELALPHA">SCI_SETSELALPHA(int alpha)</a><br />
+ <a class="message" href="#SCI_GETSELALPHA">SCI_GETSELALPHA</a><br />
+ <a class="message" href="#SCI_SETSELEOLFILLED">SCI_SETSELEOLFILLED(bool filled)</a><br />
+ <a class="message" href="#SCI_GETSELEOLFILLED">SCI_GETSELEOLFILLED</a><br />
+ <a class="message" href="#SCI_SETCARETFORE">SCI_SETCARETFORE(int colour)</a><br />
+ <a class="message" href="#SCI_GETCARETFORE">SCI_GETCARETFORE</a><br />
+ <a class="message" href="#SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool
+ show)</a><br />
+ <a class="message" href="#SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE</a><br />
+ <a class="message" href="#SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(int colour)</a><br />
+ <a class="message" href="#SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK</a><br />
+ <a class="message" href="#SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(int alpha)</a><br />
+ <a class="message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA</a><br />
+ <a class="message" href="#SCI_SETCARETPERIOD">SCI_SETCARETPERIOD(int milliseconds)</a><br />
+ <a class="message" href="#SCI_GETCARETPERIOD">SCI_GETCARETPERIOD</a><br />
+ <a class="message" href="#SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</a><br />
+ <a class="message" href="#SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</a><br />
+ <a class="message" href="#SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</a><br />
+ <a class="message" href="#SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</a><br />
+ <a class="message" href="#SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useSetting,
+ int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_GETHOTSPOTACTIVEFORE">SCI_GETHOTSPOTACTIVEFORE</a><br />
+ <a class="message" href="#SCI_SETHOTSPOTACTIVEBACK">SCI_SETHOTSPOTACTIVEBACK(bool useSetting,
+ int <a class="jump" href="#colour">colour<a>)</a><br />
+ <a class="message" href="#SCI_GETHOTSPOTACTIVEBACK">SCI_GETHOTSPOTACTIVEBACK</a><br />
+ <a class="message" href="#SCI_SETHOTSPOTACTIVEUNDERLINE">SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)</a><br />
+ <a class="message" href="#SCI_GETHOTSPOTACTIVEUNDERLINE">SCI_GETHOTSPOTACTIVEUNDERLINE</a><br />
+ <a class="message" href="#SCI_SETHOTSPOTSINGLELINE">SCI_SETHOTSPOTSINGLELINE(bool singleLine)</a><br />
+ <a class="message" href="#SCI_GETHOTSPOTSINGLELINE">SCI_GETHOTSPOTSINGLELINE</a><br />
+ <a class="message" href="#SCI_SETCONTROLCHARSYMBOL">SCI_SETCONTROLCHARSYMBOL(int
+ symbol)</a><br />
+ <a class="message" href="#SCI_GETCONTROLCHARSYMBOL">SCI_GETCONTROLCHARSYMBOL</a><br />
+ <a class="message" href="#SCI_SETCARETSTICKY">SCI_SETCARETSTICKY(bool useCaretStickyBehaviour)</a><br />
+ <a class="message" href="#SCI_GETCARETSTICKY">SCI_GETCARETSTICKY</a><br />
+ <a class="message" href="#SCI_TOGGLECARETSTICKY">SCI_TOGGLECARETSTICKY</a><br />
+ </code>
+
+ <p><b id="SCI_SETSELFORE">SCI_SETSELFORE(bool useSelectionForeColour, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_SETSELBACK">SCI_SETSELBACK(bool useSelectionBackColour, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ You can choose to override the default selection colouring with these two messages. The colour
+ you provide is used if you set <code>useSelection*Colour</code> to <code>true</code>. If it is
+ set to <code>false</code>, the default styled colouring is used and the <code>colour</code>
+ argument has no effect.</p>
+ <p><b id="SCI_SETSELALPHA">SCI_SETSELALPHA(int <a class="jump" href="#alpha">alpha</a>)</b><br />
+ <b id="SCI_GETSELALPHA">SCI_GETSELALPHA</b><br />
+ The selection can be drawn translucently in the selection background colour by
+ setting an alpha value.</p>
+
+ <p><b id="SCI_SETSELEOLFILLED">SCI_SETSELEOLFILLED(bool filled)</b><br />
+ <b id="SCI_GETSELEOLFILLED">SCI_GETSELEOLFILLED</b><br />
+ The selection can be drawn up to the right hand border by setting this property.</p>
+
+ <p><b id="SCI_SETCARETFORE">SCI_SETCARETFORE(int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETCARETFORE">SCI_GETCARETFORE</b><br />
+ The colour of the caret can be set with <code>SCI_SETCARETFORE</code> and retrieved with
+ <code>SCI_GETCARETFORE</code>.</p>
+
+ <p><b id="SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</b><br />
+ <b id="SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE</b><br />
+ <b id="SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK</b><br />
+ <b id="SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(int <a class="jump" href="#alpha">alpha</a>)</b><br />
+ <b id="SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA</b><br />
+ You can choose to make the background colour of the line containing the caret different with
+ these messages. To do this, set the desired background colour with
+ <code>SCI_SETCARETLINEBACK</code>, then use <code>SCI_SETCARETLINEVISIBLE(true)</code> to
+ enable the effect. You can cancel the effect with <code>SCI_SETCARETLINEVISIBLE(false)</code>.
+ The two <code>SCI_GETCARET*</code> functions return the state and the colour. This form of
+ background colouring has highest priority when a line has markers that would otherwise change
+ the background colour.
+ The caret line may also be drawn translucently which allows other background colours to show
+ through. This is done by setting the alpha (translucency) value by calling
+ SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA,
+ the caret line is drawn after all other features so will affect the colour of all other features.
+ </p>
+
+ <p><b id="SCI_SETCARETPERIOD">SCI_SETCARETPERIOD(int milliseconds)</b><br />
+ <b id="SCI_GETCARETPERIOD">SCI_GETCARETPERIOD</b><br />
+ The rate at which the caret blinks can be set with <code>SCI_SETCARETPERIOD</code> which
+ determines the time in milliseconds that the caret is visible or invisible before changing
+ state. Setting the period to 0 stops the caret blinking. The default value is 500 milliseconds.
+ <code>SCI_GETCARETPERIOD</code> returns the current setting.</p>
+
+ <p><b id="SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</b><br />
+ <b id="SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</b><br />
+ The style of the caret can be set with <code>SCI_SETCARETSTYLE</code> to be a line caret
+ (CARETSTYLE_LINE=1), a block caret (CARETSTYLE_BLOCK=2) or to not draw at all
+ (CARETSTYLE_INVISIBLE=0). The default value is the line caret (CARETSTYLE_LINE=1).
+ You can determine the current caret style setting using <code>SCI_GETCARETSTYLE</code>.</p>
+
+ <p>The block character draws most combining and multibyte character sequences successfully,
+ though some fonts like Thai Fonts (and possibly others) can sometimes appear strange when
+ the cursor is positioned at these characters, which may result in only drawing a part of the
+ cursor character sequence. This is most notable on Windows platforms.</p>
+
+ <p><b id="SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</b><br />
+ <b id="SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</b><br />
+ The width of the line caret can be set with <code>SCI_SETCARETWIDTH</code> to a value of
+ 0, 1, 2 or 3 pixels. The default width is 1 pixel. You can read back the current width with
+ <code>SCI_GETCARETWIDTH</code>. A width of 0 makes the caret invisible (added at version
+ 1.50), similar to setting the caret style to CARETSTYLE_INVISIBLE (though not interchangable).
+ This setting only affects the width of the cursor when the cursor style is set to line caret
+ mode, it does not affect the width for a block caret.</p>
+
+ <p><b id="SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useHotSpotForeColour, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETHOTSPOTACTIVEFORE">SCI_GETHOTSPOTACTIVEFORE</b><br />
+ <b id="SCI_SETHOTSPOTACTIVEBACK">SCI_SETHOTSPOTACTIVEBACK(bool useHotSpotBackColour, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETHOTSPOTACTIVEBACK">SCI_GETHOTSPOTACTIVEBACK</b><br />
+ <b id="SCI_SETHOTSPOTACTIVEUNDERLINE">SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)</b><br />
+ <b id="SCI_GETHOTSPOTACTIVEUNDERLINE">SCI_GETHOTSPOTACTIVEUNDERLINE</b><br />
+ <b id="SCI_SETHOTSPOTSINGLELINE">SCI_SETHOTSPOTSINGLELINE(bool singleLine)</b><br />
+ <b id="SCI_GETHOTSPOTSINGLELINE">SCI_GETHOTSPOTSINGLELINE</b><br />
+ While the cursor hovers over text in a style with the hotspot attribute set,
+ the default colouring can be modified and an underline drawn with these settings.
+ Single line mode stops a hotspot from wrapping onto next line.</p>
+
+ <p><b id="SCI_SETCONTROLCHARSYMBOL">SCI_SETCONTROLCHARSYMBOL(int symbol)</b><br />
+ <b id="SCI_GETCONTROLCHARSYMBOL">SCI_GETCONTROLCHARSYMBOL</b><br />
+ By default, Scintilla displays control characters (characters with codes less than 32) in a
+ rounded rectangle as ASCII mnemonics: "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK",
+ "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US". These mnemonics come from the
+ early days of signaling, though some are still used (LF = Line Feed, BS = Back Space, CR =
+ Carriage Return, for example).</p>
+
+ <p>You can choose to replace these mnemonics by a nominated symbol with an ASCII code in the
+ range 32 to 255. If you set a symbol value less than 32, all control characters are displayed
+ as mnemonics. The symbol you set is rendered in the font of the style set for the character.
+ You can read back the current symbol with the <code>SCI_GETCONTROLCHARSYMBOL</code> message.
+ The default symbol value is 0.</p>
+
+ <p><b id="SCI_SETCARETSTICKY">SCI_SETCARETSTICKY(bool useCaretStickyBehaviour)</b><br />
+ <b id="SCI_GETCARETSTICKY">SCI_GETCARETSTICKY</b><br />
+ <b id="SCI_TOGGLECARETSTICKY">SCI_TOGGLECARETSTICKY</b><br />
+ These messages set, get or toggle the caretSticky flag which controls when the last position
+ of the caret on the line is saved. When set to true, the position is not saved when you type
+ a character, a tab, paste the clipboard content or press backspace.</p>
+
+ <h2 id="Margins">Margins</h2>
+
+ <p>There may be up to five margins to the left of the text display, plus a gap either side of
+ the text. Each margin can be set to display either symbols or line numbers with <a
+ class="message" href="#SCI_SETMARGINTYPEN"><code>SCI_SETMARGINTYPEN</code></a>. The markers
+ that can be displayed in each margin are set with <a class="message"
+ href="#SCI_SETMARGINMASKN"><code>SCI_SETMARGINMASKN</code></a>. Any markers not associated with
+ a visible margin will be displayed as changes in background colour in the text. A width in
+ pixels can be set for each margin. Margins with a zero width are ignored completely. You can
+ choose if a mouse click in a margin sends a <a class="message"
+ href="#SCN_MARGINCLICK"><code>SCN_MARGINCLICK</code></a> notification to the container or
+ selects a line of text.</p>
+
+ <p>The margins are numbered 0 to 4. Using a margin number outside the valid range has no
+ effect. By default, margin 0 is set to display line numbers, but is given a width of 0, so it
+ is hidden. Margin 1 is set to display non-folding symbols and is given a width of 16 pixels, so
+ it is visible. Margin 2 is set to display the folding symbols, but is given a width of 0, so it
+ is hidden. Of course, you can set the margins to be whatever you wish.</p>
+
+ <p>Styled text margins used to show revision and blame information:</p>
+ <p><img src="styledmargin.png" alt="Styled text margins used to show revision and blame information" /></p>
+
+ <code><a class="message" href="#SCI_SETMARGINTYPEN">SCI_SETMARGINTYPEN(int margin, int
+ type)</a><br />
+ <a class="message" href="#SCI_GETMARGINTYPEN">SCI_GETMARGINTYPEN(int margin)</a><br />
+ <a class="message" href="#SCI_SETMARGINWIDTHN">SCI_SETMARGINWIDTHN(int margin, int
+ pixelWidth)</a><br />
+ <a class="message" href="#SCI_GETMARGINWIDTHN">SCI_GETMARGINWIDTHN(int margin)</a><br />
+ <a class="message" href="#SCI_SETMARGINMASKN">SCI_SETMARGINMASKN(int margin, int
+ mask)</a><br />
+ <a class="message" href="#SCI_GETMARGINMASKN">SCI_GETMARGINMASKN(int margin)</a><br />
+ <a class="message" href="#SCI_SETMARGINSENSITIVEN">SCI_SETMARGINSENSITIVEN(int margin, bool
+ sensitive)</a><br />
+ <a class="message" href="#SCI_GETMARGINSENSITIVEN">SCI_GETMARGINSENSITIVEN(int
+ margin)</a><br />
+ <a class="message" href="#SCI_SETMARGINLEFT">SCI_SETMARGINLEFT(&lt;unused&gt;, int
+ pixels)</a><br />
+ <a class="message" href="#SCI_GETMARGINLEFT">SCI_GETMARGINLEFT</a><br />
+ <a class="message" href="#SCI_SETMARGINRIGHT">SCI_SETMARGINRIGHT(&lt;unused&gt;, int
+ pixels)</a><br />
+ <a class="message" href="#SCI_GETMARGINRIGHT">SCI_GETMARGINRIGHT</a><br />
+ <a class="message" href="#SCI_SETFOLDMARGINCOLOUR">SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)</a><br />
+ <a class="message" href="#SCI_SETFOLDMARGINHICOLOUR">SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)</a><br />
+ <a class="message" href="#SCI_MARGINSETTEXT">SCI_MARGINSETTEXT(int line, char *text)</a><br />
+ <a class="message" href="#SCI_MARGINGETTEXT">SCI_MARGINGETTEXT(int line, char *text)</a><br />
+ <a class="message" href="#SCI_MARGINSETSTYLE">SCI_MARGINSETSTYLE(int line, int style)</a><br />
+ <a class="message" href="#SCI_MARGINGETSTYLE">SCI_MARGINGETSTYLE(int line)</a><br />
+ <a class="message" href="#SCI_MARGINSETSTYLES">SCI_MARGINSETSTYLES(int line, char *styles)</a><br />
+ <a class="message" href="#SCI_MARGINGETSTYLES">SCI_MARGINGETSTYLES(int line, char *styles)</a><br />
+ <a class="message" href="#SCI_MARGINTEXTCLEARALL">SCI_MARGINTEXTCLEARALL</a><br />
+ <a class="message" href="#SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET(int style)</a><br />
+ <a class="message" href="#SCI_MARGINGETSTYLEOFFSET">SCI_MARGINGETSTYLEOFFSET</a><br />
+ </code>
+
+ <p><b id="SCI_SETMARGINTYPEN">SCI_SETMARGINTYPEN(int margin, int iType)</b><br />
+ <b id="SCI_GETMARGINTYPEN">SCI_GETMARGINTYPEN(int margin)</b><br />
+ These two routines set and get the type of a margin. The margin argument should be 0, 1, 2, 3 or 4.
+ You can use the predefined constants <code>SC_MARGIN_SYMBOL</code> (0) and
+ <code>SC_MARGIN_NUMBER</code> (1) to set a margin as either a line number or a symbol margin.
+ A margin with application defined text may use <code>SC_MARGIN_TEXT</code> (4) or
+ <code>SC_MARGIN_RTEXT</code> (5) to right justify the text.
+ By convention, margin 0 is used for line numbers and the next two are used for symbols. You can
+ also use the constants <code>SC_MARGIN_BACK</code> (2) and <code>SC_MARGIN_FORE</code> (3) for
+ symbol margins that set their background colour to match the STYLE_DEFAULT background and
+ foreground colours.</p>
+
+ <p><b id="SCI_SETMARGINWIDTHN">SCI_SETMARGINWIDTHN(int margin, int pixelWidth)</b><br />
+ <b id="SCI_GETMARGINWIDTHN">SCI_GETMARGINWIDTHN(int margin)</b><br />
+ These routines set and get the width of a margin in pixels. A margin with zero width is
+ invisible. By default, Scintilla sets margin 1 for symbols with a width of 16 pixels, so this
+ is a reasonable guess if you are not sure what would be appropriate. Line number margins widths
+ should take into account the number of lines in the document and the line number style. You
+ could use something like <a class="message"
+ href="#SCI_TEXTWIDTH"><code>SCI_TEXTWIDTH(STYLE_LINENUMBER, "_99999")</code></a> to get a
+ suitable width.</p>
+
+ <p><b id="SCI_SETMARGINMASKN">SCI_SETMARGINMASKN(int margin, int mask)</b><br />
+ <b id="SCI_GETMARGINMASKN">SCI_GETMARGINMASKN(int margin)</b><br />
+ The mask is a 32-bit value. Each bit corresponds to one of 32 logical symbols that can be
+ displayed in a margin that is enabled for symbols. There is a useful constant,
+ <code>SC_MASK_FOLDERS</code> (0xFE000000 or -33554432), that is a mask for the 7 logical
+ symbols used to denote folding. You can assign a wide range of symbols and colours to each of
+ the 32 logical symbols, see <a href="#Markers">Markers</a> for more information. If <code>(mask
+ &amp; SC_MASK_FOLDERS)==0</code>, the margin background colour is controlled by style 33 (<a
+ class="message" href="#StyleDefinition"><code>STYLE_LINENUMBER</code></a>).</p>
+
+ <p>You add logical markers to a line with <a class="message"
+ href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. If a line has an associated marker that
+ does not appear in the mask of any margin with a non-zero width, the marker changes the
+ background colour of the line. For example, suppose you decide to use logical marker 10 to mark
+ lines with a syntax error and you want to show such lines by changing the background colour.
+ The mask for this marker is 1 shifted left 10 times (1&lt;&lt;10) which is 0x400. If you make
+ sure that no symbol margin includes 0x400 in its mask, any line with the marker gets the
+ background colour changed.</p>
+
+ <p>To set a non-folding margin 1 use <code>SCI_SETMARGINMASKN(1, ~SC_MASK_FOLDERS)</code>; to
+ set a folding margin 2 use <code>SCI_SETMARGINMASKN(2, SC_MASK_FOLDERS)</code>. This is the
+ default set by Scintilla. <code>~SC_MASK_FOLDERS</code> is 0x1FFFFFF in hexadecimal or 33554431
+ decimal. Of course, you may need to display all 32 symbols in a margin, in which case use
+ <code>SCI_SETMARGINMASKN(margin, -1)</code>.</p>
+
+ <p><b id="SCI_SETMARGINSENSITIVEN">SCI_SETMARGINSENSITIVEN(int margin, bool
+ sensitive)</b><br />
+ <b id="SCI_GETMARGINSENSITIVEN">SCI_GETMARGINSENSITIVEN(int margin)</b><br />
+ Each of the five margins can be set sensitive or insensitive to mouse clicks. A click in a
+ sensitive margin sends a <a class="message"
+ href="#SCN_MARGINCLICK"><code>SCN_MARGINCLICK</code></a> <a class="jump"
+ href="#Notifications">notification</a> to the container. Margins that are not sensitive act as
+ selection margins which make it easy to select ranges of lines. By default, all margins are
+ insensitive.</p>
+
+ <p><b id="SCI_SETMARGINLEFT">SCI_SETMARGINLEFT(&lt;unused&gt;, int pixels)</b><br />
+ <b id="SCI_GETMARGINLEFT">SCI_GETMARGINLEFT</b><br />
+ <b id="SCI_SETMARGINRIGHT">SCI_SETMARGINRIGHT(&lt;unused&gt;, int pixels)</b><br />
+ <b id="SCI_GETMARGINRIGHT">SCI_GETMARGINRIGHT</b><br />
+ These messages set and get the width of the blank margin on both sides of the text in pixels.
+ The default is to one pixel on each side.</p>
+
+ <p><b id="SCI_SETFOLDMARGINCOLOUR">SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)</b><br />
+ <b id="SCI_SETFOLDMARGINHICOLOUR">SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)</b><br />
+ These messages allow changing the colour of the fold margin and fold margin highlight.
+ On Windows the fold margin colour defaults to ::GetSysColor(COLOR_3DFACE) and the fold margin highlight
+ colour to ::GetSysColor(COLOR_3DHIGHLIGHT).</p>
+
+ <p>
+ <b id="SCI_MARGINSETTEXT">SCI_MARGINSETTEXT(int line, char *text)</b><br />
+ <b id="SCI_MARGINGETTEXT">SCI_MARGINGETTEXT(int line, char *text)</b><br />
+ <b id="SCI_MARGINSETSTYLE">SCI_MARGINSETSTYLE(int line, int style)</b><br />
+ <b id="SCI_MARGINGETSTYLE">SCI_MARGINGETSTYLE(int line)</b><br />
+ <b id="SCI_MARGINSETSTYLES">SCI_MARGINSETSTYLES(int line, char *styles)</b><br />
+ <b id="SCI_MARGINGETSTYLES">SCI_MARGINGETSTYLES(int line, char *styles)</b><br />
+ <b id="SCI_MARGINTEXTCLEARALL">SCI_MARGINTEXTCLEARALL</b><br />
+ Text margins are created with the type SC_MARGIN_TEXT or SC_MARGIN_RTEXT.
+ A different string may be set for each line with <code>SCI_MARGINSETTEXT</code>.
+ The whole of the text margin on a line may be displayed in a particular style with
+ <code>SCI_MARGINSETSTYLE</code> or each character may be individually styled with
+ <code>SCI_MARGINSETSTYLES</code> which uses an array of bytes with each byte setting the style
+ of the corresponding text byte similar to <code>SCI_SETSTYLINGEX</code>.
+ Setting a text margin will cause a
+ <a class="message" href="#SC_MOD_CHANGEMARGIN"><code>SC_MOD_CHANGEMARGIN</code></a>
+ notification to be sent.
+ </p>
+ <p>
+ <b id="SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET(int style)</b><br />
+ <b id="SCI_MARGINGETSTYLEOFFSET">SCI_MARGINGETSTYLEOFFSET</b><br />
+ Margin styles may be completely separated from standard text styles by setting a style offset. For example,
+ <code>SCI_MARGINSETSTYLEOFFSET(256)</code> would allow the margin styles to be numbered from
+ 256 upto 511 so they do not overlap styles set by lexers. Each style number set with <code>SCI_MARGINSETSTYLE</code>
+ or <code>SCI_MARGINSETSTYLES</code> has the offset added before looking up the style.
+ </p>
+
+ <h2 id="Annotations">Annotations</h2>
+
+ <p>Annotations are read-only lines of text underneath each line of editable text.
+ An annotation may consist of multiple lines separated by '\n'.
+ Annotations can be used to display an assembler version of code for debugging or to show diagnostic messages inline or to
+ line up different versions of text in a merge tool.</p>
+ <p>Annotations used for inline diagnostics:</p>
+ <p><img src="annotations.png" alt="Annotations used for inline diagnostics" /></p>
+
+ <code>
+ <a class="message" href="#SCI_ANNOTATIONSETTEXT">SCI_ANNOTATIONSETTEXT(int line, char *text)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETTEXT">SCI_ANNOTATIONGETTEXT(int line, char *text)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONSETSTYLE">SCI_ANNOTATIONSETSTYLE(int line, int style)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETSTYLE">SCI_ANNOTATIONGETSTYLE(int line)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONSETSTYLES">SCI_ANNOTATIONSETSTYLES(int line, char *styles)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETSTYLES">SCI_ANNOTATIONGETSTYLES(int line, char *styles)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETLINES">SCI_ANNOTATIONGETLINES(int line)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONCLEARALL">SCI_ANNOTATIONCLEARALL</a><br />
+ <a class="message" href="#SCI_ANNOTATIONSETVISIBLE">SCI_ANNOTATIONSETVISIBLE(int visible)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETVISIBLE">SCI_ANNOTATIONGETVISIBLE</a><br />
+ <a class="message" href="#SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET(int style)</a><br />
+ <a class="message" href="#SCI_ANNOTATIONGETSTYLEOFFSET">SCI_ANNOTATIONGETSTYLEOFFSET</a><br />
+ </code>
+
+ <p>
+ <b id="SCI_ANNOTATIONSETTEXT">SCI_ANNOTATIONSETTEXT(int line, char *text)</b><br />
+ <b id="SCI_ANNOTATIONGETTEXT">SCI_ANNOTATIONGETTEXT(int line, char *text)</b><br />
+ <b id="SCI_ANNOTATIONSETSTYLE">SCI_ANNOTATIONSETSTYLE(int line, int style)</b><br />
+ <b id="SCI_ANNOTATIONGETSTYLE">SCI_ANNOTATIONGETSTYLE(int line)</b><br />
+ <b id="SCI_ANNOTATIONSETSTYLES">SCI_ANNOTATIONSETSTYLES(int line, char *styles)</b><br />
+ <b id="SCI_ANNOTATIONGETSTYLES">SCI_ANNOTATIONGETSTYLES(int line, char *styles)</b><br />
+ <b id="SCI_ANNOTATIONGETLINES">SCI_ANNOTATIONGETLINES(int line)</b><br />
+ <b id="SCI_ANNOTATIONCLEARALL">SCI_ANNOTATIONCLEARALL</b><br />
+ A different string may be set for each line with <code>SCI_ANNOTATIONSETTEXT</code>.
+ To clear annotations call <code>SCI_ANNOTATIONSETTEXT</code> with a NULL pointer.
+ The whole of the text ANNOTATION on a line may be displayed in a particular style with
+ <code>SCI_ANNOTATIONSETSTYLE</code> or each character may be individually styled with
+ <code>SCI_ANNOTATIONSETSTYLES</code> which uses an array of bytes with each byte setting the style
+ of the corresponding text byte similar to <code>SCI_SETSTYLINGEX</code>. The text must be set first as it
+ specifies how long the annotation is so how many bytes of styling to read.
+ Setting an annotation will cause a
+ <a class="message" href="#SC_MOD_CHANGEANNOTATION"><code>SC_MOD_CHANGEANNOTATION</code></a>
+ notification to be sent.
+ </p>
+ <p>
+ The number of lines annotating a line can be retrieved with <code>SCI_ANNOTATIONGETLINES</code>.
+ All the lines can be cleared of annotations with <code>SCI_ANNOTATIONCLEARALL</code>
+ which is equivalent to clearing each line (setting to 0) and then deleting other memory used for this feature.
+ </p>
+ <p>
+ <b id="SCI_ANNOTATIONSETVISIBLE">SCI_ANNOTATIONSETVISIBLE(int visible)</b><br />
+ <b id="SCI_ANNOTATIONGETVISIBLE">SCI_ANNOTATIONGETVISIBLE</b><br />
+ Annotations can be made visible in a view and there is a choice of display style when visible.
+ The two messages set and get the annotation display mode. The <code>visible</code>
+ argument can be one of:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Annotation visibility">
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>ANNOTATION_HIDDEN</code></th>
+
+ <td>0</td>
+
+ <td>Annotations are not displayed.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>ANNOTATION_STANDARD</code></th>
+
+ <td>1</td>
+
+ <td>Annotations are drawn left justified with no adornment.</td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>ANNOTATION_BOXED</code></th>
+
+ <td>2</td>
+
+ <td>Annotations are indented to match the text and are surrounded by a box.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ </p>
+ <p>
+ <b id="SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET(int style)</b><br />
+ <b id="SCI_ANNOTATIONGETSTYLEOFFSET">SCI_ANNOTATIONGETSTYLEOFFSET</b><br />
+ Annotation styles may be completely separated from standard text styles by setting a style offset. For example,
+ <code>SCI_ANNOTATIONSETSTYLEOFFSET(512)</code> would allow the annotation styles to be numbered from
+ 512 upto 767 so they do not overlap styles set by lexers (or margins if margins offset is 256).
+ Each style number set with <code>SCI_ANNOTATIONSETSTYLE</code>
+ or <code>SCI_ANNOTATIONSETSTYLES</code> has the offset added before looking up the style.
+ </p>
+
+ <h2 id="OtherSettings">Other settings</h2>
+ <code><a class="message" href="#SCI_SETUSEPALETTE">SCI_SETUSEPALETTE(bool
+ allowPaletteUse)</a><br />
+ <a class="message" href="#SCI_GETUSEPALETTE">SCI_GETUSEPALETTE</a><br />
+ <a class="message" href="#SCI_SETBUFFEREDDRAW">SCI_SETBUFFEREDDRAW(bool isBuffered)</a><br />
+ <a class="message" href="#SCI_GETBUFFEREDDRAW">SCI_GETBUFFEREDDRAW</a><br />
+ <a class="message" href="#SCI_SETTWOPHASEDRAW">SCI_SETTWOPHASEDRAW(bool twoPhase)</a><br />
+ <a class="message" href="#SCI_GETTWOPHASEDRAW">SCI_GETTWOPHASEDRAW</a><br />
+ <a class="message" href="#SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</a><br />
+ <a class="message" href="#SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</a><br />
+ <a class="message" href="#SCI_SETCODEPAGE">SCI_SETCODEPAGE(int codePage)</a><br />
+ <a class="message" href="#SCI_GETCODEPAGE">SCI_GETCODEPAGE</a><br />
+ <a class="message" href="#SCI_SETKEYSUNICODE">SCI_SETKEYSUNICODE(bool keysUnicode)</a><br />
+ <a class="message" href="#SCI_GETKEYSUNICODE">SCI_GETKEYSUNICODE</a><br />
+ <a class="message" href="#SCI_SETWORDCHARS">SCI_SETWORDCHARS(&lt;unused&gt;, const char
+ *chars)</a><br />
+ <a class="message" href="#SCI_SETWHITESPACECHARS">SCI_SETWHITESPACECHARS(&lt;unused&gt;, const char
+ *chars)</a><br />
+ <a class="message" href="#SCI_SETCHARSDEFAULT">SCI_SETCHARSDEFAULT</a><br />
+ <a class="message" href="#SCI_GRABFOCUS">SCI_GRABFOCUS</a><br />
+ <a class="message" href="#SCI_SETFOCUS">SCI_SETFOCUS(bool focus)</a><br />
+ <a class="message" href="#SCI_GETFOCUS">SCI_GETFOCUS</a><br />
+ </code>
+
+ <p><b id="SCI_SETUSEPALETTE">SCI_SETUSEPALETTE(bool allowPaletteUse)</b><br />
+ <b id="SCI_GETUSEPALETTE">SCI_GETUSEPALETTE</b><br />
+ On 8 bit displays, which can only display a maximum of 256 colours, the graphics environment
+ mediates between the colour needs of applications through the use of palettes. On GTK+,
+ Scintilla always uses a palette.</p>
+
+ <p>On Windows, there are some problems with visual flashing when switching between applications
+ with palettes and it is also necessary for the application containing the Scintilla control to
+ forward some messages to Scintilla for its palette code to work. Because of this, by default,
+ the palette is not used and the application must tell Scintilla to use one. If Scintilla is not
+ using a palette, it will only display in those colours already available, which are often the
+ 20 Windows system colours.</p>
+
+ <p>To see an example of how to enable palette support in Scintilla, search the text of SciTE
+ for <code>WM_PALETTECHANGED</code>, <code>WM_QUERYNEWPALETTE</code> and
+ <code>SCI_SETUSEPALETTE</code>. The Windows messages to forward are:<br />
+ <code>WM_SYSCOLORCHANGE</code>, <code>WM_PALETTECHANGED</code>,
+ <code>WM_QUERYNEWPALETTE</code> (should return <code>TRUE</code>).</p>
+
+ <p>To forward a message <code>(WM_XXXX, WPARAM, LPARAM)</code> to Scintilla, you can use
+ <code>SendMessage(hScintilla, WM_XXXX, WPARAM, LPARAM)</code> where <code>hScintilla</code> is
+ the handle to the Scintilla window you created as your editor.</p>
+
+ <p>While we are on the subject of forwarding messages in Windows, the top level window should
+ forward any <code>WM_SETTINGCHANGE</code> messages to Scintilla (this is currently used to
+ collect changes to mouse settings, but could be used for other user interface items in the
+ future).</p>
+
+ <p><b id="SCI_SETBUFFEREDDRAW">SCI_SETBUFFEREDDRAW(bool isBuffered)</b><br />
+ <b id="SCI_GETBUFFEREDDRAW">SCI_GETBUFFEREDDRAW</b><br />
+ These messages turn buffered drawing on or off and report the buffered drawing state. Buffered
+ drawing draws each line into a bitmap rather than directly to the screen and then copies the
+ bitmap to the screen. This avoids flickering although it does take longer. The default is for
+ drawing to be buffered.</p>
+
+ <p><b id="SCI_SETTWOPHASEDRAW">SCI_SETTWOPHASEDRAW(bool twoPhase)</b><br />
+ <b id="SCI_GETTWOPHASEDRAW">SCI_GETTWOPHASEDRAW</b><br />
+ Two phase drawing is a better but slower way of drawing text.
+ In single phase drawing each run of characters in one style is drawn along with its background.
+ If a character overhangs the end of a run, such as in "<i>V</i>_" where the
+ "<i>V</i>" is in a different style from the "_", then this can cause the right hand
+ side of the "<i>V</i>" to be overdrawn by the background of the "_" which
+ cuts it off. Two phase drawing
+ fixes this by drawing all the backgrounds first and then drawing the text in
+ transparent mode. Two phase drawing may flicker more than single phase
+ unless buffered drawing is on. The default is for drawing to be two phase.</p>
+
+ <p><b id="SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</b><br />
+ <b id="SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</b><br />
+ Manage font quality (antialiasing method). Currently, the following values are available on Windows:
+ <code>SC_EFF_QUALITY_DEFAULT</code> (backward compatible),
+ <code>SC_EFF_QUALITY_NON_ANTIALIASED</code>,
+ <code>SC_EFF_QUALITY_ANTIALIASED</code>,
+ <code>SC_EFF_QUALITY_LCD_OPTIMIZED</code>.</p>
+ <p>In case it is necessary to squeeze more options into this property, only a limited number of bits defined
+ by SC_EFF_QUALITY_MASK (0xf) will be used for quality.</p>
+
+ <p><b id="SCI_SETCODEPAGE">SCI_SETCODEPAGE(int codePage)</b><br />
+ <b id="SCI_GETCODEPAGE">SCI_GETCODEPAGE</b><br />
+ Scintilla has some support for Japanese, Chinese and Korean DBCS. Use this message with
+ <code>codePage</code> set to the code page number to set Scintilla to use code page information
+ to ensure double byte characters are treated as one character rather than two. This also stops
+ the caret from moving between the two bytes in a double byte character.
+ Do not use this message to choose between different single byte character sets: it doesn't do that.
+ Call with
+ <code>codePage</code> set to zero to disable DBCS support. The default is
+ <code>SCI_SETCODEPAGE(0)</code>.</p>
+
+ <p>Code page <code>SC_CP_UTF8</code> (65001) sets Scintilla into Unicode mode with the document
+ treated as a sequence of characters expressed in UTF-8. The text is converted to the platform's
+ normal Unicode encoding before being drawn by the OS and thus can display Hebrew, Arabic,
+ Cyrillic, and Han characters. Languages which can use two characters stacked vertically in one
+ horizontal space, such as Thai, will mostly work but there are some issues where the characters
+ are drawn separately leading to visual glitches. Bi-directional text is not supported. </p>
+
+ <p>On Windows, code page can be set to 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK),
+ 949 (Korean Unified Hangul Code), 950 (Traditional Chinese Big5), or 1361 (Korean Johab)
+ although these may require installation of language specific support.</p>
+
+ <p>On GTK+, code page can be set to 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK),
+ or 950 (Traditional Chinese Big5).
+ The code page may also be set to <code>SC_CP_DBCS</code> (1)
+ which uses the current locale to handle multi byte characters which may work for otherwise unsupported
+ code pages.</p>
+
+ <p>For GTK+ 1.x, the locale should be set to a Unicode locale with a call similar to
+ <code>setlocale(LC_CTYPE, "en_US.UTF-8")</code>. Fonts with an <code>"iso10646"</code> registry
+ should be used in a font set. Font sets are a comma separated list of partial font
+ specifications where each partial font specification can be in the form:
+ <code>foundry-fontface-charsetregistry-encoding</code> or
+ <code>fontface-charsetregistry-encoding</code> or <code>foundry-fontface</code> or
+ <code>fontface</code>. An example is <code>"misc-fixed-iso10646-1,*"</code>.
+ On GTK+ 2.x, Pango fonts should be used rather than font sets.</p>
+
+ <p>Setting <code>codePage</code> to a non-zero value that is not <code>SC_CP_UTF8</code> is
+ operating system dependent.</p>
+
+ <p><b id="SCI_SETKEYSUNICODE">SCI_SETKEYSUNICODE(bool keysUnicode)</b><br />
+ <b id="SCI_GETKEYSUNICODE">SCI_GETKEYSUNICODE</b><br />
+ On Windows, character keys are normally handled differently depending on whether Scintilla is a wide
+ or narrow character window with character messages treated as Unicode when wide and as 8 bit otherwise.
+ Set this property to always treat as Unicode. This option is needed for Delphi.</p>
+
+ <p><b id="SCI_SETWORDCHARS">SCI_SETWORDCHARS(&lt;unused&gt;, const char *chars)</b><br />
+ Scintilla has several functions that operate on words, which are defined to be contiguous
+ sequences of characters from a particular set of characters. This message defines which
+ characters are members of that set. The character sets are set to default values before processing this
+ function.
+ For example, if you don't allow '_' in your set of characters
+ use:<br />
+ <code>SCI_SETWORDCHARS(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")</code>;</p>
+
+ <p><b id="SCI_SETWHITESPACECHARS">SCI_SETWHITESPACECHARS(&lt;unused&gt;, const char *chars)</b><br />
+ Similar to <code>SCI_SETWORDCHARS</code>, this message allows the user to define which chars Scintilla considers
+ as whitespace. Setting the whitespace chars allows the user to fine-tune Scintilla's behaviour doing
+ such things as moving the cursor to the start or end of a word; for example, by defining punctuation chars
+ as whitespace, they will be skipped over when the user presses ctrl+left or ctrl+right.
+ This function should be called after <code>SCI_SETWORDCHARS</code> as it will
+ reset the whitespace characters to the default set.</p>
+ <p><b id="SCI_SETCHARSDEFAULT">SCI_SETCHARSDEFAULT</b><br />
+ Use the default sets of word and whitespace characters. This sets whitespace to space, tab and other
+ characters with codes less than 0x20, with word characters set to alphanumeric and '_'.
+ </p>
+
+
+ <p><b id="SCI_GRABFOCUS">SCI_GRABFOCUS</b><br />
+ <b id="SCI_SETFOCUS">SCI_SETFOCUS(bool focus)</b><br />
+ <b id="SCI_GETFOCUS">SCI_GETFOCUS</b><br />
+ Scintilla can be told to grab the focus with this message. This is needed more on GTK+ where
+ focus handling is more complicated than on Windows.</p>
+
+ <p>The internal focus flag can be set with <code>SCI_SETFOCUS</code>. This is used by clients
+ that have complex focus requirements such as having their own window that gets the real focus
+ but with the need to indicate that Scintilla has the logical focus.</p>
+
+ <h2 id="BraceHighlighting">Brace highlighting</h2>
+ <code><a class="message" href="#SCI_BRACEHIGHLIGHT">SCI_BRACEHIGHLIGHT(int pos1, int
+ pos2)</a><br />
+ <a class="message" href="#SCI_BRACEBADLIGHT">SCI_BRACEBADLIGHT(int pos1)</a><br />
+ <a class="message" href="#SCI_BRACEMATCH">SCI_BRACEMATCH(int position, int
+ maxReStyle)</a><br />
+ </code>
+
+ <p><b id="SCI_BRACEHIGHLIGHT">SCI_BRACEHIGHLIGHT(int pos1, int pos2)</b><br />
+ Up to two characters can be highlighted in a 'brace highlighting style', which is defined as
+ style number <a class="message" href="#StyleDefinition"><code>STYLE_BRACELIGHT</code></a> (34).
+ If you have enabled indent guides, you may also wish to highlight the indent that corresponds
+ with the brace. You can locate the column with <a class="message"
+ href="#SCI_GETCOLUMN"><code>SCI_GETCOLUMN</code></a> and highlight the indent with <a
+ class="message" href="#SCI_SETHIGHLIGHTGUIDE"><code>SCI_SETHIGHLIGHTGUIDE</code></a>.</p>
+
+ <p><b id="SCI_BRACEBADLIGHT">SCI_BRACEBADLIGHT(int pos1)</b><br />
+ If there is no matching brace then the <a class="jump" href="#StyleDefinition">brace
+ badlighting style</a>, style <code>STYLE_BRACEBAD</code> (35), can be used to show the brace
+ that is unmatched. Using a position of <code>INVALID_POSITION</code> (-1) removes the
+ highlight.</p>
+
+ <p><b id="SCI_BRACEMATCH">SCI_BRACEMATCH(int pos, int maxReStyle)</b><br />
+ The <code>SCI_BRACEMATCH</code> message finds a corresponding matching brace given
+ <code>pos</code>, the position of one brace. The brace characters handled are '(', ')', '[',
+ ']', '{', '}', '&lt;', and '&gt;'. The search is forwards from an opening brace and backwards
+ from a closing brace. If the character at position is not a brace character, or a matching
+ brace cannot be found, the return value is -1. Otherwise, the return value is the position of
+ the matching brace.</p>
+
+ <p>A match only occurs if the style of the matching brace is the same as the starting brace or
+ the matching brace is beyond the end of styling. Nested braces are handled correctly. The
+ <code>maxReStyle</code> parameter must currently be 0 - it may be used in the future to limit
+ the length of brace searches.</p>
+
+ <h2 id="TabsAndIndentationGuides">Tabs and Indentation Guides</h2>
+
+ <p>Indentation (the white space at the start of a line) is often used by programmers to clarify
+ program structure and in some languages, for example Python, it may be part of the language
+ syntax. Tabs are normally used in editors to insert a tab character or to pad text with spaces
+ up to the next tab.</p>
+
+ <p>Scintilla can be set to treat tab and backspace in the white space at the start of a line in
+ a special way: inserting a tab indents the line to the next indent position rather than just
+ inserting a tab at the current character position and backspace unindents the line rather than
+ deleting a character. Scintilla can also display indentation guides (vertical lines) to help
+ you to generate code.</p>
+ <code><a class="message" href="#SCI_SETTABWIDTH">SCI_SETTABWIDTH(int widthInChars)</a><br />
+ <a class="message" href="#SCI_GETTABWIDTH">SCI_GETTABWIDTH</a><br />
+ <a class="message" href="#SCI_SETUSETABS">SCI_SETUSETABS(bool useTabs)</a><br />
+ <a class="message" href="#SCI_GETUSETABS">SCI_GETUSETABS</a><br />
+ <a class="message" href="#SCI_SETINDENT">SCI_SETINDENT(int widthInChars)</a><br />
+ <a class="message" href="#SCI_GETINDENT">SCI_GETINDENT</a><br />
+ <a class="message" href="#SCI_SETTABINDENTS">SCI_SETTABINDENTS(bool tabIndents)</a><br />
+ <a class="message" href="#SCI_GETTABINDENTS">SCI_GETTABINDENTS</a><br />
+ <a class="message" href="#SCI_SETBACKSPACEUNINDENTS">SCI_SETBACKSPACEUNINDENTS(bool
+ bsUnIndents)</a><br />
+ <a class="message" href="#SCI_GETBACKSPACEUNINDENTS">SCI_GETBACKSPACEUNINDENTS</a><br />
+ <a class="message" href="#SCI_SETLINEINDENTATION">SCI_SETLINEINDENTATION(int line, int
+ indentation)</a><br />
+ <a class="message" href="#SCI_GETLINEINDENTATION">SCI_GETLINEINDENTATION(int line)</a><br />
+ <a class="message" href="#SCI_GETLINEINDENTPOSITION">SCI_GETLINEINDENTPOSITION(int
+ line)</a><br />
+ <a class="message" href="#SCI_SETINDENTATIONGUIDES">SCI_SETINDENTATIONGUIDES(int indentView)</a><br />
+ <a class="message" href="#SCI_GETINDENTATIONGUIDES">SCI_GETINDENTATIONGUIDES</a><br />
+ <a class="message" href="#SCI_SETHIGHLIGHTGUIDE">SCI_SETHIGHLIGHTGUIDE(int column)</a><br />
+ <a class="message" href="#SCI_GETHIGHLIGHTGUIDE">SCI_GETHIGHLIGHTGUIDE</a><br />
+ </code>
+
+ <p><b id="SCI_SETTABWIDTH">SCI_SETTABWIDTH(int widthInChars)</b><br />
+ <b id="SCI_GETTABWIDTH">SCI_GETTABWIDTH</b><br />
+ <code>SCI_SETTABWIDTH</code> sets the size of a tab as a multiple of the size of a space
+ character in <code>STYLE_DEFAULT</code>. The default tab width is 8 characters. There are no
+ limits on tab sizes, but values less than 1 or large values may have undesirable effects.</p>
+
+ <p><b id="SCI_SETUSETABS">SCI_SETUSETABS(bool useTabs)</b><br />
+ <b id="SCI_GETUSETABS">SCI_GETUSETABS</b><br />
+ <code>SCI_SETUSETABS</code> determines whether indentation should be created out of a mixture
+ of tabs and spaces or be based purely on spaces. Set <code>useTabs</code> to <code>false</code>
+ (0) to create all tabs and indents out of spaces. The default is <code>true</code>. You can use
+ <a class="message" href="#SCI_GETCOLUMN"><code>SCI_GETCOLUMN</code></a> to get the column of a
+ position taking the width of a tab into account.</p>
+ <p><b id="SCI_SETINDENT">SCI_SETINDENT(int widthInChars)</b><br />
+ <b id="SCI_GETINDENT">SCI_GETINDENT</b><br />
+ <code>SCI_SETINDENT</code> sets the size of indentation in terms of the width of a space in <a
+ class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>. If you set a width of
+ 0, the indent size is the same as the tab size. There are no limits on indent sizes, but values
+ less than 0 or large values may have undesirable effects.
+ </p>
+
+ <p><b id="SCI_SETTABINDENTS">SCI_SETTABINDENTS(bool tabIndents)</b><br />
+ <b id="SCI_GETTABINDENTS">SCI_GETTABINDENTS</b><br />
+ <b id="SCI_SETBACKSPACEUNINDENTS">SCI_SETBACKSPACEUNINDENTS(bool bsUnIndents)</b><br />
+ <b id="SCI_GETBACKSPACEUNINDENTS">SCI_GETBACKSPACEUNINDENTS</b><br />
+ </p>
+
+ <p>Inside indentation white space, the tab and backspace keys can be made to indent and
+ unindent rather than insert a tab character or delete a character with the
+ <code>SCI_SETTABINDENTS</code> and <code>SCI_SETBACKSPACEUNINDENTS</code> functions.</p>
+
+ <p><b id="SCI_SETLINEINDENTATION">SCI_SETLINEINDENTATION(int line, int indentation)</b><br />
+ <b id="SCI_GETLINEINDENTATION">SCI_GETLINEINDENTATION(int line)</b><br />
+ The amount of indentation on a line can be discovered and set with
+ <code>SCI_GETLINEINDENTATION</code> and <code>SCI_SETLINEINDENTATION</code>. The indentation is
+ measured in character columns, which correspond to the width of space characters.</p>
+
+ <p><b id="SCI_GETLINEINDENTPOSITION">SCI_GETLINEINDENTPOSITION(int line)</b><br />
+ This returns the position at the end of indentation of a line.</p>
+
+ <p><b id="SCI_SETINDENTATIONGUIDES">SCI_SETINDENTATIONGUIDES(int indentView)</b><br />
+ <b id="SCI_GETINDENTATIONGUIDES">SCI_GETINDENTATIONGUIDES</b><br />
+ Indentation guides are dotted vertical lines that appear within indentation white space every
+ indent size columns. They make it easy to see which constructs line up especially when they
+ extend over multiple pages. Style <a class="message"
+ href="#StyleDefinition"><code>STYLE_INDENTGUIDE</code></a> (37) is used to specify the
+ foreground and background colour of the indentation guides.</p>
+
+ <p>There are 4 indentation guide views.
+ SC_IV_NONE turns the feature off but the other 3 states determine how far the guides appear on
+ empty lines.
+ <table border="0" summary="Search flags">
+ <tbody>
+ <tr>
+ <td><code>SC_IV_NONE</code></td>
+ <td>No indentation guides are shown.</td>
+ </tr>
+
+ <tr>
+ <td><code>SC_IV_REAL</code></td>
+ <td>Indentation guides are shown inside real indentation white space.</td>
+ </tr>
+
+ <tr>
+ <td><code>SC_IV_LOOKFORWARD</code></td>
+ <td>Indentation guides are shown beyond the actual indentation up to the level of the
+ next non-empty line.
+ If the previous non-empty line was a fold header then indentation guides are shown for
+ one more level of indent than that line. This setting is good for Python.</td>
+ </tr>
+
+ <tr>
+ <td><code>SC_IV_LOOKBOTH</code></td>
+ <td>Indentation guides are shown beyond the actual indentation up to the level of the
+ next non-empty line or previous non-empty line whichever is the greater.
+ This setting is good for most languages.</td>
+ </tr>
+
+ </table>
+ </p>
+
+ <p><b id="SCI_SETHIGHLIGHTGUIDE">SCI_SETHIGHLIGHTGUIDE(int column)</b><br />
+ <b id="SCI_GETHIGHLIGHTGUIDE">SCI_GETHIGHLIGHTGUIDE</b><br />
+ When brace highlighting occurs, the indentation guide corresponding to the braces may be
+ highlighted with the brace highlighting style, <a class="message"
+ href="#StyleDefinition"><code>STYLE_BRACELIGHT</code></a> (34). Set <code>column</code> to 0 to
+ cancel this highlight.</p>
+
+ <h2 id="Markers">Markers</h2>
+
+ <p>There are 32 markers, numbered 0 to <code>MARKER_MAX</code> (31), and you can assign any combination of them to each
+ line in the document. Markers appear in the <a class="jump" href="#Margins">selection
+ margin</a> to the left of the text. If the selection margin is set to zero width, the
+ background colour of the whole line is changed instead. Marker numbers 25 to 31 are used by
+ Scintilla in folding margins, and have symbolic names of the form <code>SC_MARKNUM_</code>*,
+ for example <code>SC_MARKNUM_FOLDEROPEN</code>.</p>
+
+ <p>Marker numbers 0 to 24 have no pre-defined function; you can use them to mark syntax errors
+ or the current point of execution, break points, or whatever you need marking. If you do not
+ need folding, you can use all 32 for any purpose you wish.</p>
+
+ <p>Each marker number has a symbol associated with it. You can also set the foreground and
+ background colour for each marker number, so you can use the same symbol more than once with
+ different colouring for different uses. Scintilla has a set of symbols you can assign
+ (<code>SC_MARK_</code>*) or you can use characters. By default, all 32 markers are set to
+ <code>SC_MARK_CIRCLE</code> with a black foreground and a white background.</p>
+
+ <p>The markers are drawn in the order of their numbers, so higher numbered markers appear on
+ top of lower numbered ones. Markers try to move with their text by tracking where the start of
+ their line moves. When a line is deleted, its markers are combined, by an <code>OR</code>
+ operation, with the markers of the previous line.</p>
+ <code><a class="message" href="#SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int
+ markerSymbols)</a><br />
+ <a class="message" href="#SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber,
+ const char *xpm)</a><br />
+ <a class="message" href="#SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)
+ </a><br />
+ <a class="message" href="#SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int
+ colour)</a><br />
+ <a class="message" href="#SCI_MARKERSETBACK">SCI_MARKERSETBACK(int markerNumber, int
+ colour)</a><br />
+ <a class="message" href="#SCI_MARKERSETALPHA">SCI_MARKERSETALPHA(int markerNumber, int
+ alpha)</a><br />
+ <a class="message" href="#SCI_MARKERADD">SCI_MARKERADD(int line, int markerNumber)</a><br />
+ <a class="message" href="#SCI_MARKERADDSET">SCI_MARKERADDSET(int line, int markerMask)</a><br />
+ <a class="message" href="#SCI_MARKERDELETE">SCI_MARKERDELETE(int line, int
+ markerNumber)</a><br />
+ <a class="message" href="#SCI_MARKERDELETEALL">SCI_MARKERDELETEALL(int markerNumber)</a><br />
+ <a class="message" href="#SCI_MARKERGET">SCI_MARKERGET(int line)</a><br />
+ <a class="message" href="#SCI_MARKERNEXT">SCI_MARKERNEXT(int lineStart, int
+ markerMask)</a><br />
+ <a class="message" href="#SCI_MARKERPREVIOUS">SCI_MARKERPREVIOUS(int lineStart, int
+ markerMask)</a><br />
+ <a class="message" href="#SCI_MARKERLINEFROMHANDLE">SCI_MARKERLINEFROMHANDLE(int
+ handle)</a><br />
+ <a class="message" href="#SCI_MARKERDELETEHANDLE">SCI_MARKERDELETEHANDLE(int handle)</a><br />
+ </code>
+
+ <p><b id="SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int markerSymbols)</b><br />
+ This message associates a marker number in the range 0 to 31 with one of the marker symbols or
+ an ASCII character. The general-purpose marker symbols currently available are:<br />
+ <code>SC_MARK_CIRCLE</code>, <code>SC_MARK_ROUNDRECT</code>, <code>SC_MARK_ARROW</code>,
+ <code>SC_MARK_SMALLRECT</code>, <code>SC_MARK_SHORTARROW</code>, <code>SC_MARK_EMPTY</code>,
+ <code>SC_MARK_ARROWDOWN</code>, <code>SC_MARK_MINUS</code>, <code>SC_MARK_PLUS</code>,
+ <code>SC_MARK_ARROWS</code>, <code>SC_MARK_DOTDOTDOT</code>, <code>SC_MARK_EMPTY</code>,
+ <code>SC_MARK_BACKGROUND</code>, <code>SC_MARK_LEFTRECT</code>,
+ <code>SC_MARK_FULLRECT</code>, and <code>SC_MARK_UNDERLINE</code>.</p>
+
+ <p>The <code>SC_MARK_BACKGROUND</code> marker changes the background colour of the line only.
+ The <code>SC_MARK_FULLRECT</code> symbol mirrors this, changing only the margin background colour.
+ <code>SC_MARK_UNDERLINE</code> draws an underline across the text.
+ The <code>SC_MARK_EMPTY</code> symbol is invisible, allowing client code to track the movement
+ of lines. You would also use it if you changed the folding style and wanted one or more of the
+ <code>SC_FOLDERNUM_</code>* markers to have no associated symbol.</p>
+
+ <p>Applications may use the marker symbol <code>SC_MARK_AVAILABLE</code> to indicate that
+ plugins may allocate that marker number.
+ </p>
+
+ <p>There are also marker symbols designed for use in the folding margin in a flattened tree
+ style.<br />
+ <code>SC_MARK_BOXMINUS</code>, <code>SC_MARK_BOXMINUSCONNECTED</code>,
+ <code>SC_MARK_BOXPLUS</code>, <code>SC_MARK_BOXPLUSCONNECTED</code>,
+ <code>SC_MARK_CIRCLEMINUS</code>, <code>SC_MARK_CIRCLEMINUSCONNECTED</code>,
+ <code>SC_MARK_CIRCLEPLUS</code>, <code>SC_MARK_CIRCLEPLUSCONNECTED</code>,
+ <code>SC_MARK_LCORNER</code>, <code>SC_MARK_LCORNERCURVE</code>, <code>SC_MARK_TCORNER</code>,
+ <code>SC_MARK_TCORNERCURVE</code>, and <code>SC_MARK_VLINE</code>.</p>
+ Characters can be used as markers by adding the ASCII value of the character to
+ <code>SC_MARK_CHARACTER</code> (10000). For example, to use 'A' (ASCII code 65) as marker
+ number 1 use:<br />
+ <code>SCI_MARKERDEFINE(1, SC_MARK_CHARACTER+65)</code>. <br />
+
+ <p>The marker numbers <code>SC_MARKNUM_FOLDER</code> and <code>SC_MARKNUM_FOLDEROPEN</code> are
+ used for showing that a fold is present and open or closed. Any symbols may be assigned for
+ this purpose although the (<code>SC_MARK_PLUS</code>, <code>SC_MARK_MINUS</code>) pair or the
+ (<code>SC_MARK_ARROW</code>, <code>SC_MARK_ARROWDOWN</code>) pair are good choices. As well as
+ these two, more assignments are needed for the flattened tree style:
+ <code>SC_MARKNUM_FOLDEREND</code>, <code>SC_MARKNUM_FOLDERMIDTAIL</code>,
+ <code>SC_MARKNUM_FOLDEROPENMID</code>, <code>SC_MARKNUM_FOLDERSUB</code>, and
+ <code>SC_MARKNUM_FOLDERTAIL</code>. The bits used for folding are specified by
+ <code>SC_MASK_FOLDERS</code>, which is commonly used as an argument to
+ <code>SCI_SETMARGINMASKN</code> when defining a margin to be used for folding.</p>
+
+ <p>This table shows which <code>SC_MARK_</code>* symbols should be assigned to which
+ <code>SC_MARKNUM_</code>* marker numbers to obtain four folding styles: Arrow (mimics
+ Macintosh), plus/minus shows folded lines as '+' and opened folds as '-', Circle tree, Box
+ tree.</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Markers used for folding">
+ <thead align="left">
+ <tr>
+ <th><code>SC_MARKNUM_</code>*</th>
+
+ <th>Arrow</th>
+
+ <th>Plus/minus</th>
+
+ <th>Circle tree</th>
+
+ <th>Box tree</th>
+ </tr>
+ </thead>
+
+ <tbody valign="top">
+ <tr>
+ <th align="left"><code>FOLDEROPEN</code></th>
+
+ <td><code>ARROWDOWN</code></td>
+
+ <td><code>MINUS</code></td>
+
+ <td><code>CIRCLEMINUS</code></td>
+
+ <td><code>BOXMINUS</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDER</code></th>
+
+ <td><code>ARROW</code></td>
+
+ <td><code>PLUS</code></td>
+
+ <td><code>CIRCLEPLUS</code></td>
+
+ <td><code>BOXPLUS</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDERSUB</code></th>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>VLINE</code></td>
+
+ <td><code>VLINE</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDERTAIL</code></th>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>LCORNERCURVE</code></td>
+
+ <td><code>LCORNER</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDEREND</code></th>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>CIRCLEPLUSCONNECTED</code></td>
+
+ <td><code>BOXPLUSCONNECTED</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDEROPENMID</code></th>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>CIRCLEMINUSCONNECTED</code></td>
+
+ <td><code>BOXMINUSCONNECTED</code></td>
+ </tr>
+
+ <tr>
+ <th align="left"><code>FOLDERMIDTAIL</code></th>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>EMPTY</code></td>
+
+ <td><code>TCORNERCURVE</code></td>
+
+ <td><code>TCORNER</code></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber, const char
+ *xpm)</b><br />
+ Markers can be set to pixmaps with this message. The XPM format is used for the pixmap and it
+ is limited to pixmaps that use one character per pixel with no named colours.
+ The transparent colour may be named 'None'.
+ The data should be null terminated.
+ Pixmaps use the <code>SC_MARK_PIXMAP</code> marker symbol. You can find the full description of
+ the XPM format <a class="jump" href="http://koala.ilog.fr/lehors/xpm.html">here</a>.</p>
+
+ <p><b id="SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)</b><br />
+ Returns the symbol defined for a markerNumber with <code>SCI_MARKERDEFINE</code>
+ or <code>SC_MARK_PIXMAP</code> if defined with <code>SCI_MARKERDEFINEPIXMAP</code>.</p>
+
+ <p><b id="SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_MARKERSETBACK">SCI_MARKERSETBACK(int markerNumber, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ These two messages set the foreground and background colour of a marker number.</p>
+ <p><b id="SCI_MARKERSETALPHA">SCI_MARKERSETALPHA(int markerNumber, int <a class="jump"
+ href="#alpha">alpha</a>)</b><br />
+ When markers are drawn in the content area, either because there is no margin for them or
+ they are of <code>SC_MARK_BACKGROUND</code> or <code>SC_MARK_UNDERLINE</code> types, they may be drawn translucently by
+ setting an alpha value.</p>
+
+ <p><b id="SCI_MARKERADD">SCI_MARKERADD(int line, int markerNumber)</b><br />
+ This message adds marker number <code>markerNumber</code> to a line. The message returns -1 if
+ this fails (illegal line number, out of memory) or it returns a marker handle number that
+ identifies the added marker. You can use this returned handle with <a class="message"
+ href="#SCI_MARKERLINEFROMHANDLE"><code>SCI_MARKERLINEFROMHANDLE</code></a> to find where a
+ marker is after moving or combining lines and with <a class="message"
+ href="#SCI_MARKERDELETEHANDLE"><code>SCI_MARKERDELETEHANDLE</code></a> to delete the marker
+ based on its handle. The message does not check the value of markerNumber, nor does it
+ check if the line already contains the marker.</p>
+
+ <p><b id="SCI_MARKERADDSET">SCI_MARKERADDSET(int line, int markerMask)</b><br />
+ This message can add one or more markers to a line with a single call, specified in the same "one-bit-per-marker" 32-bit integer format returned by
+ <a class="message" href="#SCI_MARKERGET"><code>SCI_MARKERGET</code></a>
+ (and used by the mask-based marker search functions
+ <a class="message" href="#SCI_MARKERNEXT"><code>SCI_MARKERNEXT</code></a> and
+ <a class="message" href="#SCI_MARKERPREVIOUS"><code>SCI_MARKERPREVIOUS</code></a>).
+ As with
+ <a class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>, no check is made
+ to see if any of the markers are already present on the targeted line.</p>
+
+ <p><b id="SCI_MARKERDELETE">SCI_MARKERDELETE(int line, int markerNumber)</b><br />
+ This searches the given line number for the given marker number and deletes it if it is
+ present. If you added the same marker more than once to the line, this will delete one copy
+ each time it is used. If you pass in a marker number of -1, all markers are deleted from the
+ line.</p>
+
+ <p><b id="SCI_MARKERDELETEALL">SCI_MARKERDELETEALL(int markerNumber)</b><br />
+ This removes markers of the given number from all lines. If markerNumber is -1, it deletes all
+ markers from all lines.</p>
+
+ <p><b id="SCI_MARKERGET">SCI_MARKERGET(int line)</b><br />
+ This returns a 32-bit integer that indicates which markers were present on the line. Bit 0 is
+ set if marker 0 is present, bit 1 for marker 1 and so on.</p>
+
+ <p><b id="SCI_MARKERNEXT">SCI_MARKERNEXT(int lineStart, int markerMask)</b><br />
+ <b id="SCI_MARKERPREVIOUS">SCI_MARKERPREVIOUS(int lineStart, int markerMask)</b><br />
+ These messages search efficiently for lines that include a given set of markers. The search
+ starts at line number <code>lineStart</code> and continues forwards to the end of the file
+ (<code>SCI_MARKERNEXT</code>) or backwards to the start of the file
+ (<code>SCI_MARKERPREVIOUS</code>). The <code>markerMask</code> argument should have one bit set
+ for each marker you wish to find. Set bit 0 to find marker 0, bit 1 for marker 1 and so on. The
+ message returns the line number of the first line that contains one of the markers in
+ <code>markerMask</code> or -1 if no marker is found.</p>
+
+ <p><b id="SCI_MARKERLINEFROMHANDLE">SCI_MARKERLINEFROMHANDLE(int markerHandle)</b><br />
+ The <code>markerHandle</code> argument is an identifier for a marker returned by <a
+ class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. This function searches
+ the document for the marker with this handle and returns the line number that contains it or -1
+ if it is not found.</p>
+
+ <p><b id="SCI_MARKERDELETEHANDLE">SCI_MARKERDELETEHANDLE(int markerHandle)</b><br />
+ The <code>markerHandle</code> argument is an identifier for a marker returned by <a
+ class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. This function searches
+ the document for the marker with this handle and deletes the marker if it is found.</p>
+
+ <h2 id="Indicators">Indicators</h2>
+
+ <p>Indicators are used to display additional information over the top of styling.
+ They can be used to show, for example, syntax errors, deprecated names and bad indentation
+ by drawing underlines under text or boxes around text. Originally, Scintilla stored indicator information in
+ the style bytes but this has proved limiting, so now up to 32 separately stored indicators may be used.
+ While style byte indicators currently still work, they will soon be removed so all the bits in each style
+ byte can be used for lexical states.</p>
+
+ <p>Indicators may be displayed as simple underlines, squiggly underlines, a
+ line of small 'T' shapes, a line of diagonal hatching, a strike-out or a rectangle around the text.</p>
+
+ <p>The <code>SCI_INDIC*</code> messages allow you to get and set the visual appearance of the
+ indicators. They all use an <code>indicatorNumber</code> argument in the range 0 to INDIC_MAX(31)
+ to set the indicator to style. To prevent interference the set of indicators is divided up into a range for use
+ by lexers (0..7) and a range for use by containers
+ (8=<code>INDIC_CONTAINER</code> .. 31=<code>INDIC_MAX</code>).</p>
+
+ <code><a class="message" href="#SCI_INDICSETSTYLE">SCI_INDICSETSTYLE(int indicatorNumber, int
+ indicatorStyle)</a><br />
+ <a class="message" href="#SCI_INDICGETSTYLE">SCI_INDICGETSTYLE(int indicatorNumber)</a><br />
+ <a class="message" href="#SCI_INDICSETFORE">SCI_INDICSETFORE(int indicatorNumber, int
+ colour)</a><br />
+ <a class="message" href="#SCI_INDICGETFORE">SCI_INDICGETFORE(int indicatorNumber)</a><br />
+ <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA(int indicatorNumber, int alpha)</a><br />
+ <a class="message" href="#SCI_INDICGETALPHA">SCI_INDICGETALPHA(int indicatorNumber)</a><br />
+ <a class="message" href="#SCI_INDICSETUNDER">SCI_INDICSETUNDER(int indicatorNumber, bool under)</a><br />
+ <a class="message" href="#SCI_INDICGETUNDER">SCI_INDICGETUNDER(int indicatorNumber)</a><br />
+ </code>
+
+ <p><b id="SCI_INDICSETSTYLE">SCI_INDICSETSTYLE(int indicatorNumber, int
+ indicatorStyle)</b><br />
+ <b id="SCI_INDICGETSTYLE">SCI_INDICGETSTYLE(int indicatorNumber)</b><br />
+ These two messages set and get the style for a particular indicator. The indicator styles
+ currently available are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Indicators">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+
+ <th>Value</th>
+
+ <th align="left">Visual effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>INDIC_PLAIN</code></td>
+
+ <td align="center">0</td>
+
+ <td>Underlined with a single, straight line.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_SQUIGGLE</code></td>
+
+ <td align="center">1</td>
+
+ <td>A squiggly underline.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_TT</code></td>
+
+ <td align="center">2</td>
+
+ <td>A line of small T shapes.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_DIAGONAL</code></td>
+
+ <td align="center">3</td>
+
+ <td>Diagonal hatching.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_STRIKE</code></td>
+
+ <td align="center">4</td>
+
+ <td>Strike out.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_HIDDEN</code></td>
+
+ <td align="center">5</td>
+
+ <td>An indicator with no visual effect.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_BOX</code></td>
+
+ <td align="center">6</td>
+
+ <td>A rectangle around the text.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>INDIC_ROUNDBOX</code></td>
+
+ <td align="center">7</td>
+
+ <td>A rectangle with rounded corners around the text using translucent drawing with the
+ interior more transparent than the border. You can use
+ <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA</a>
+ to control the alpha transparency value. The default alpha value is 30.
+ </tr>
+ </tbody>
+ </table>
+
+ <p>The default indicator styles are equivalent to:<br />
+ <code>SCI_INDICSETSTYLE(0, INDIC_SQUIGGLE);</code><br />
+ <code>SCI_INDICSETSTYLE(1, INDIC_TT);</code><br />
+ <code>SCI_INDICSETSTYLE(2, INDIC_PLAIN);</code></p>
+
+ <p><b id="SCI_INDICSETFORE">SCI_INDICSETFORE(int indicatorNumber, int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_INDICGETFORE">SCI_INDICGETFORE(int indicatorNumber)</b><br />
+ These two messages set and get the colour used to draw an indicator. The default indicator
+ colours are equivalent to:<br />
+ <code>SCI_INDICSETFORE(0, 0x007f00);</code> (dark green)<br />
+ <code>SCI_INDICSETFORE(1, 0xff0000);</code> (light blue)<br />
+ <code>SCI_INDICSETFORE(2, 0x0000ff);</code> (light red)</p>
+
+ <p><b id="SCI_INDICSETALPHA">SCI_INDICSETALPHA(int indicatorNumber, int alpha)</b><br />
+ <b id="SCI_INDICGETALPHA">SCI_INDICGETALPHA(int indicatorNumber)</b><br />
+ These two messages set and get the alpha transparency used for drawing the
+ fill color of the INDIC_ROUNDBOX rectangle. The alpha value can range from
+ 0 (completely transparent) to 100 (no transparency).
+ </p>
+
+ <p><b id="SCI_INDICSETUNDER">SCI_INDICSETUNDER(int indicatorNumber, bool under)</b><br />
+ <b id="SCI_INDICGETUNDER">SCI_INDICGETUNDER(int indicatorNumber)</b><br />
+ These two messages set and get whether an indicator is drawn under text or over(default).
+ Drawing under text works only for modern indicators when <a class="message" href="#SCI_SETTWOPHASEDRAW">two phase drawing</a>
+ is enabled.</p>
+
+ <h3 id="Modern Indicators">Modern Indicators</h3>
+
+ <p>Modern indicators are stored in a format similar to run length encoding which is efficient in both
+ speed and storage for sparse information.</p>
+ <p>An indicator may store different values for each range but currently all values are drawn the same.
+ In the future, it may be possible to draw different values in different styles.</p>
+ <p>
+ <b id="SCI_SETINDICATORCURRENT">SCI_SETINDICATORCURRENT(int indicator)</b><br />
+ <b id="SCI_GETINDICATORCURRENT">SCI_GETINDICATORCURRENT</b><br />
+ These two messages set and get the indicator that will be affected by calls to
+ <a class="message" href="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE</a> and
+ <a class="message" href="#SCI_INDICATORCLEARRANGE">SCI_INDICATORCLEARRANGE</a>.
+ </p>
+
+ <p>
+ <b id="SCI_SETINDICATORVALUE">SCI_SETINDICATORVALUE(int value)</b><br />
+ <b id="SCI_GETINDICATORVALUE">SCI_GETINDICATORVALUE</b><br />
+ These two messages set and get the value that will be set by calls to
+ <a class="message" href="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE</a>.
+ </p>
+
+ <p>
+ <b id="SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE(int position, int fillLength)</b><br />
+ <b id="SCI_INDICATORCLEARRANGE">SCI_INDICATORCLEARRANGE(int position, int clearLength)</b><br />
+ These two messages fill or clear a range for the current indicator.
+ <code>SCI_INDICATORFILLRANGE</code> fills with the
+ the current value.
+ </p>
+
+ <p>
+ <b id="SCI_INDICATORALLONFOR">SCI_INDICATORALLONFOR(int position)</b><br />
+ Retrieve a bitmap value representing which indicators are non-zero at a position.
+ </p>
+
+ <p>
+ <b id="SCI_INDICATORVALUEAT">SCI_INDICATORVALUEAT(int indicator, int position)</b><br />
+ Retrieve the value of a particular indicator at a position.
+ </p>
+
+ <p>
+ <b id="SCI_INDICATORSTART">SCI_INDICATORSTART(int indicator, int position)</b><br />
+ <b id="SCI_INDICATOREND">SCI_INDICATOREND(int indicator, int position)</b><br />
+ Find the start or end of a range with one value from a position within the range.
+ Can be used to iterate through the document to discover all the indicator positions.
+ </p>
+
+ <h3 id="Style Byte Indicators">Style Byte Indicators (deprecated)</h3>
+ <p>By default, Scintilla organizes the style byte associated with each text byte as 5 bits of
+ style information (for 32 styles) and 3 bits of indicator information for 3 independent
+ indicators so that, for example, syntax errors, deprecated names and bad indentation could all
+ be displayed at once.</p>
+
+ <p>The indicators are set using <a class="message"
+ href="#SCI_STARTSTYLING"><code>SCI_STARTSTYLING</code></a> with a <code>INDICS_MASK</code> mask
+ and <a class="message" href="#SCI_SETSTYLING"><code>SCI_SETSTYLING</code></a> with the values
+ <code>INDIC0_MASK</code>, <code>INDIC1_MASK</code> and <code>INDIC2_MASK</code>.</p>
+
+ <p>If you are using indicators in a buffer that has a lexer active
+ (see <a class="message" href="#SCI_SETLEXER"><code>SCI_SETLEXER</code></a>),
+ you must save lexing state information before setting any indicators and restore it afterwards.
+ Use <a class="message" href="#SCI_GETENDSTYLED"><code>SCI_GETENDSTYLED</code></a>
+ to retrieve the current "styled to" position and
+ <a class="message" href="#SCI_STARTSTYLING"><code>SCI_STARTSTYLING</code></a>
+ to reset the styling position and mask (<code>0x1f </code> in the default layout of 5 style bits and 3 indicator bits)
+ when you are done.</p>
+
+ <p>The number of bits used for styles can be altered with <a class="message"
+ href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> from 0 to 8 bits. The remaining bits
+ can be used for indicators, so there can be from 1 to 8 indicators. However, the
+ <code>INDIC*_MASK</code> constants defined in <code>Scintilla.h</code> all assume 5 bits of
+ styling information and 3 indicators. If you use a different arrangement, you must define your
+ own constants.</p>
+
+
+ <h2 id="Autocompletion">Autocompletion</h2>
+
+ <p>Autocompletion displays a list box showing likely identifiers based upon the user's typing.
+ The user chooses the currently selected item by pressing the tab character or another character
+ that is a member of the fillup character set defined with <code>SCI_AUTOCSETFILLUPS</code>.
+ Autocompletion is triggered by your application. For example, in C if you detect that the user
+ has just typed <code>fred.</code> you could look up <code>fred</code>, and if it has a known
+ list of members, you could offer them in an autocompletion list. Alternatively, you could
+ monitor the user's typing and offer a list of likely items once their typing has narrowed down
+ the choice to a reasonable list. As yet another alternative, you could define a key code to
+ activate the list.</p>
+
+ <p>When the user makes a selection from the list the container is sent a <code><a class="message"
+ href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a></code> <a class="jump"
+ href="#Notifications">notification message</a>. On return from the notification Scintilla will insert
+ the selected text unless the autocompletion list has been cancelled, for example by the container sending
+ <code><a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a></code>.</p>
+
+ <p>To make use of autocompletion you must monitor each character added to the document. See
+ <code>SciTEBase::CharAdded()</code> in SciTEBase.cxx for an example of autocompletion.</p>
+ <code><a class="message" href="#SCI_AUTOCSHOW">SCI_AUTOCSHOW(int lenEntered, const char
+ *list)</a><br />
+ <a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a><br />
+ <a class="message" href="#SCI_AUTOCACTIVE">SCI_AUTOCACTIVE</a><br />
+ <a class="message" href="#SCI_AUTOCPOSSTART">SCI_AUTOCPOSSTART</a><br />
+ <a class="message" href="#SCI_AUTOCCOMPLETE">SCI_AUTOCCOMPLETE</a><br />
+ <a class="message" href="#SCI_AUTOCSTOPS">SCI_AUTOCSTOPS(&lt;unused&gt;, const char
+ *chars)</a><br />
+ <a class="message" href="#SCI_AUTOCSETSEPARATOR">SCI_AUTOCSETSEPARATOR(char
+ separator)</a><br />
+ <a class="message" href="#SCI_AUTOCGETSEPARATOR">SCI_AUTOCGETSEPARATOR</a><br />
+ <a class="message" href="#SCI_AUTOCSELECT">SCI_AUTOCSELECT(&lt;unused&gt;, const char
+ *select)</a><br />
+ <a class="message" href="#SCI_AUTOCGETCURRENT">SCI_AUTOCGETCURRENT</a><br />
+ <a class="message" href="#SCI_AUTOCGETCURRENTTEXT">SCI_AUTOCGETCURRENTTEXT(&lt;unused&gt;,
+ char *text)</a><br />
+ <a class="message" href="#SCI_AUTOCSETCANCELATSTART">SCI_AUTOCSETCANCELATSTART(bool
+ cancel)</a><br />
+ <a class="message" href="#SCI_AUTOCGETCANCELATSTART">SCI_AUTOCGETCANCELATSTART</a><br />
+ <a class="message" href="#SCI_AUTOCSETFILLUPS">SCI_AUTOCSETFILLUPS(&lt;unused&gt;, const char
+ *chars)</a><br />
+ <a class="message" href="#SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE(bool
+ chooseSingle)</a><br />
+ <a class="message" href="#SCI_AUTOCGETCHOOSESINGLE">SCI_AUTOCGETCHOOSESINGLE</a><br />
+ <a class="message" href="#SCI_AUTOCSETIGNORECASE">SCI_AUTOCSETIGNORECASE(bool
+ ignoreCase)</a><br />
+ <a class="message" href="#SCI_AUTOCGETIGNORECASE">SCI_AUTOCGETIGNORECASE</a><br />
+ <a class="message" href="#SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</a><br />
+ <a class="message" href="#SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</a><br />
+ <a class="message" href="#SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool
+ dropRestOfWord)</a><br />
+ <a class="message" href="#SCI_AUTOCGETDROPRESTOFWORD">SCI_AUTOCGETDROPRESTOFWORD</a><br />
+ <a class="message" href="#SCI_REGISTERIMAGE">SCI_REGISTERIMAGE</a><br />
+ <a class="message" href="#SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</a><br />
+ <a class="message" href="#SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</a><br />
+ <a class="message" href="#SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</a><br />
+ <a class="message" href="#SCI_AUTOCSETMAXHEIGHT">SCI_AUTOCSETMAXHEIGHT(int rowCount)</a><br />
+ <a class="message" href="#SCI_AUTOCGETMAXHEIGHT">SCI_AUTOCGETMAXHEIGHT</a><br />
+ <a class="message" href="#SCI_AUTOCSETMAXWIDTH">SCI_AUTOCSETMAXWIDTH(int characterCount)</a><br />
+ <a class="message" href="#SCI_AUTOCGETMAXWIDTH">SCI_AUTOCGETMAXWIDTH</a><br />
+ </code>
+
+ <p><b id="SCI_AUTOCSHOW">SCI_AUTOCSHOW(int lenEntered, const char *list)</b><br />
+ This message causes a list to be displayed. <code>lenEntered</code> is the number of
+ characters of the word already entered and <code>list</code> is the list of words separated by
+ separator characters. The initial separator character is a space but this can be set or got
+ with <a class="message" href="#SCI_AUTOCSETSEPARATOR"><code>SCI_AUTOCSETSEPARATOR</code></a>
+ and <a class="message"
+ href="#SCI_AUTOCGETSEPARATOR"><code>SCI_AUTOCGETSEPARATOR</code></a>.</p>
+
+ <p>The list of words should be in sorted order. If set to ignore case mode with <a
+ class="message" href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>, then
+ strings are matched after being converted to upper case. One result of this is that the list
+ should be sorted with the punctuation characters '[', '\', ']', '^', '_', and '`' sorted after
+ letters.</p>
+
+ <p><b id="SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</b><br />
+ This message cancels any displayed autocompletion list. When in autocompletion mode, the list
+ should disappear when the user types a character that can not be part of the autocompletion,
+ such as '.', '(' or '[' when typing an identifier. A set of characters that will cancel
+ autocompletion can be specified with <a class="message"
+ href="#SCI_AUTOCSTOPS"><code>SCI_AUTOCSTOPS</code></a>.</p>
+
+ <p><b id="SCI_AUTOCACTIVE">SCI_AUTOCACTIVE</b><br />
+ This message returns non-zero if there is an active autocompletion list and zero if there is
+ not.</p>
+
+ <p><b id="SCI_AUTOCPOSSTART">SCI_AUTOCPOSSTART</b><br />
+ This returns the value of the current position when <code>SCI_AUTOCSHOW</code> started display
+ of the list.</p>
+
+ <p><b id="SCI_AUTOCCOMPLETE">SCI_AUTOCCOMPLETE</b><br />
+ This message triggers autocompletion. This has the same effect as the tab key.</p>
+
+ <p><b id="SCI_AUTOCSTOPS">SCI_AUTOCSTOPS(&lt;unused&gt;, const char *chars)</b><br />
+ The <code>chars</code> argument is a string containing a list of characters that will
+ automatically cancel the autocompletion list. When you start the editor, this list is
+ empty.</p>
+
+ <p><b id="SCI_AUTOCSETSEPARATOR">SCI_AUTOCSETSEPARATOR(char separator)</b><br />
+ <b id="SCI_AUTOCGETSEPARATOR">SCI_AUTOCGETSEPARATOR</b><br />
+ These two messages set and get the separator character used to separate words in the
+ <code>SCI_AUTOCSHOW</code> list. The default is the space character.</p>
+
+ <p><b id="SCI_AUTOCSELECT">SCI_AUTOCSELECT(&lt;unused&gt;, const char *select)</b><br />
+ <b id="SCI_AUTOCGETCURRENT">SCI_AUTOCGETCURRENT</b><br />
+ This message selects an item in the autocompletion list. It searches the list of words for the
+ first that matches <code>select</code>. By default, comparisons are case sensitive, but you can
+ change this with <a class="message"
+ href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>. The match is character
+ by character for the length of the <code>select</code> string. That is, if select is "Fred" it
+ will match "Frederick" if this is the first item in the list that begins with "Fred". If an
+ item is found, it is selected. If the item is not found, the autocompletion list closes if
+ auto-hide is true (see <a class="message"
+ href="#SCI_AUTOCSETAUTOHIDE"><code>SCI_AUTOCSETAUTOHIDE</code></a>).<br />
+ The current selection index can be retrieved with <code>SCI_AUTOCGETCURRENT</code>.</p>
+
+ <p><b id="SCI_AUTOCGETCURRENTTEXT">SCI_AUTOCGETCURRENTTEXT(&lt;unused&gt;, char *text)</b><br />
+ This message retrieves the current selected text in the autocompletion list. Normally the
+ <a class="message" href="#SCN_AUTOCSELECTION"><code>SCN_AUTOCSELECTION</code></a> notification
+ is used instead.</p>
+
+ <p></p>The value is copied to the <code>text</code> buffer, returning the length (not including the
+ terminating 0). If not found, an empty string is copied to the buffer and 0 is returned.</p>
+
+ <p>If the value argument is 0 then the length that should be allocated to store the value is
+ returned; again, the terminating 0 is not included.</p>
+
+ <p><b id="SCI_AUTOCSETCANCELATSTART">SCI_AUTOCSETCANCELATSTART(bool cancel)</b><br />
+ <b id="SCI_AUTOCGETCANCELATSTART">SCI_AUTOCGETCANCELATSTART</b><br />
+ The default behavior is for the list to be cancelled if the caret moves before the location it
+ was at when the list was displayed. By calling this message with a <code>false</code> argument,
+ the list is not cancelled until the caret moves before the first character of the word being
+ completed.</p>
+
+ <p><b id="SCI_AUTOCSETFILLUPS">SCI_AUTOCSETFILLUPS(&lt;unused&gt;, const char *chars)</b><br />
+ If a fillup character is typed with an autocompletion list active, the currently selected item
+ in the list is added into the document, then the fillup character is added. Common fillup
+ characters are '(', '[' and '.' but others are possible depending on the language. By default,
+ no fillup characters are set.</p>
+
+ <p><b id="SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE(bool chooseSingle)</b><br />
+ <b id="SCI_AUTOCGETCHOOSESINGLE">SCI_AUTOCGETCHOOSESINGLE</b><br />
+ If you use <code>SCI_AUTOCSETCHOOSESINGLE(1)</code> and a list has only one item, it is
+ automatically added and no list is displayed. The default is to display the list even if there
+ is only a single item.</p>
+
+ <p><b id="SCI_AUTOCSETIGNORECASE">SCI_AUTOCSETIGNORECASE(bool ignoreCase)</b><br />
+ <b id="SCI_AUTOCGETIGNORECASE">SCI_AUTOCGETIGNORECASE</b><br />
+ By default, matching of characters to list members is case sensitive. These messages let you
+ set and get case sensitivity.</p>
+
+ <p><b id="SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</b><br />
+ <b id="SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</b><br />
+ By default, the list is cancelled if there are no viable matches (the user has typed
+ characters that no longer match a list entry). If you want to keep displaying the original
+ list, set <code>autoHide</code> to <code>false</code>. This also effects <a class="message"
+ href="#SCI_AUTOCSELECT"><code>SCI_AUTOCSELECT</code></a>.</p>
+
+ <p><b id="SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool dropRestOfWord)</b><br />
+ <b id="SCI_AUTOCGETDROPRESTOFWORD">SCI_AUTOCGETDROPRESTOFWORD</b><br />
+ When an item is selected, any word characters following the caret are first erased if
+ <code>dropRestOfWord</code> is set <code>true</code>. The default is <code>false</code>.</p>
+
+ <p>
+ <b id="SCI_REGISTERIMAGE">SCI_REGISTERIMAGE(int type, const char *xpmData)</b><br />
+ <b id="SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</b><br />
+ <b id="SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</b><br />
+ <b id="SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</b><br />
+
+ Autocompletion list items may display an image as well as text. Each image is first registered with an integer
+ type. Then this integer is included in the text of the list separated by a '?' from the text. For example,
+ "fclose?2 fopen" displays image 2 before the string "fclose" and no image before "fopen".
+ The images are in XPM format as is described for
+ <a class="message" href="#SCI_MARKERDEFINEPIXMAP"><code>SCI_MARKERDEFINEPIXMAP</code></a>
+ The set of registered images can be cleared with <code>SCI_CLEARREGISTEREDIMAGES</code> and the '?' separator changed
+ with <code>SCI_AUTOCSETTYPESEPARATOR</code>.
+ </p>
+
+ <p>
+ <b id="SCI_AUTOCSETMAXHEIGHT">SCI_AUTOCSETMAXHEIGHT(int rowCount)</b><br />
+ <b id="SCI_AUTOCGETMAXHEIGHT">SCI_AUTOCGETMAXHEIGHT</b><br />
+
+ Get or set the maximum number of rows that will be visible in an autocompletion list. If there are more rows in the list, then a vertical
+ scrollbar is shown. The default is 5.
+ </p>
+
+ <p>
+ <b id="SCI_AUTOCSETMAXWIDTH">SCI_AUTOCSETMAXWIDTH(int characterCount)</b><br />
+ <b id="SCI_AUTOCGETMAXWIDTH">SCI_AUTOCGETMAXWIDTH</b><br />
+
+ Get or set the maximum width of an autocompletion list expressed as the number of characters in the longest item that will be totally visible.
+ If zero (the default) then the list's width is calculated to fit the item with the most characters. Any items that cannot be fully displayed within
+ the available width are indicated by the presence of ellipsis.
+ </p>
+
+ <h2 id="UserLists">User lists</h2>
+
+ <p>User lists use the same internal mechanisms as autocompletion lists, and all the calls
+ listed for autocompletion work on them; you cannot display a user list at the same time as an
+ autocompletion list is active. They differ in the following respects:</p>
+
+ <p>o The <code><a class="message"
+ href="#SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE</a></code> message has no
+ effect.<br />
+ o When the user makes a selection you are sent a <code><a class="message"
+ href="#SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</a></code> <a class="jump"
+ href="#Notifications">notification message</a> rather than <code><a class="message"
+ href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a></code>.</p>
+
+ <p>BEWARE: if you have set fillup characters or stop characters, these will still be active
+ with the user list, and may result in items being selected or the user list cancelled due to
+ the user typing into the editor.</p>
+
+ <p><b id="SCI_USERLISTSHOW">SCI_USERLISTSHOW(int listType, const char *list)</b><br />
+ The <code>listType</code> parameter is returned to the container as the <code>wParam</code>
+ field of the <a class="message" href="#SCNotification"><code>SCNotification</code></a>
+ structure. It must be greater than 0 as this is how Scintilla tells the difference between an
+ autocompletion list and a user list. If you have different types of list, for example a list of
+ buffers and a list of macros, you can use <code>listType</code> to tell which one has returned
+ a selection. </p>
+
+ <h2 id="CallTips">Call tips</h2>
+
+ <p>Call tips are small windows displaying the arguments to a function and are displayed after
+ the user has typed the name of the function. They normally display characters using the font
+ facename, size and character set defined by
+ <code><a class="message" href="#StyleDefinition">STYLE_DEFAULT</a></code>. You can choose to
+ use <code><a class="message" href="#StyleDefinition">STYLE_CALLTIP</a></code> to define the
+ facename, size, foreground and background colours and character set with
+ <code><a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE</a></code>.
+ This also enables support for Tab characters.
+
+ There is some interaction between call tips and autocompletion lists in that showing a
+ call tip cancels any active autocompletion list, and vice versa.</p>
+
+ <p>Call tips can highlight part of the text within them. You could use this to highlight the
+ current argument to a function by counting the number of commas (or whatever separator your
+ language uses). See <code>SciTEBase::CharAdded()</code> in <code>SciTEBase.cxx</code> for an
+ example of call tip use.</p>
+
+ <p>The mouse may be clicked on call tips and this causes a
+ <code><a class="message" href="#SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</a></code>
+ notification to be sent to the container. Small up and down arrows may be displayed within
+ a call tip by, respectively, including the characters '\001', or '\002'. This is useful
+ for showing that there are overloaded variants of one function name and that the user can
+ click on the arrows to cycle through the overloads.</p>
+
+ <p>Alternatively, call tips can be displayed when you leave the mouse pointer for a while over
+ a word in response to the <code><a class="message"
+ href="#SCN_DWELLSTART">SCN_DWELLSTART</a></code> <a class="jump"
+ href="#Notifications">notification</a> and cancelled in response to <code><a class="message"
+ href="#SCN_DWELLEND">SCN_DWELLEND</a></code>. This method could be used in a debugger to give
+ the value of a variable, or during editing to give information about the word under the
+ pointer.</p>
+ <code><a class="message" href="#SCI_CALLTIPSHOW">SCI_CALLTIPSHOW(int posStart, const char
+ *definition)</a><br />
+ <a class="message" href="#SCI_CALLTIPCANCEL">SCI_CALLTIPCANCEL</a><br />
+ <a class="message" href="#SCI_CALLTIPACTIVE">SCI_CALLTIPACTIVE</a><br />
+ <a class="message" href="#SCI_CALLTIPPOSSTART">SCI_CALLTIPPOSSTART</a><br />
+ <a class="message" href="#SCI_CALLTIPSETHLT">SCI_CALLTIPSETHLT(int highlightStart, int
+ highlightEnd)</a><br />
+ <a class="message" href="#SCI_CALLTIPSETBACK">SCI_CALLTIPSETBACK(int colour)</a><br />
+ <a class="message" href="#SCI_CALLTIPSETFORE">SCI_CALLTIPSETFORE(int colour)</a><br />
+ <a class="message" href="#SCI_CALLTIPSETFOREHLT">SCI_CALLTIPSETFOREHLT(int colour)</a><br />
+ <a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE(int tabsize)</a><br />
+ </code>
+
+ <p><b id="SCI_CALLTIPSHOW">SCI_CALLTIPSHOW(int posStart, const char *definition)</b><br />
+ This message starts the process by displaying the call tip window. If a call tip is already
+ active, this has no effect.<br />
+ <code>posStart</code> is the position in the document at which to align the call tip. The call
+ tip text is aligned to start 1 line below this character unless you have included up and/or
+ down arrows in the call tip text in which case the tip is aligned to the right-hand edge of
+ the rightmost arrow. The assumption is that you will start the text with something like
+ "\001 1 of 3 \002".<br />
+ <code>definition</code> is the call tip text. This can contain multiple lines separated by
+ '\n' (Line Feed, ASCII code 10) characters. Do not include '\r' (Carriage Return, ASCII
+ code 13), as this will most likely print as an empty box. '\t' (Tab, ASCII code 9) is
+ supported if you set a tabsize with
+ <code><a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE</a></code>.<br /></p>
+
+ <p><b id="SCI_CALLTIPCANCEL">SCI_CALLTIPCANCEL</b><br />
+ This message cancels any displayed call tip. Scintilla will also cancel call tips for you if
+ you use any keyboard commands that are not compatible with editing the argument list of a
+ function.</p>
+
+ <p><b id="SCI_CALLTIPACTIVE">SCI_CALLTIPACTIVE</b><br />
+ This returns 1 if a call tip is active and 0 if it is not active.</p>
+
+ <p><b id="SCI_CALLTIPPOSSTART">SCI_CALLTIPPOSSTART</b><br />
+ This message returns the value of the current position when <code>SCI_CALLTIPSHOW</code>
+ started to display the tip.</p>
+
+ <p><b id="SCI_CALLTIPSETHLT">SCI_CALLTIPSETHLT(int hlStart, int hlEnd)</b><br />
+ This sets the region of the call tips text to display in a highlighted style.
+ <code>hlStart</code> is the zero-based index into the string of the first character to
+ highlight and <code>hlEnd</code> is the index of the first character after the highlight.
+ <code>hlEnd</code> must be greater than <code>hlStart</code>; <code>hlEnd-hlStart</code> is the
+ number of characters to highlight. Highlights can extend over line ends if this is
+ required.</p>
+
+ <p>Unhighlighted text is drawn in a mid gray. Selected text is drawn in a dark blue. The
+ background is white. These can be changed with
+ <code>SCI_CALLTIPSETBACK</code>,
+ <code>SCI_CALLTIPSETFORE</code>, and
+ <code>SCI_CALLTIPSETFOREHLT</code>.
+ </p>
+
+ <p><b id="SCI_CALLTIPSETBACK">SCI_CALLTIPSETBACK(int colour)</b><br />
+ The background colour of call tips can be set with this message; the default colour is white.
+ It is not a good idea to set a dark colour as the background as the default colour for normal
+ calltip text is mid gray and the defaultcolour for highlighted text is dark blue. This also
+ sets the background colour of <code>STYLE_CALLTIP</code>.</p>
+
+ <p><b id="SCI_CALLTIPSETFORE">SCI_CALLTIPSETFORE(int colour)</b><br />
+ The colour of call tip text can be set with this message; the default colour is mid gray.
+ This also sets the foreground colour of <code>STYLE_CALLTIP</code>.</p>
+
+ <p><b id="SCI_CALLTIPSETFOREHLT">SCI_CALLTIPSETFOREHLT(int colour)</b><br />
+ The colour of highlighted call tip text can be set with this message; the default colour
+ is dark blue.</p>
+
+ <p><b id="SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE(int tabsize)</b><br />
+ This message changes the style used for call tips from <code>STYLE_DEFAULT</code> to
+ <code>STYLE_CALLTIP</code> and sets a tab size in screen pixels. If <code>tabsize</code> is
+ less than 1, Tab characters are not treated specially. Once this call has been used, the
+ call tip foreground and background colours are also taken from the style.</p>
+
+
+ <h2 id="KeyboardCommands">Keyboard commands</h2>
+
+ <p>To allow the container application to perform any of the actions available to the user with
+ keyboard, all the keyboard actions are messages. They do not take any parameters. These
+ commands are also used when redefining the key bindings with the <a class="message"
+ href="#SCI_ASSIGNCMDKEY"><code>SCI_ASSIGNCMDKEY</code></a> message.</p>
+
+ <table border="0" summary="Keyboard commands">
+ <tbody>
+ <tr>
+ <td><code>SCI_LINEDOWN</code></td>
+
+ <td><code>SCI_LINEDOWNEXTEND</code></td>
+
+ <td><code>SCI_LINEDOWNRECTEXTEND</code></td>
+
+ <td><code>SCI_LINESCROLLDOWN</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_LINEUP</code></td>
+
+ <td><code>SCI_LINEUPEXTEND</code></td>
+
+ <td><code>SCI_LINEUPRECTEXTEND</code></td>
+
+ <td><code>SCI_LINESCROLLUP</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_PARADOWN</code></td>
+
+ <td><code>SCI_PARADOWNEXTEND</code></td>
+
+ <td><code>SCI_PARAUP</code></td>
+
+ <td><code>SCI_PARAUPEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_CHARLEFT</code></td>
+
+ <td><code>SCI_CHARLEFTEXTEND</code></td>
+
+ <td><code>SCI_CHARLEFTRECTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_CHARRIGHT</code></td>
+
+ <td><code>SCI_CHARRIGHTEXTEND</code></td>
+
+ <td><code>SCI_CHARRIGHTRECTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_WORDLEFT</code></td>
+
+ <td><code>SCI_WORDLEFTEXTEND</code></td>
+
+ <td><code>SCI_WORDRIGHT</code></td>
+
+ <td><code>SCI_WORDRIGHTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_WORDLEFTEND</code></td>
+
+ <td><code>SCI_WORDLEFTENDEXTEND</code></td>
+
+ <td><code>SCI_WORDRIGHTEND</code></td>
+
+ <td><code>SCI_WORDRIGHTENDEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_WORDPARTLEFT</code></td>
+
+ <td><code>SCI_WORDPARTLEFTEXTEND</code></td>
+
+ <td><code>SCI_WORDPARTRIGHT</code></td>
+
+ <td><code>SCI_WORDPARTRIGHTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_HOME</code></td>
+
+ <td><code>SCI_HOMEEXTEND</code></td>
+
+ <td><code>[SCI_HOMERECTEXTEND]</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_HOMEDISPLAY</code></td>
+
+ <td><code>SCI_HOMEDISPLAYEXTEND</code></td>
+
+ <td><code>SCI_HOMEWRAP</code></td>
+
+ <td><code>SCI_HOMEWRAPEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_VCHOME</code></td>
+
+ <td><code>SCI_VCHOMEEXTEND</code></td>
+
+ <td><code>SCI_VCHOMERECTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_VCHOMEWRAP</code></td>
+
+ <td><code>SCI_VCHOMEWRAPEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_LINEEND</code></td>
+
+ <td><code>SCI_LINEENDEXTEND</code></td>
+
+ <td><code>SCI_LINEENDRECTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_LINEENDDISPLAY</code></td>
+
+ <td><code>SCI_LINEENDDISPLAYEXTEND</code></td>
+
+ <td><code>SCI_LINEENDWRAP</code></td>
+
+ <td><code>SCI_LINEENDWRAPEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_DOCUMENTSTART</code></td>
+
+ <td><code>SCI_DOCUMENTSTARTEXTEND</code></td>
+
+ <td><code>SCI_DOCUMENTEND</code></td>
+
+ <td><code>SCI_DOCUMENTENDEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_PAGEUP</code></td>
+
+ <td><code>SCI_PAGEUPEXTEND</code></td>
+
+ <td><code>SCI_PAGEUPRECTEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_PAGEDOWN</code></td>
+
+ <td><code>SCI_PAGEDOWNEXTEND</code></td>
+
+ <td><code>SCI_PAGEDOWNRECTEXTEND</code></td>
+ </tr>
+
+
+ <tr>
+ <td><code>SCI_STUTTEREDPAGEUP</code></td>
+
+ <td><code>SCI_STUTTEREDPAGEUPEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_STUTTEREDPAGEDOWN</code></td>
+
+ <td><code>SCI_STUTTEREDPAGEDOWNEXTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_DELETEBACK</code></td>
+
+ <td><code>SCI_DELETEBACKNOTLINE</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_DELWORDLEFT</code></td>
+
+ <td><code>SCI_DELWORDRIGHT</code></td>
+
+ <td><code>SCI_DELWORDRIGHTEND</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_DELLINELEFT</code></td>
+
+ <td><code>SCI_DELLINERIGHT</code></td>
+
+ <td><code>SCI_LINEDELETE</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_LINECUT</code></td>
+
+ <td><code>SCI_LINECOPY</code></td>
+
+ <td><code>SCI_LINETRANSPOSE</code></td>
+
+ <td><code>SCI_LINEDUPLICATE</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_LOWERCASE</code></td>
+
+ <td><code>SCI_UPPERCASE</code></td>
+
+ <td><code>SCI_CANCEL</code></td>
+
+ <td><code>SCI_EDITTOGGLEOVERTYPE</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_NEWLINE</code></td>
+
+ <td><code>SCI_FORMFEED</code></td>
+
+ <td><code>SCI_TAB</code></td>
+
+ <td><code>SCI_BACKTAB</code></td>
+ </tr>
+
+ <tr>
+ <td><code>SCI_SELECTIONDUPLICATE</code></td>
+
+ </tr>
+ </tbody>
+ </table>
+
+ <p>The <code>SCI_*EXTEND</code> messages extend the selection.</p>
+
+ <p>The <code>SCI_*RECTEXTEND</code> messages extend the rectangular selection
+ (and convert regular selection to rectangular one, if any).</p>
+
+ <p>The <code>SCI_WORDPART*</code> commands are used to move between word segments marked by
+ capitalisation (aCamelCaseIdentifier) or underscores (an_under_bar_ident).</p>
+
+ <p>The <code>SCI_HOME*</code> commands move the caret to the start of the line, while the
+ <code>SCI_VCHOME*</code>commands move the caret to the first non-blank character of the line
+ (ie. just after the indentation) unless it is already there; in this case, it acts as SCI_HOME*.</p>
+
+ <p>The <code>SCI_[HOME|LINEEND]DISPLAY*</code> commands are used when in line wrap mode to
+ allow movement to the start or end of display lines as opposed to the normal
+ <code>SCI_[HOME|LINEEND]</code> commands which move to the start or end of document lines.</p>
+
+ <p>The <code>SCI_[[VC]HOME|LINEEND]WRAP*</code> commands are like their namesakes
+ <code>SCI_[[VC]HOME|LINEEND]*</code> except they behave differently when word-wrap is enabled:
+ They go first to the start / end of the display line, like <code>SCI_[HOME|LINEEND]DISPLAY*</code>,
+ but if the cursor is already at the point, it goes on to the start or end of the document line,
+ as appropriate for <code>SCI_[[VC]HOME|LINEEND]*</code>.
+ </p>
+
+ <h2 id="KeyBindings">Key bindings</h2>
+
+ <p>There is a default binding of keys to commands that is defined in the Scintilla source in
+ the file <code>KeyMap.cxx</code> by the constant <code>KeyMap::MapDefault[]</code>. This table
+ maps key definitions to <code>SCI_*</code> messages with no parameters (mostly the <a
+ class="jump" href="#KeyboardCommands">keyboard commands</a> discussed above, but any Scintilla
+ command that has no arguments can be mapped). You can change the mapping to suit your own
+ requirements.</p>
+ <code><a class="message" href="#SCI_ASSIGNCMDKEY">SCI_ASSIGNCMDKEY(int keyDefinition, int
+ sciCommand)</a><br />
+ <a class="message" href="#SCI_CLEARCMDKEY">SCI_CLEARCMDKEY(int keyDefinition)</a><br />
+ <a class="message" href="#SCI_CLEARALLCMDKEYS">SCI_CLEARALLCMDKEYS</a><br />
+ <a class="message" href="#SCI_NULL">SCI_NULL</a><br />
+ </code>
+
+ <p><b id="keyDefinition">keyDefinition</b><br />
+ A key definition contains the key code in the low 16-bits and the key modifiers in the high
+ 16-bits. To combine <code>keyCode</code> and <code>keyMod</code> set:<br />
+ <br />
+ <code>keyDefinition = keyCode + (keyMod &lt;&lt; 16)</code></p>
+
+ <p>The key code is a visible or control character or a key from the <code>SCK_*</code>
+ enumeration, which contains:<br />
+ <code>SCK_ADD</code>, <code>SCK_BACK</code>, <code>SCK_DELETE</code>, <code>SCK_DIVIDE</code>,
+ <code>SCK_DOWN</code>, <code>SCK_END</code>, <code>SCK_ESCAPE</code>, <code>SCK_HOME</code>,
+ <code>SCK_INSERT</code>, <code>SCK_LEFT</code>, <code>SCK_MENU</code>, <code>SCK_NEXT</code> (Page Down),
+ <code>SCK_PRIOR</code> (Page Up), <code>SCK_RETURN</code>, <code>SCK_RIGHT</code>,
+ <code>SCK_RWIN</code>,
+ <code>SCK_SUBTRACT</code>, <code>SCK_TAB</code>, <code>SCK_UP</code>, and
+ <code>SCK_WIN</code>.</p>
+
+ <p>The modifiers are a combination of zero or more of <code>SCMOD_ALT</code>,
+ <code>SCMOD_CTRL</code>, and <code>SCMOD_SHIFT</code>. If you are building a table, you might
+ want to use <code>SCMOD_NORM</code>, which has the value 0, to mean no modifiers.</p>
+
+ <p><b id="SCI_ASSIGNCMDKEY">SCI_ASSIGNCMDKEY(int <a class="jump"
+ href="#keyDefinition">keyDefinition</a>, int sciCommand)</b><br />
+ This assigns the given key definition to a Scintilla command identified by
+ <code>sciCommand</code>. <code>sciCommand</code> can be any <code>SCI_*</code> command that has
+ no arguments.</p>
+
+ <p><b id="SCI_CLEARCMDKEY">SCI_CLEARCMDKEY(int <a class="jump"
+ href="#keyDefinition">keyDefinition</a>)</b><br />
+ This makes the given key definition do nothing by assigning the action <code>SCI_NULL</code>
+ to it.</p>
+
+ <p><b id="SCI_CLEARALLCMDKEYS">SCI_CLEARALLCMDKEYS</b><br />
+ This command removes all keyboard command mapping by setting an empty mapping table.</p>
+
+ <p><b id="SCI_NULL">SCI_NULL</b><br />
+ The <code>SCI_NULL</code> does nothing and is the value assigned to keys that perform no
+ action. SCI_NULL ensures that keys do not propagate to the parent window as that may
+ cause focus to move. If you want the standard platform behaviour use the constant 0 instead.</p>
+
+ <h2 id="PopupEditMenu">Popup edit menu</h2>
+
+ <p><b id="SCI_USEPOPUP">SCI_USEPOPUP(bool bEnablePopup)</b><br />
+ Clicking the wrong button on the mouse pops up a short default editing menu. This may be
+ turned off with <code>SCI_USEPOPUP(0)</code>. If you turn it off, context menu commands (in
+ Windows, <code>WM_CONTEXTMENU</code>) will not be handled by Scintilla, so the parent of the
+ Scintilla window will have the opportunity to handle the message.</p>
+
+ <h2 id="MacroRecording">Macro recording</h2>
+
+ <p>Start and stop macro recording mode. In macro recording mode, actions are reported to the
+ container through <code><a class="message" href="#SCN_MACRORECORD">SCN_MACRORECORD</a></code>
+ <a class="jump" href="#Notifications">notifications</a>. It is then up to the container to
+ record these actions for future replay.</p>
+
+ <p><b id="SCI_STARTRECORD">SCI_STARTRECORD</b><br />
+ <b id="SCI_STOPRECORD">SCI_STOPRECORD</b><br />
+ These two messages turn macro recording on and off.</p>
+
+ <h2 id="Printing">Printing</h2>
+
+ <p>On Windows <code>SCI_FORMATRANGE</code> can be used to draw the text onto a display context
+ which can include a printer display context. Printed output shows text styling as on the
+ screen, but it hides all margins except a line number margin. All special marker effects are
+ removed and the selection and caret are hidden.</p>
+ <code><a class="message" href="#SCI_FORMATRANGE">SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat
+ *pfr)</a><br />
+ <a class="message" href="#SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int
+ magnification)</a><br />
+ <a class="message" href="#SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION</a><br />
+ <a class="message" href="#SCI_SETPRINTCOLOURMODE">SCI_SETPRINTCOLOURMODE(int mode)</a><br />
+ <a class="message" href="#SCI_GETPRINTCOLOURMODE">SCI_GETPRINTCOLOURMODE</a><br />
+ <a class="message" href="#SCI_SETPRINTWRAPMODE">SCI_SETPRINTWRAPMODE</a><br />
+ <a class="message" href="#SCI_GETPRINTWRAPMODE">SCI_GETPRINTWRAPMODE</a><br />
+ </code>
+
+ <p><b id="SCI_FORMATRANGE">SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat *pfr)</b><br />
+ This call allows Windows users to render a range of text into a device context. If you use
+ this for printing, you will probably want to arrange a page header and footer; Scintilla does
+ not do this for you. See <code>SciTEWin::Print()</code> in <code>SciTEWinDlg.cxx</code> for an
+ example. Each use of this message renders a range of text into a rectangular area and returns
+ the position in the document of the next character to print.</p>
+
+ <p><code>bDraw</code> controls if any output is done. Set this to false if you are paginating
+ (for example, if you use this with MFC you will need to paginate in
+ <code>OnBeginPrinting()</code> before you output each page.</p>
+<pre>
+struct Sci_Rectangle { int left; int top; int right; int bottom; };
+
+struct Sci_RangeToFormat {
+ Sci_SurfaceID hdc; // The HDC (device context) we print to
+ Sci_SurfaceID hdcTarget; // The HDC we use for measuring (may be same as hdc)
+ Sci_Rectangle rc; // Rectangle in which to print
+ Sci_Rectangle rcPage; // Physically printable page size
+ Sci_CharacterRange chrg; // Range of characters to print
+};
+</pre>
+
+ <p><code>hdc</code> and <code>hdcTarget</code> should both be set to the device context handle
+ of the output device (usually a printer). If you print to a metafile these will not be the same
+ as Windows metafiles (unlike extended metafiles) do not implement the full API for returning
+ information. In this case, set <code>hdcTarget</code> to the screen DC.<br />
+ <code>rcPage</code> is the rectangle <code>{0, 0, maxX, maxY}</code> where <code>maxX+1</code>
+ and <code>maxY+1</code> are the number of physically printable pixels in x and y.<br />
+ <code>rc</code> is the rectangle to render the text in (which will, of course, fit within the
+ rectangle defined by rcPage).<br />
+ <code>chrg.cpMin</code> and <code>chrg.cpMax</code> define the start position and maximum
+ position of characters to output. All of each line within this character range is drawn.</p>
+
+ <p>When printing, the most tedious part is always working out what the margins should be to
+ allow for the non-printable area of the paper and printing a header and footer. If you look at
+ the printing code in SciTE, you will find that most of it is taken up with this. The loop that
+ causes Scintilla to render text is quite simple if you strip out all the margin, non-printable
+ area, header and footer code.</p>
+
+ <p><b id="SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int magnification)</b><br />
+ <b id="SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION</b><br />
+ <code>SCI_GETPRINTMAGNIFICATION</code> lets you to print at a different size than the screen
+ font. <code>magnification</code> is the number of points to add to the size of each screen
+ font. A value of -3 or -4 gives reasonably small print. You can get this value with
+ <code>SCI_GETPRINTMAGNIFICATION</code>.</p>
+
+ <p><b id="SCI_SETPRINTCOLOURMODE">SCI_SETPRINTCOLOURMODE(int mode)</b><br />
+ <b id="SCI_GETPRINTCOLOURMODE">SCI_GETPRINTCOLOURMODE</b><br />
+ These two messages set and get the method used to render coloured text on a printer that is
+ probably using white paper. It is especially important to consider the treatment of colour if
+ you use a dark or black screen background. Printing white on black uses up toner and ink very
+ many times faster than the other way around. You can set the mode to one of:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Colour printing modes">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+
+ <th>Value</th>
+
+ <th align="left">Purpose</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_PRINT_NORMAL</code></td>
+
+ <td align="center">0</td>
+
+ <td>Print using the current screen colours. This is the default.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PRINT_INVERTLIGHT</code></td>
+
+ <td align="center">1</td>
+
+ <td>If you use a dark screen background this saves ink by inverting the light value of
+ all colours and printing on a white background.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PRINT_BLACKONWHITE</code></td>
+
+ <td align="center">2</td>
+
+ <td>Print all text as black on a white background.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PRINT_COLOURONWHITE</code></td>
+
+ <td align="center">3</td>
+
+ <td>Everything prints in its own colour on a white background.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PRINT_COLOURONWHITEDEFAULTBG</code></td>
+
+ <td align="center">4</td>
+
+ <td>Everything prints in its own colour on a white background except that line numbers
+ use their own background colour.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_SETPRINTWRAPMODE">SCI_SETPRINTWRAPMODE(int wrapMode)</b><br />
+ <b id="SCI_GETPRINTWRAPMODE">SCI_GETPRINTWRAPMODE</b><br />
+ These two functions get and set the printer wrap mode. <code>wrapMode</code> can be
+ set to <code>SC_WRAP_NONE</code> (0), <code>SC_WRAP_WORD</code> (1) or
+ <code>SC_WRAP_CHAR</code> (2). The default is
+ <code>SC_WRAP_WORD</code>, which wraps printed output so that all characters fit
+ into the print rectangle. If you set <code>SC_WRAP_NONE</code>, each line of text
+ generates one line of output and the line is truncated if it is too long to fit
+ into the print area.<br />
+ <code>SC_WRAP_WORD</code> tries to wrap only between words as indicated by
+ white space or style changes although if a word is longer than a line, it will be wrapped before
+ the line end. <code>SC_WRAP_CHAR</code> is preferred to
+ <code>SC_WRAP_WORD</code> for Asian languages where there is no white space
+ between words.</p>
+
+ <h2 id="DirectAccess">Direct access</h2>
+ <code><a class="message" href="#SCI_GETDIRECTFUNCTION">SCI_GETDIRECTFUNCTION</a><br />
+ <a class="message" href="#SCI_GETDIRECTPOINTER">SCI_GETDIRECTPOINTER</a><br />
+ <a class="message" href="#SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</a><br />
+ </code>
+
+ <p>On Windows, the message-passing scheme used to communicate between the container and
+ Scintilla is mediated by the operating system <code>SendMessage</code> function and can lead to
+ bad performance when calling intensively. To avoid this overhead, Scintilla provides messages
+ that allow you to call the Scintilla message function directly. The code to do this in C/C++ is
+ of the form:</p>
+<pre>
+#include "Scintilla.h"
+SciFnDirect pSciMsg = (SciFnDirect)SendMessage(hSciWnd, SCI_GETDIRECTFUNCTION, 0, 0);
+sptr_t pSciWndData = (sptr_t)SendMessage(hSciWnd, SCI_GETDIRECTPOINTER, 0, 0);
+
+// now a wrapper to call Scintilla directly
+sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
+ return pSciMsg(pSciWndData, iMessage, wParam, lParam);
+}
+</pre>
+
+ <p><code>SciFnDirect</code>, <code>sptr_t</code> and <code>uptr_t</code> are declared in
+ <code>Scintilla.h</code>. <code>hSciWnd</code> is the window handle returned when you created
+ the Scintilla window.</p>
+
+ <p>While faster, this direct calling will cause problems if performed from a different thread
+ to the native thread of the Scintilla window in which case <code>SendMessage(hSciWnd, SCI_*,
+ wParam, lParam)</code> should be used to synchronize with the window's thread.</p>
+
+ <p>This feature also works on GTK+ but has no significant impact on speed.</p>
+
+ <p>From version 1.47 on Windows, Scintilla exports a function called
+ <code>Scintilla_DirectFunction</code> that can be used the same as the function returned by
+ <code>SCI_GETDIRECTFUNCTION</code>. This saves you the call to
+ <code>SCI_GETDIRECTFUNCTION</code> and the need to call Scintilla indirectly via the function
+ pointer.</p>
+
+ <p><b id="SCI_GETDIRECTFUNCTION">SCI_GETDIRECTFUNCTION</b><br />
+ This message returns the address of the function to call to handle Scintilla messages without
+ the overhead of passing through the Windows messaging system. You need only call this once,
+ regardless of the number of Scintilla windows you create.</p>
+
+ <p><b id="SCI_GETDIRECTPOINTER">SCI_GETDIRECTPOINTER</b><br />
+ This returns a pointer to data that identifies which Scintilla window is in use. You must call
+ this once for each Scintilla window you create. When you call the direct function, you must
+ pass in the direct pointer associated with the target window.</p>
+
+ <p><b id="SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</b><br />
+ Move the gap within Scintilla so that the text of the document is stored consecutively
+ and ensure there is a NUL character after the text, then return a pointer to the first character.
+ Applications may then pass this to a function that accepts a character pointer such as a regular
+ expression search or a parser. The pointer should <em>not</em> be written to as that may desynchronize
+ the internal state of Scintilla.</p>
+ <p>Since any action in Scintilla may change its internal state
+ this pointer becomes invalid after any call or by allowing user interface activity. The application
+ should reacquire the pointer after making any call to Scintilla or performing any user-interface calls such
+ as modifying a progress indicator.</p>
+ <p>This call takes similar time to inserting a character at the end of the document and this may
+ include moving the document contents. Specifically, all the characters after the document gap
+ are moved to before the gap. This compacted state should persist over calls and user interface
+ actions that do not change the document contents so reacquiring the pointer afterwards is very
+ quick. If this call is used to implement a global replace operation, then each replacement will
+ move the gap so if <code>SCI_GETCHARACTERPOINTER</code> is called after
+ each replacement then the operation will become O(n^2) rather than O(n). Instead, all
+ matches should be found and remembered, then all the replacements performed.</p>
+
+ <h2 id="MultipleViews">Multiple views</h2>
+
+ <p>A Scintilla window and the document that it displays are separate entities. When you create
+ a new window, you also create a new, empty document. Each document has a reference count that
+ is initially set to 1. The document also has a list of the Scintilla windows that are linked to
+ it so when any window changes the document, all other windows in which it appears are notified
+ to cause them to update. The system is arranged in this way so that you can work with many
+ documents in a single Scintilla window and so you can display a single document in multiple
+ windows (for use with splitter windows).</p>
+
+ <p>Although these messages use <code>document *pDoc</code>, to ensure compatibility with future
+ releases of Scintilla you should treat <code>pDoc</code> as an opaque <code>void*</code>. That
+ is, you can use and store the pointer as described in this section but you should not
+ dereference it.</p>
+ <code><a class="message" href="#SCI_GETDOCPOINTER">SCI_GETDOCPOINTER</a><br />
+ <a class="message" href="#SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(&lt;unused&gt;, document
+ *pDoc)</a><br />
+ <a class="message" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</a><br />
+ <a class="message" href="#SCI_ADDREFDOCUMENT">SCI_ADDREFDOCUMENT(&lt;unused&gt;, document
+ *pDoc)</a><br />
+ <a class="message" href="#SCI_RELEASEDOCUMENT">SCI_RELEASEDOCUMENT(&lt;unused&gt;, document
+ *pDoc)</a><br />
+ </code>
+
+ <p><b id="SCI_GETDOCPOINTER">SCI_GETDOCPOINTER</b><br />
+ This returns a pointer to the document currently in use by the window. It has no other
+ effect.</p>
+
+ <p><b id="SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(&lt;unused&gt;, document *pDoc)</b><br />
+ This message does the following:<br />
+ 1. It removes the current window from the list held by the current document.<br />
+ 2. It reduces the reference count of the current document by 1.<br />
+ 3. If the reference count reaches 0, the document is deleted.<br />
+ 4. <code>pDoc</code> is set as the new document for the window.<br />
+ 5. If <code>pDoc</code> was 0, a new, empty document is created and attached to the
+ window.<br />
+ 6. If <code>pDoc</code> was not 0, its reference count is increased by 1.</p>
+
+ <p><b id="SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</b><br />
+ This message creates a new, empty document and returns a pointer to it. This document is not
+ selected into the editor and starts with a reference count of 1. This means that you have
+ ownership of it and must either reduce its reference count by 1 after using
+ <code>SCI_SETDOCPOINTER</code> so that the Scintilla window owns it or you must make sure that
+ you reduce the reference count by 1 with <code>SCI_RELEASEDOCUMENT</code> before you close the
+ application to avoid memory leaks.</p>
+
+ <p><b id="SCI_ADDREFDOCUMENT">SCI_ADDREFDOCUMENT(&lt;unused&gt;, document *pDoc)</b><br />
+ This increases the reference count of a document by 1. If you want to replace the current
+ document in the Scintilla window and take ownership of the current document, for example if you
+ are editing many documents in one window, do the following:<br />
+ 1. Use <code>SCI_GETDOCPOINTER</code> to get a pointer to the document,
+ <code>pDoc</code>.<br />
+ 2. Use <code>SCI_ADDREFDOCUMENT(0, pDoc)</code> to increment the reference count.<br />
+ 3. Use <code>SCI_SETDOCPOINTER(0, pNewDoc)</code> to set a different document or
+ <code>SCI_SETDOCPOINTER(0, 0)</code> to set a new, empty document.</p>
+
+ <p><b id="SCI_RELEASEDOCUMENT">SCI_RELEASEDOCUMENT(&lt;unused&gt;, document *pDoc)</b><br />
+ This message reduces the reference count of the document identified by <code>pDoc</code>. pDoc
+ must be the result of <code>SCI_GETDOCPOINTER</code> or <code>SCI_CREATEDOCUMENT</code> and
+ must point at a document that still exists. If you call this on a document with a reference
+ count of 1 that is still attached to a Scintilla window, bad things will happen. To keep the
+ world spinning in its orbit you must balance each call to <code>SCI_CREATEDOCUMENT</code> or
+ <code>SCI_ADDREFDOCUMENT</code> with a call to <code>SCI_RELEASEDOCUMENT</code>.</p>
+
+ <h2 id="Folding">Folding</h2>
+
+ <p>The fundamental operation in folding is making lines invisible or visible. Line visibility
+ is a property of the view rather than the document so each view may be displaying a different
+ set of lines. From the point of view of the user, lines are hidden and displayed using fold
+ points. Generally, the fold points of a document are based on the hierarchical structure of the
+ document contents. In Python, the hierarchy is determined by indentation and in C++ by brace
+ characters. This hierarchy can be represented within a Scintilla document object by attaching a
+ numeric "fold level" to each line. The fold level is most easily set by a lexer, but you can
+ also set it with messages.</p>
+
+ <p>It is up to your code to set the connection between user actions and folding and unfolding.
+ The best way to see how this is done is to search the SciTE source code for the messages used
+ in this section of the documentation and see how they are used. You will also need to use
+ markers and a folding margin to complete your folding implementation.
+ The <code>"fold"</code> property should be set to <code>"1"</code> with
+ <code>SCI_SETPROPERTY("fold", "1")</code> to enable folding. </p>
+ <code><a class="message" href="#SCI_VISIBLEFROMDOCLINE">SCI_VISIBLEFROMDOCLINE(int
+ docLine)</a><br />
+ <a class="message" href="#SCI_DOCLINEFROMVISIBLE">SCI_DOCLINEFROMVISIBLE(int
+ displayLine)</a><br />
+ <a class="message" href="#SCI_SHOWLINES">SCI_SHOWLINES(int lineStart, int lineEnd)</a><br />
+ <a class="message" href="#SCI_HIDELINES">SCI_HIDELINES(int lineStart, int lineEnd)</a><br />
+ <a class="message" href="#SCI_GETLINEVISIBLE">SCI_GETLINEVISIBLE(int line)</a><br />
+ <a class="message" href="#SCI_SETFOLDLEVEL">SCI_SETFOLDLEVEL(int line, int level)</a><br />
+ <a class="message" href="#SCI_GETFOLDLEVEL">SCI_GETFOLDLEVEL(int line)</a><br />
+ <a class="message" href="#SCI_SETFOLDFLAGS">SCI_SETFOLDFLAGS(int flags)</a><br />
+ <a class="message" href="#SCI_GETLASTCHILD">SCI_GETLASTCHILD(int line, int level)</a><br />
+ <a class="message" href="#SCI_GETFOLDPARENT">SCI_GETFOLDPARENT(int line)</a><br />
+ <a class="message" href="#SCI_SETFOLDEXPANDED">SCI_SETFOLDEXPANDED(int line, bool
+ expanded)</a><br />
+ <a class="message" href="#SCI_GETFOLDEXPANDED">SCI_GETFOLDEXPANDED(int line)</a><br />
+ <a class="message" href="#SCI_TOGGLEFOLD">SCI_TOGGLEFOLD(int line)</a><br />
+ <a class="message" href="#SCI_ENSUREVISIBLE">SCI_ENSUREVISIBLE(int line)</a><br />
+ <a class="message" href="#SCI_ENSUREVISIBLEENFORCEPOLICY">SCI_ENSUREVISIBLEENFORCEPOLICY(int
+ line)</a><br />
+ </code>
+
+ <p><b id="SCI_VISIBLEFROMDOCLINE">SCI_VISIBLEFROMDOCLINE(int docLine)</b><br />
+ When some lines are folded, then a particular line in the document may be displayed at a
+ different position to its document position. If no lines are folded, this message returns
+ <code>docLine</code>. Otherwise, this returns the display line (counting the very first visible
+ line as 0). The display line of an invisible line is the same as the previous visible line. The
+ display line number of the first line in the document is 0. If there is folding and
+ <code>docLine</code> is outside the range of lines in the document, the return value is -1.
+ Lines can occupy more than one display line if they wrap.</p>
+
+ <p><b id="SCI_DOCLINEFROMVISIBLE">SCI_DOCLINEFROMVISIBLE(int displayLine)</b><br />
+ When some lines are hidden, then a particular line in the document may be displayed at a
+ different position to its document position. This message returns the document line number that
+ corresponds to a display line (counting the display line of the first line in the document as
+ 0). If <code>displayLine</code> is less than or equal to 0, the result is 0. If
+ <code>displayLine</code> is greater than or equal to the number of displayed lines, the result
+ is the number of lines in the document.</p>
+
+ <p><b id="SCI_SHOWLINES">SCI_SHOWLINES(int lineStart, int lineEnd)</b><br />
+ <b id="SCI_HIDELINES">SCI_HIDELINES(int lineStart, int lineEnd)</b><br />
+ <b id="SCI_GETLINEVISIBLE">SCI_GETLINEVISIBLE(int line)</b><br />
+ The first two messages mark a range of lines as visible or invisible and then redraw the
+ display. The third message reports on the visible state of a line and returns 1 if it is
+ visible and 0 if it is not visible. These messages have no effect on fold levels or fold
+ flags. The first line can not be hidden.</p>
+
+ <p><b id="SCI_SETFOLDLEVEL">SCI_SETFOLDLEVEL(int line, int level)</b><br />
+ <b id="SCI_GETFOLDLEVEL">SCI_GETFOLDLEVEL(int line)</b><br />
+ These two messages set and get a 32-bit value that contains the fold level of a line and some
+ flags associated with folding. The fold level is a number in the range 0 to
+ <code>SC_FOLDLEVELNUMBERMASK</code> (4095). However, the initial fold level is set to
+ <code>SC_FOLDLEVELBASE</code> (1024) to allow unsigned arithmetic on folding levels. There are
+ two addition flag bits. <code>SC_FOLDLEVELWHITEFLAG</code> indicates that the line is blank and
+ allows it to be treated slightly different then its level may indicate. For example, blank
+ lines should generally not be fold points and will be considered part of the preceding section even though
+ they may have a lesser fold level.
+ <code>SC_FOLDLEVELHEADERFLAG</code> indicates that
+ the line is a header (fold point).</p>
+
+ <p>Use <code>SCI_GETFOLDLEVEL(line) &amp; SC_FOLDLEVELNUMBERMASK</code> to get the fold level
+ of a line. Likewise, use <code>SCI_GETFOLDLEVEL(line) &amp; SC_FOLDLEVEL*FLAG</code> to get the
+ state of the flags. To set the fold level you must or in the associated flags. For instance, to
+ set the level to <code>thisLevel</code> and mark a line as being a fold point use:
+ <code>SCI_SETFOLDLEVEL(line, thisLevel | SC_FOLDLEVELHEADERFLAG)</code>.</p>
+ If you use a lexer, you should not need to use <code>SCI_SETFOLDLEVEL</code> as this is far
+ better handled by the lexer. You will need to use <code>SCI_GETFOLDLEVEL</code> to decide how
+ to handle user folding requests. If you do change the fold levels, the folding margin will
+ update to match your changes.
+
+ <p><b id="SCI_SETFOLDFLAGS">SCI_SETFOLDFLAGS(int flags)</b><br />
+ In addition to showing markers in the folding margin, you can indicate folds to the user by
+ drawing lines in the text area. The lines are drawn in the foreground colour set for <a
+ class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>. Bits set in
+ <code>flags</code> determine where folding lines are drawn:<br />
+ </p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Fold flags">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+ <th align="left">Value</th>
+ <th align="left">Effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"></td>
+ <td align="left">1</td>
+ <td align="left">Experimental feature that has been removed.</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDFLAG_LINEBEFORE_EXPANDED</td>
+ <td align="left">2</td>
+
+ <td align="left">Draw above if expanded</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDFLAG_LINEBEFORE_CONTRACTED</td>
+ <td align="left">4</td>
+
+ <td align="left">Draw above if not expanded</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDFLAG_LINEAFTER_EXPANDED</td>
+ <td align="left">8</td>
+
+ <td align="left">Draw below if expanded</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDFLAG_LINEAFTER_CONTRACTED</td>
+ <td align="left">16</td>
+
+ <td align="left">Draw below if not expanded</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDFLAG_LEVELNUMBERS</td>
+ <td align="left">64</td>
+
+ <td align="left">display hexadecimal fold levels in line margin to aid debugging of
+ folding. The appearance of this feature may change in the future.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>This message causes the display to redraw.</p>
+
+ <p><b id="SCI_GETLASTCHILD">SCI_GETLASTCHILD(int startLine, int level)</b><br />
+ This message searches for the next line after <code>startLine</code>, that has a folding level
+ that is less than or equal to <code>level</code> and then returns the previous line number. If
+ you set <code>level</code> to -1, <code>level</code> is set to the folding level of line
+ <code>startLine</code>. If <code>from</code> is a fold point, <code>SCI_GETLASTCHILD(from,
+ -1)</code> returns the last line that would be in made visible or hidden by toggling the fold
+ state.</p>
+
+ <p><b id="SCI_GETFOLDPARENT">SCI_GETFOLDPARENT(int startLine)</b><br />
+ This message returns the line number of the first line before <code>startLine</code> that is
+ marked as a fold point with <code>SC_FOLDLEVELHEADERFLAG</code> and has a fold level less than
+ the <code>startLine</code>. If no line is found, or if the header flags and fold levels are
+ inconsistent, the return value is -1.</p>
+
+ <p><b id="SCI_TOGGLEFOLD">SCI_TOGGLEFOLD(int line)</b><br />
+ Each fold point may be either expanded, displaying all its child lines, or contracted, hiding
+ all the child lines. This message toggles the folding state of the given line as long as it has
+ the <code>SC_FOLDLEVELHEADERFLAG</code> set. This message takes care of folding or expanding
+ all the lines that depend on the line. The display updates after this message.</p>
+
+ <p><b id="SCI_SETFOLDEXPANDED">SCI_SETFOLDEXPANDED(int line, bool expanded)</b><br />
+ <b id="SCI_GETFOLDEXPANDED">SCI_GETFOLDEXPANDED(int line)</b><br />
+ These messages set and get the expanded state of a single line. The set message has no effect
+ on the visible state of the line or any lines that depend on it. It does change the markers in
+ the folding margin. If you ask for the expansion state of a line that is outside the document,
+ the result is <code>false</code> (0).</p>
+
+ <p>If you just want to toggle the fold state of one line and handle all the lines that are
+ dependent on it, it is much easier to use <code>SCI_TOGGLEFOLD</code>. You would use the
+ <code>SCI_SETFOLDEXPANDED</code> message to process many folds without updating the display
+ until you had finished. See <code>SciTEBase::FoldAll()</code> and
+ <code>SciTEBase::Expand()</code> for examples of the use of these messages.</p>
+
+ <p><b id="SCI_ENSUREVISIBLE">SCI_ENSUREVISIBLE(int line)</b><br />
+ <b id="SCI_ENSUREVISIBLEENFORCEPOLICY">SCI_ENSUREVISIBLEENFORCEPOLICY(int line)</b><br />
+ A line may be hidden because more than one of its parent lines is contracted. Both these
+ message travels up the fold hierarchy, expanding any contracted folds until they reach the top
+ level. The line will then be visible. If you use <code>SCI_ENSUREVISIBLEENFORCEPOLICY</code>,
+ the vertical caret policy set by <a class="message"
+ href="#SCI_SETVISIBLEPOLICY"><code>SCI_SETVISIBLEPOLICY</code></a> is then applied.</p>
+
+ <h2 id="LineWrapping">Line wrapping</h2>
+
+ <code><a class="message" href="#SCI_SETWRAPMODE">SCI_SETWRAPMODE(int wrapMode)</a><br />
+ <a class="message" href="#SCI_GETWRAPMODE">SCI_GETWRAPMODE</a><br />
+ <a class="message" href="#SCI_SETWRAPVISUALFLAGS">SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)</a><br />
+ <a class="message" href="#SCI_GETWRAPVISUALFLAGS">SCI_GETWRAPVISUALFLAGS</a><br />
+ <a class="message" href="#SCI_SETWRAPVISUALFLAGSLOCATION">SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)</a><br />
+ <a class="message" href="#SCI_GETWRAPVISUALFLAGSLOCATION">SCI_GETWRAPVISUALFLAGSLOCATION</a><br />
+ <a class="message" href="#SCI_SETWRAPINDENTMODE">SCI_SETWRAPINDENTMODE(int indentMode)</a><br />
+ <a class="message" href="#SCI_GETWRAPINDENTMODE">SCI_GETWRAPINDENTMODE</a><br />
+ <a class="message" href="#SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT(int indent)</a><br />
+ <a class="message" href="#SCI_GETWRAPSTARTINDENT">SCI_GETWRAPSTARTINDENT</a><br />
+ <a class="message" href="#SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</a><br />
+ <a class="message" href="#SCI_GETLAYOUTCACHE">SCI_GETLAYOUTCACHE</a><br />
+ <a class="message" href="#SCI_SETPOSITIONCACHE">SCI_SETPOSITIONCACHE(int size)</a><br />
+ <a class="message" href="#SCI_GETPOSITIONCACHE">SCI_GETPOSITIONCACHE</a><br />
+ <a class="message" href="#SCI_LINESSPLIT">SCI_LINESSPLIT(int pixelWidth)</a><br />
+ <a class="message" href="#SCI_LINESJOIN">SCI_LINESJOIN</a><br />
+ <a class="message" href="#SCI_WRAPCOUNT">SCI_WRAPCOUNT(int docLine)</a><br />
+ </code>
+
+ <p>By default, Scintilla does not wrap lines of text. If you enable line wrapping, lines wider
+ than the window width are continued on the following lines. Lines are broken after space or tab
+ characters or between runs of different styles. If this is not possible because a word in one
+ style is wider than the window then the break occurs after the last character that completely
+ fits on the line. The horizontal scroll bar does not appear when wrap mode is on.</p>
+
+ <p>For wrapped lines Scintilla can draw visual flags (little arrows) at end of a a subline of a
+ wrapped line and at begin of the next subline. These can be enabled individually, but if Scintilla
+ draws the visual flag at the beginning of the next subline this subline will be indented by one char.
+ Independent from drawing a visual flag at the begin the subline can have an indention.</p>
+
+ <p>Much of the time used by Scintilla is spent on laying out and drawing text. The same text
+ layout calculations may be performed many times even when the data used in these calculations
+ does not change. To avoid these unnecessary calculations in some circumstances, the line layout
+ cache can store the results of the calculations. The cache is invalidated whenever the
+ underlying data, such as the contents or styling of the document changes. Caching the layout of
+ the whole document has the most effect, making dynamic line wrap as much as 20 times faster but
+ this requires 7 times the memory required by the document contents plus around 80 bytes per
+ line.</p>
+
+ <p>Wrapping is not performed immediately there is a change but is delayed until the display
+ is redrawn. This delay improves peformance by allowing a set of changes to be performed
+ and then wrapped and displayed once. Because of this, some operations may not occur as
+ expected. If a file is read and the scroll position moved to a particular line in the text,
+ such as occurs when a container tries to restore a previous editing session, then
+ the scroll position will have been determined before wrapping so an unexpected range
+ of text will be displayed. To scroll to the position correctly, delay the scroll until the
+ wrapping has been performed by waiting for an initial
+ <a class="message" href="#SCN_PAINTED">SCN_PAINTED</a> notification.</p>
+
+ <p><b id="SCI_SETWRAPMODE">SCI_SETWRAPMODE(int wrapMode)</b><br />
+ <b id="SCI_GETWRAPMODE">SCI_GETWRAPMODE</b><br />
+ Set wrapMode to <code>SC_WRAP_WORD</code> (1) to enable wrapping
+ on word boundaries, <code>SC_WRAP_CHAR</code> (2) to enable wrapping
+ between any characters, and to <code>SC_WRAP_NONE</code> (0) to disable line
+ wrapping. <code>SC_WRAP_CHAR</code> is preferred to
+ <code>SC_WRAP_WORD</code> for Asian languages where there is no white space
+ between words.</p>
+
+
+ <p><b id="SCI_SETWRAPVISUALFLAGS">SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)</b><br />
+ <b id="SCI_GETWRAPVISUALFLAGS">SCI_GETWRAPVISUALFLAGS</b><br />
+ You can enable the drawing of visual flags to indicate a line is wrapped. Bits set in
+ wrapVisualFlags determine which visual flags are drawn.
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+ <th>Value</th>
+ <th align="left">Effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAG_NONE</code></td>
+ <td align="center">0</td>
+ <td>No visual flags</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAG_END</code></td>
+ <td align="center">1</td>
+ <td>Visual flag at end of subline of a wrapped line.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAG_START</code></td>
+ <td align="center">2</td>
+ <td>Visual flag at begin of subline of a wrapped line.<br />
+ Subline is indented by at least 1 to make room for the flag.<br />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_SETWRAPVISUALFLAGSLOCATION">SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)</b><br />
+ <b id="SCI_GETWRAPVISUALFLAGSLOCATION">SCI_GETWRAPVISUALFLAGSLOCATION</b><br />
+ You can set whether the visual flags to indicate a line is wrapped are drawn near the border or near the text.
+ Bits set in wrapVisualFlagsLocation set the location to near the text for the corresponding visual flag.
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags locations">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+ <th>Value</th>
+ <th align="left">Effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAGLOC_DEFAULT</code></td>
+ <td align="center">0</td>
+ <td>Visual flags drawn near border</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAGLOC_END_BY_TEXT</code></td>
+ <td align="center">1</td>
+ <td>Visual flag at end of subline drawn near text</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPVISUALFLAGLOC_START_BY_TEXT</code></td>
+ <td align="center">2</td>
+ <td>Visual flag at beginning of subline drawn near text</td>
+ </tr>
+ </tbody>
+ </table>
+ </p>
+
+ <p><b id="SCI_SETWRAPINDENTMODE">SCI_SETWRAPINDENTMODE(int indentMode)</b><br />
+ <b id="SCI_GETWRAPINDENTMODE">SCI_GETWRAPINDENTMODE</b><br />
+ Wrapped sublines can be indented to the position of their first subline or one more indent level.
+ The default is <code>SC_WRAPINDENT_FIXED</code>.
+ The modes are:
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags locations">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+ <th>Value</th>
+ <th align="left">Effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_WRAPINDENT_FIXED</code></td>
+ <td align="center">0</td>
+ <td>Wrapped sublines aligned to left of window plus amount set by
+ <a class="message" href="#SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT</a></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPINDENT_SAME</code></td>
+ <td align="center">1</td>
+ <td>Wrapped sublines are aligned to first subline indent</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_WRAPINDENT_INDENT</code></td>
+ <td align="center">2</td>
+ <td>Wrapped sublines are aligned to first subline indent plus one more level of indentation</td>
+ </tr>
+ </tbody>
+ </table>
+ </p>
+
+ <p><b id="SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT(int indent)</b><br />
+ <b id="SCI_GETWRAPSTARTINDENT">SCI_GETWRAPSTARTINDENT</b><br />
+ <code>SCI_SETWRAPSTARTINDENT</code> sets the size of indentation of sublines for
+ wrapped lines in terms of the average character width in
+ <a class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>.
+ There are no limits on indent sizes, but values less than 0 or large values may have
+ undesirable effects.<br />
+ The indention of sublines is independent of visual flags, but if
+ <code>SC_WRAPVISUALFLAG_START</code> is set an indent of at least 1 is used.
+ </p>
+
+ <p><b id="SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</b><br />
+ <b id="SCI_GETLAYOUTCACHE">SCI_GETLAYOUTCACHE</b><br />
+ You can set <code>cacheMode</code> to one of the symbols in the table:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Line caching styles">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+
+ <th>Value</th>
+
+ <th align="left">Layout cached for these lines</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_CACHE_NONE</code></td>
+
+ <td align="center">0</td>
+
+ <td>No lines are cached.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_CACHE_CARET</code></td>
+
+ <td align="center">1</td>
+
+ <td>The line containing the text caret. This is the default.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_CACHE_PAGE</code></td>
+
+ <td align="center">2</td>
+
+ <td>Visible lines plus the line containing the caret.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_CACHE_DOCUMENT</code></td>
+
+ <td align="center">3</td>
+
+ <td>All lines in the document.</td>
+ </tr>
+ </tbody>
+ </table>
+ </p>
+
+ <p><b id="SCI_SETPOSITIONCACHE">SCI_SETPOSITIONCACHE(int size)</b><br />
+ <b id="SCI_GETPOSITIONCACHE">SCI_GETPOSITIONCACHE</b><br />
+ The position cache stores position information for short runs of text
+ so that their layout can be determined more quickly if the run recurs.
+ The size in entries of this cache can be set with <code>SCI_SETPOSITIONCACHE</code>.</p>
+
+ <p><b id="SCI_LINESSPLIT">SCI_LINESSPLIT(int pixelWidth)</b><br />
+ Split a range of lines indicated by the target into lines that are at most pixelWidth wide.
+ Splitting occurs on word boundaries wherever possible in a similar manner to line wrapping.
+ When <code>pixelWidth</code> is 0 then the width of the window is used.
+ </p>
+
+ <p><b id="SCI_LINESJOIN">SCI_LINESJOIN</b><br />
+ Join a range of lines indicated by the target into one line by
+ removing line end characters.
+ Where this would lead to no space between words, an extra space is inserted.
+ </p>
+
+ <p><b id="SCI_WRAPCOUNT">SCI_WRAPCOUNT(int docLine)</b><br />
+ Document lines can occupy more than one display line if they wrap and this
+ returns the number of display lines needed to wrap a document line.</p>
+
+ <h2 id="Zooming">Zooming</h2>
+
+ <p>Scintilla incorporates a "zoom factor" that lets you make all the text in the document
+ larger or smaller in steps of one point. The displayed point size never goes below 2, whatever
+ zoom factor you set. You can set zoom factors in the range -10 to +20 points.</p>
+ <code><a class="message" href="#SCI_ZOOMIN">SCI_ZOOMIN</a><br />
+ <a class="message" href="#SCI_ZOOMOUT">SCI_ZOOMOUT</a><br />
+ <a class="message" href="#SCI_SETZOOM">SCI_SETZOOM(int zoomInPoints)</a><br />
+ <a class="message" href="#SCI_GETZOOM">SCI_GETZOOM</a><br />
+ </code>
+
+ <p><b id="SCI_ZOOMIN">SCI_ZOOMIN</b><br />
+ <b id="SCI_ZOOMOUT">SCI_ZOOMOUT</b><br />
+ <code>SCI_ZOOMIN</code> increases the zoom factor by one point if the current zoom factor is
+ less than 20 points. <code>SCI_ZOOMOUT</code> decreases the zoom factor by one point if the
+ current zoom factor is greater than -10 points.</p>
+
+ <p><b id="SCI_SETZOOM">SCI_SETZOOM(int zoomInPoints)</b><br />
+ <b id="SCI_GETZOOM">SCI_GETZOOM</b><br />
+ These messages let you set and get the zoom factor directly. There is no limit set on the
+ factors you can set, so limiting yourself to -10 to +20 to match the incremental zoom functions
+ is a good idea.</p>
+
+ <h2 id="LongLines">Long lines</h2>
+
+ <p>You can choose to mark lines that exceed a given length by drawing a vertical line or by
+ colouring the background of characters that exceed the set length.</p>
+ <code><a class="message" href="#SCI_SETEDGEMODE">SCI_SETEDGEMODE(int mode)</a><br />
+ <a class="message" href="#SCI_GETEDGEMODE">SCI_GETEDGEMODE</a><br />
+ <a class="message" href="#SCI_SETEDGECOLUMN">SCI_SETEDGECOLUMN(int column)</a><br />
+ <a class="message" href="#SCI_GETEDGECOLUMN">SCI_GETEDGECOLUMN</a><br />
+ <a class="message" href="#SCI_SETEDGECOLOUR">SCI_SETEDGECOLOUR(int colour)</a><br />
+ <a class="message" href="#SCI_GETEDGECOLOUR">SCI_GETEDGECOLOUR</a><br />
+ </code>
+
+ <p><b id="SCI_SETEDGEMODE">SCI_SETEDGEMODE(int edgeMode)</b><br />
+ <b id="SCI_GETEDGEMODE">SCI_GETEDGEMODE</b><br />
+ These two messages set and get the mode used to display long lines. You can set one of the
+ values in the table:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Long line styles">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+
+ <th>Value</th>
+
+ <th align="left">Long line display mode</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>EDGE_NONE</code></td>
+
+ <td align="center">0</td>
+
+ <td>Long lines are not marked. This is the default state.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>EDGE_LINE</code></td>
+
+ <td align="center">1</td>
+
+ <td>A vertical line is drawn at the column number set by <code>SCI_SETEDGECOLUMN</code>.
+ This works well for monospaced fonts. The line is drawn at a position based on the width
+ of a space character in <a class="message"
+ href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>, so it may not work very well if
+ your styles use proportional fonts or if your style have varied font sizes or you use a
+ mixture of bold, italic and normal text.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>EDGE_BACKGROUND</code></td>
+
+ <td align="center">2</td>
+
+ <td>The background colour of characters after the column limit is changed to the colour
+ set by <code>SCI_SETEDGECOLOUR</code>. This is recommended for proportional fonts.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCI_SETEDGECOLUMN">SCI_SETEDGECOLUMN(int column)</b><br />
+ <b id="SCI_GETEDGECOLUMN">SCI_GETEDGECOLUMN</b><br />
+ These messages set and get the column number at which to display the long line marker. When
+ drawing lines, the column sets a position in units of the width of a space character in
+ <code>STYLE_DEFAULT</code>. When setting the background colour, the column is a character count
+ (allowing for tabs) into the line.</p>
+
+ <p><b id="SCI_SETEDGECOLOUR">SCI_SETEDGECOLOUR(int <a class="jump"
+ href="#colour">colour</a>)</b><br />
+ <b id="SCI_GETEDGECOLOUR">SCI_GETEDGECOLOUR</b><br />
+ These messages set and get the colour of the marker used to show that a line has exceeded the
+ length set by <code>SCI_SETEDGECOLUMN</code>.</p>
+
+ <h2 id="Lexer">Lexer</h2>
+
+ <p>If you define the symbol <code>SCI_LEXER</code> when building Scintilla, (this is sometimes
+ called the SciLexer version of Scintilla), lexing support for a wide range programming
+ languages is included and the messages in this section are supported. If you want to set
+ styling and fold points for an unsupported language you can either do this in the container or
+ better still, write your own lexer following the pattern of one of the existing ones.</p>
+
+ <p>Scintilla also supports external lexers. These are DLLs (on Windows) or .so modules (on GTK+/Linux) that export four
+ functions: <code>GetLexerCount</code>, <code>GetLexerName</code>, <code>Lex</code> and
+ <code>Fold</code>. See <code>externalLexer.cxx</code> for more.</p>
+ <code><a class="message" href="#SCI_SETLEXER">SCI_SETLEXER(int lexer)</a><br />
+ <a class="message" href="#SCI_GETLEXER">SCI_GETLEXER</a><br />
+ <a class="message" href="#SCI_SETLEXERLANGUAGE">SCI_SETLEXERLANGUAGE(&lt;unused&gt;, const char
+ *name)</a><br />
+ <a class="message" href="#SCI_GETLEXERLANGUAGE">SCI_GETLEXERLANGUAGE(&lt;unused&gt;, char
+ *name)</a><br />
+ <a class="message" href="#SCI_LOADLEXERLIBRARY">SCI_LOADLEXERLIBRARY(&lt;unused&gt;, const char
+ *path)</a><br />
+ <a class="message" href="#SCI_COLOURISE">SCI_COLOURISE(int start, int end)</a><br />
+ <a class="message" href="#SCI_SETPROPERTY">SCI_SETPROPERTY(const char *key, const char *value)</a><br />
+ <a class="message" href="#SCI_GETPROPERTY">SCI_GETPROPERTY(const char *key, char *value)</a><br />
+ <a class="message" href="#SCI_GETPROPERTYEXPANDED">SCI_GETPROPERTYEXPANDED(const char *key, char *value)</a><br />
+ <a class="message" href="#SCI_GETPROPERTYINT">SCI_GETPROPERTYINT(const char *key, int default)</a><br />
+ <a class="message" href="#SCI_SETKEYWORDS">SCI_SETKEYWORDS(int keyWordSet, const char
+ *keyWordList)</a><br />
+ <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a>
+ <br />
+ </code>
+
+ <p><b id="SCI_SETLEXER">SCI_SETLEXER(int lexer)</b><br />
+ <b id="SCI_GETLEXER">SCI_GETLEXER</b><br />
+ You can select the lexer to use with an integer code from the <code>SCLEX_*</code> enumeration
+ in <code>Scintilla.h</code>. There are two codes in this sequence that do not use lexers:
+ <code>SCLEX_NULL</code> to select no lexing action and <code>SCLEX_CONTAINER</code> which sends
+ the <code><a class="message" href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a></code> notification to
+ the container whenever a range of text needs to be styled. You cannot use the
+ <code>SCLEX_AUTOMATIC</code> value; this identifies additional external lexers that Scintilla
+ assigns unused lexer numbers to.</p>
+
+ <p><b id="SCI_SETLEXERLANGUAGE">SCI_SETLEXERLANGUAGE(&lt;unused&gt;, const char *name)</b><br />
+ <b id="SCI_GETLEXERLANGUAGE">SCI_GETLEXERLANGUAGE(&lt;unused&gt;, char *name)</b><br />
+ <code>SCI_SETLEXERLANGUAGE</code> lets you select a lexer by name, and is the only method if you are using an
+ external lexer or if you have written a lexer module for a language of your own and do not wish
+ to assign it an explicit lexer number. To select an existing lexer, set <code>name</code> to
+ match the (case sensitive) name given to the module, for example "ada" or "python", not "Ada"
+ or "Python". To locate the name for the built-in lexers, open the relevant
+ <code>Lex*.cxx</code> file and search for <code>LexerModule</code>. The third argument in the
+ <code>LexerModule</code> constructor is the name to use.</p>
+
+ <p>To test if your lexer assignment worked, use <a class="message"
+ href="#SCI_GETLEXER"><code>SCI_GETLEXER</code></a> before and after setting the new lexer to
+ see if the lexer number changed.</p>
+
+ <p><code>SCI_GETLEXERLANGUAGE</code> retrieves the name of the lexer.</p>
+
+ <p><b id="SCI_LOADLEXERLIBRARY">SCI_LOADLEXERLIBRARY(&lt;unused&gt;, const char *path)</b><br />
+ Load a lexer implemented in a shared library. This is a .so file on GTK+/Linux or a .DLL file on Windows.
+ </p>
+
+ <p><b id="SCI_COLOURISE">SCI_COLOURISE(int startPos, int endPos)</b><br />
+ This requests the current lexer or the container (if the lexer is set to
+ <code>SCLEX_CONTAINER</code>) to style the document between <code>startPos</code> and
+ <code>endPos</code>. If <code>endPos</code> is -1, the document is styled from
+ <code>startPos</code> to the end. If the <code>"fold"</code> property is set to
+ <code>"1"</code> and your lexer or container supports folding, fold levels are also set. This
+ message causes a redraw.</p>
+
+ <p><b id="SCI_SETPROPERTY">SCI_SETPROPERTY(const char *key, const char *value)</b><br />
+ You can communicate settings to lexers with keyword:value string pairs. There is no limit to
+ the number of keyword pairs you can set, other than available memory. <code>key</code> is a
+ case sensitive keyword, <code>value</code> is a string that is associated with the keyword. If
+ there is already a value string associated with the keyword, it is replaced. If you pass a zero
+ length string, the message does nothing. Both <code>key</code> and <code>value</code> are used
+ without modification; extra spaces at the beginning or end of <code>key</code> are
+ significant.</p>
+
+ <p>The <code>value</code> string can refer to other keywords. For example,
+ <code>SCI_SETPROPERTY("foldTimes10", "$(fold)0")</code> stores the string
+ <code>"$(fold)0"</code>, but when this is accessed, the <code>$(fold)</code> is replaced by the
+ value of the <code>"fold"</code> keyword (or by nothing if this keyword does not exist).</p>
+
+ <p>Currently the "fold" property is defined for most of the lexers to set the fold structure if
+ set to "1". <code>SCLEX_PYTHON</code> understands <code>"tab.timmy.whinge.level"</code> as a
+ setting that determines how to indicate bad indentation. Most keywords have values that are
+ interpreted as integers. Search the lexer sources for <code>GetPropertyInt</code> to see how
+ properties are used.</p>
+
+ <p>There is a convention for naming properties used by lexers so that the set of properties can be found by scripts.
+ Property names should start with "lexer.&lt;lexer&gt;." or "fold.&lt;lexer&gt;." when they apply to one
+ lexer or start with "lexer." or "fold." if they apply to multiple lexers.</p>
+
+ <p>Applications may discover the set of properties used by searching the source code of lexers for lines that contain
+ <code>GetProperty</code> and a double quoted string and extract the value of the double quoted string as the property name.
+ The <code>scintilla/src/LexGen.py</code> script does this and can be used as an example.
+ Documentation for the property may be located above the call as a multi-line comment starting with
+ <br/><code>// property &lt;property-name&gt;</code></p>
+
+ <p><b id="SCI_GETPROPERTY">SCI_GETPROPERTY(const char *key, char *value)</b><br />
+ Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied
+ buffer and return the length (not including the terminating 0). If not found, copy an empty string
+ to the buffer and return 0.</p>
+
+ <p>Note that "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
+ <code>SCI_SETPROPERTY</code></a> will not be performed.</p>
+
+ <p>If the value argument is 0 then the length that should be allocated to store the value is returned;
+ again, the terminating 0 is not included.</p>
+
+ <p><b id="SCI_GETPROPERTYEXPANDED">SCI_GETPROPERTYEXPANDED(const char *key, char *value)</b><br />
+ Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied
+ buffer and return the length (not including the terminating 0). If not found, copy an empty string
+ to the buffer and return 0.</p>
+
+ <p>Note that "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
+ <code>SCI_SETPROPERTY</code></a> will be performed.</p>
+
+ <p>If the value argument is 0 then the length that should be allocated to store the value (including any indicated keyword replacement)
+ is returned; again, the terminating 0 is not included.</p>
+
+ <p><b id="SCI_GETPROPERTYINT">SCI_GETPROPERTYINT(const char *key, int default)</b><br />
+ Lookup a keyword:value pair using the specified key; if found, interpret the value as an integer and return it.
+ If not found (or the value is an empty string) then return the supplied default. If the keyword:value pair is found but is not
+ a number, then return 0.</p>
+
+ <p>Note that "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
+ <code>SCI_SETPROPERTY</code></a> will be performed before any numeric interpretation.</p>
+
+ <p><b id="SCI_SETKEYWORDS">SCI_SETKEYWORDS(int keyWordSet, const char *keyWordList)</b><br />
+ You can set up to 9 lists of keywords for use by the current lexer. This was increased from 6
+ at revision 1.50. <code>keyWordSet</code> can be 0 to 8 (actually 0 to <code>KEYWORDSET_MAX</code>)
+ and selects which keyword list to replace. <code>keyWordList</code> is a list of keywords
+ separated by spaces, tabs, <code>"\n"</code> or <code>"\r"</code> or any combination of these.
+ It is expected that the keywords will be composed of standard ASCII printing characters,
+ but there is nothing to stop you using any non-separator character codes from 1 to 255
+ (except common sense).</p>
+
+ <p>How these keywords are used is entirely up to the lexer. Some languages, such as HTML may
+ contain embedded languages, VBScript and JavaScript are common for HTML. For HTML, key word set
+ 0 is for HTML, 1 is for JavaScript and 2 is for VBScript, 3 is for Python, 4 is for PHP and 5
+ is for SGML and DTD keywords. Review the lexer code to see examples of keyword list. A fully
+ conforming lexer sets the fourth argument of the <code>LexerModule</code> constructor to be a
+ list of strings that describe the uses of the keyword lists.</p>
+
+ <p>Alternatively, you might use set 0 for general keywords, set 1 for keywords that cause
+ indentation and set 2 for keywords that cause unindentation. Yet again, you might have a simple
+ lexer that colours keywords and you could change languages by changing the keywords in set 0.
+ There is nothing to stop you building your own keyword lists into the lexer, but this means
+ that the lexer must be rebuilt if more keywords are added.</p>
+
+ <p><b id="SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</b><br />
+ Retrieve the number of bits the current lexer needs for styling. This should normally be the argument
+ to <a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS</a>.
+ </p>
+
+ <h2 id="Notifications">Notifications</h2>
+
+ <p>Notifications are sent (fired) from the Scintilla control to its container when an event has
+ occurred that may interest the container. Notifications are sent using the
+ <code>WM_NOTIFY</code> message on Windows and the "notify" signal on GTK+. The container is
+ passed a <code>SCNotification</code> structure containing information about the event.</p>
+<pre id="SCNotification">
+struct NotifyHeader { // This matches the Win32 NMHDR structure
+ void *hwndFrom; // environment specific window handle/pointer
+ uptr_t idFrom; // CtrlID of the window issuing the notification
+ unsigned int code; // The SCN_* notification code
+};
+
+struct SCNotification {
+ struct NotifyHeader nmhdr;
+ int position;
+ // SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_DWELLSTART,
+ // SCN_DWELLEND, SCN_CALLTIPCLICK,
+ // SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK
+ int ch; // SCN_CHARADDED, SCN_KEY
+ int modifiers; // SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK
+ int modificationType; // SCN_MODIFIED
+ const char *text; // SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION
+ int length; // SCN_MODIFIED
+ int linesAdded; // SCN_MODIFIED
+ int message; // SCN_MACRORECORD
+ uptr_t wParam; // SCN_MACRORECORD
+ sptr_t lParam; // SCN_MACRORECORD
+ int line; // SCN_MODIFIED, SCN_DOUBLECLICK
+ int foldLevelNow; // SCN_MODIFIED
+ int foldLevelPrev; // SCN_MODIFIED
+ int margin; // SCN_MARGINCLICK
+ int listType; // SCN_USERLISTSELECTION, SCN_AUTOCSELECTION
+ int x; // SCN_DWELLSTART, SCN_DWELLEND
+ int y; // SCN_DWELLSTART, SCN_DWELLEND
+};
+</pre>
+
+ <p>The notification messages that your container can choose to handle and the messages
+ associated with them are:</p>
+ <code><a class="message" href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a><br />
+ <a class="message" href="#SCN_CHARADDED">SCN_CHARADDED</a><br />
+ <a class="message" href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a><br />
+ <a class="message" href="#SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</a><br />
+ <a class="message" href="#SCN_MODIFYATTEMPTRO">SCN_MODIFYATTEMPTRO</a><br />
+ <a class="message" href="#SCN_KEY">SCN_KEY</a><br />
+ <a class="message" href="#SCN_DOUBLECLICK">SCN_DOUBLECLICK</a><br />
+ <a class="message" href="#SCN_UPDATEUI">SCN_UPDATEUI</a><br />
+ <a class="message" href="#SCN_MODIFIED">SCN_MODIFIED</a><br />
+ <a class="message" href="#SCN_MACRORECORD">SCN_MACRORECORD</a><br />
+ <a class="message" href="#SCN_MARGINCLICK">SCN_MARGINCLICK</a><br />
+ <a class="message" href="#SCN_NEEDSHOWN">SCN_NEEDSHOWN</a><br />
+ <a class="message" href="#SCN_PAINTED">SCN_PAINTED</a><br />
+ <a class="message" href="#SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</a><br />
+ <a class="message" href="#SCN_URIDROPPED">SCN_URIDROPPED</a><br />
+ <a class="message" href="#SCN_DWELLSTART">SCN_DWELLSTART</a><br />
+ <a class="message" href="#SCN_DWELLEND">SCN_DWELLEND</a><br />
+ <a class="message" href="#SCN_ZOOM">SCN_ZOOM</a><br />
+ <a class="message" href="#SCN_HOTSPOTCLICK">SCN_HOTSPOTCLICK</a><br />
+ <a class="message" href="#SCN_HOTSPOTDOUBLECLICK">SCN_HOTSPOTDOUBLECLICK</a><br />
+ <a class="message" href="#SCN_INDICATORCLICK">SCN_INDICATORCLICK</a><br />
+ <a class="message" href="#SCN_INDICATORRELEASE">SCN_INDICATORRELEASE</a><br />
+ <a class="message" href="#SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</a><br />
+ <a class="message" href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a><br />
+ <a class="message" href="#SCN_AUTOCCANCELLED">SCN_AUTOCCANCELLED</a><br />
+ <a class="message" href="#SCN_AUTOCCHARDELETED">SCN_AUTOCCHARDELETED</a><br />
+ </code>
+
+ <p>The following <code>SCI_*</code> messages are associated with these notifications:</p>
+ <code><a class="message" href="#SCI_SETMODEVENTMASK">SCI_SETMODEVENTMASK(int
+ eventMask)</a><br />
+ <a class="message" href="#SCI_GETMODEVENTMASK">SCI_GETMODEVENTMASK</a><br />
+ <a class="message" href="#SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME</a><br />
+ <a class="message" href="#SCI_GETMOUSEDWELLTIME">SCI_GETMOUSEDWELLTIME</a><br />
+ </code>
+
+ <p>The following additional notifications are sent using the <code>WM_COMMAND</code> message on
+ Windows and the "Command" signal on GTK+. This emulates the Windows Edit control. Only the lower
+ 16 bits of the control's ID is passed in these notifications.</p>
+ <code><a class="message" href="#SCEN_CHANGE">SCEN_CHANGE</a><br />
+ <a class="message" href="#SCEN_SETFOCUS">SCEN_SETFOCUS</a><br />
+ <a class="message" href="#SCEN_KILLFOCUS">SCEN_KILLFOCUS</a><br />
+ </code>
+
+ <p><b id="SCN_STYLENEEDED">SCN_STYLENEEDED</b><br />
+ If you used <code><a class="message"
+ href="#SCI_SETLEXER">SCI_SETLEXER</a>(SCLEX_CONTAINER)</code> to make the container act as the
+ lexer, you will receive this notification when Scintilla is about to display or print text that
+ requires styling. You are required to style the text from the line that contains the position
+ returned by <a class="message" href="#SCI_GETENDSTYLED"><code>SCI_GETENDSTYLED</code></a> up to
+ the position passed in <code>SCNotification.position</code>. Symbolically, you need code of the
+ form:</p>
+<pre>
+ startPos = <a class="message" href="#SCI_GETENDSTYLED">SCI_GETENDSTYLED</a>()
+ lineNumber = <a class="message"
+href="#SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION</a>(startPos);
+ startPos = <a class="message"
+href="#SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE</a>(lineNumber);
+ MyStyleRoutine(startPos, SCNotification.position);
+</pre>
+
+ <p><b id="SCN_CHARADDED">SCN_CHARADDED</b><br />
+ This is sent when the user types an ordinary text character (as opposed to a command
+ character) that is entered into the text. The container can use this to decide to display a <a
+ class="jump" href="#CallTips">call tip</a> or an <a class="jump" href="#Autocompletion">auto
+ completion list</a>. The character is in <code>SCNotification.ch</code>.
+ This notification is sent before the character has been styled so processing that depends on
+ styling should instead be performed in the SCN_UPDATEUI notification.</p>
+
+ <p><b id="SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</b><br />
+ <b id="SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</b><br />
+ Sent to the container when the save point is entered or left, allowing the container to
+ display a "document dirty" indicator and change its menus.<br />
+ See also: <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a>, <a
+ class="message" href="#SCI_GETMODIFY"><code>SCI_GETMODIFY</code></a></p>
+
+ <p><b id="SCN_MODIFYATTEMPTRO">SCN_MODIFYATTEMPTRO</b><br />
+ When in read-only mode, this notification is sent to the container if the user tries to change
+ the text. This can be used to check the document out of a version control system. You can set
+ the read-only state of a document with <code><a class="message"
+ href="#SCI_SETREADONLY">SCI_SETREADONLY</a></code>.</p>
+
+ <p><b id="SCN_KEY">SCN_KEY</b><br />
+ Reports all keys pressed but not consumed by Scintilla. Used on GTK+ because of
+ some problems with keyboard focus and is not sent by the Windows version. <code>SCNotification.ch</code> holds the key code and
+ <code>SCNotification.modifiers</code> holds the modifiers. This notification is sent if the
+ modifiers include <code>SCMOD_ALT</code> or <code>SCMOD_CTRL</code> and the key code is less
+ than 256.</p>
+
+ <p><b id="SCN_DOUBLECLICK">SCN_DOUBLECLICK</b><br />
+ The mouse button was double clicked in editor. The <code>position</code> field is set to the text position of the
+ double click and the <code>line</code> field is set to the line of the double click.</p>
+
+ <p><b id="SCN_UPDATEUI">SCN_UPDATEUI</b><br />
+ Either the text or styling of the document has changed or the selection range has changed. Now
+ would be a good time to update any container UI elements that depend on document or view state.
+ This was previously called <code><a class="message"
+ href="#SCN_CHECKBRACE">SCN_CHECKBRACE</a></code> because a common use is to check whether the
+ caret is next to a brace and set highlights on this brace and its corresponding matching brace.
+ This also replaces <a class="message" href="#SCN_POSCHANGED"><code>SCN_POSCHANGED</code></a>,
+ which is now deprecated.</p>
+
+ <p><b id="SCN_MODIFIED">SCN_MODIFIED</b><br />
+ This notification is sent when the text or styling of the document changes or is about to
+ change. You can set a mask for the notifications that are sent to the container with <a
+ class="message" href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>. The
+ notification structure contains information about what changed, how the change occurred and
+ whether this changed the number of lines in the document. No modifications may be performed
+ while in a <code>SCN_MODIFIED</code> event. The <code>SCNotification</code> fields used
+ are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Modify notification types">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>modificationType</code></td>
+
+ <td align="left">A set of flags that identify the change(s) made. See the next
+ table.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>position</code></td>
+
+ <td align="left">Start position of a text or styling change. Set to 0 if not used.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>length</code></td>
+
+ <td align="left">Length of the change in cells or characters when the text or styling
+ changes. Set to 0 if not used.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>linesAdded</code></td>
+
+ <td align="left">Number of added lines. If negative, the number of deleted lines. Set to
+ 0 if not used or no lines added or deleted.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>text</code></td>
+
+ <td align="left">Valid for text changes, not for style changes. If we are collecting undo
+ information this holds a pointer to the text that is handed to the Undo system, otherwise
+ it is zero. For user performed SC_MOD_BEFOREDELETE the text field is 0 and
+ for user performed SC_MOD_BEFOREINSERT the text field points to an array of cells,
+ not bytes and the length is the number of cells.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>line</code></td>
+
+ <td align="left">The line number at which a fold level or marker change occurred. This is
+ 0 if unused and may be -1 if more than one line changed.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>foldLevelNow</code></td>
+
+ <td align="left">The new fold level applied to the line or 0 if this field is
+ unused.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>foldLevelPrev</code></td>
+
+ <td align="left">The previous folding level of the line or 0 if this field is
+ unused.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p>The <code>SCNotification.modificationType</code> field has bits set to tell you what has
+ been done. The <code>SC_MOD_*</code> bits correspond to actions. The
+ <code>SC_PERFORMED_*</code> bits tell you if the action was done by the user, or the result of
+ Undo or Redo of a previous action.</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Modify notification type flags">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+
+ <th>Value</th>
+
+ <th align="left">Meaning</th>
+
+ <th align="left">SCNotification fields</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>SC_MOD_INSERTTEXT</code></td>
+
+ <td align="center">0x01</td>
+
+ <td>Text has been inserted into the document.</td>
+
+ <td><code>position, length, text, linesAdded</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_DELETETEXT</code></td>
+
+ <td align="center">0x02</td>
+
+ <td>Text has been removed from the document.</td>
+
+ <td><code>position, length, text, linesAdded</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_CHANGESTYLE</code></td>
+
+ <td align="center">0x04</td>
+
+ <td>A style change has occurred.</td>
+
+ <td><code>position, length</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_CHANGEFOLD</code></td>
+
+ <td align="center">0x08</td>
+
+ <td>A folding change has occurred.</td>
+
+ <td><code>line, foldLevelNow, foldLevelPrev</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PERFORMED_USER</code></td>
+
+ <td align="center">0x10</td>
+
+ <td>Information: the operation was done by the user.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PERFORMED_UNDO</code></td>
+
+ <td align="center">0x20</td>
+
+ <td>Information: this was the result of an Undo.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_PERFORMED_REDO</code></td>
+
+ <td align="center">0x40</td>
+
+ <td>Information: this was the result of a Redo.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MULTISTEPUNDOREDO</code></td>
+
+ <td align="center">0x80</td>
+
+ <td>This is part of a multi-step Undo or Redo transaction.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_LASTSTEPINUNDOREDO</code></td>
+
+ <td align="center">0x100</td>
+
+ <td>This is the final step in an Undo or Redo transaction.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_CHANGEMARKER</code></td>
+
+ <td align="center">0x200</td>
+
+ <td>One or more markers has changed in a line.</td>
+
+ <td><code>line</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_BEFOREINSERT</code></td>
+
+ <td align="center">0x400</td>
+
+ <td>Text is about to be inserted into the document.</td>
+
+ <td><code>position, if performed by user then text in cells, length in cells</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_BEFOREDELETE</code></td>
+
+ <td align="center">0x800</td>
+
+ <td>Text is about to be deleted from the document.</td>
+
+ <td><code>position, length</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MOD_CHANGEINDICATOR</code></td>
+
+ <td align="center">0x4000</td>
+
+ <td>An indicator has been added or removed from a range of text.</td>
+
+ <td><code>position, length</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code id="SC_MOD_CHANGELINESTATE">SC_MOD_CHANGELINESTATE</code></td>
+
+ <td align="center">0x8000</td>
+
+ <td>A line state has changed because <a class="message" href="#SCI_SETLINESTATE">SCI_SETLINESTATE</a>
+ was called.</td>
+
+ <td><code>line</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code id="SC_MOD_CHANGEMARGIN">SC_MOD_CHANGEMARGIN</code></td>
+
+ <td align="center">0x10000</td>
+
+ <td>A text margin has changed.</td>
+
+ <td><code>line</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code id="SC_MOD_CHANGEANNOTATION">SC_MOD_CHANGEANNOTATION</code></td>
+
+ <td align="center">0x20000</td>
+
+ <td>An annotation has changed.</td>
+
+ <td><code>line</code></td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MULTILINEUNDOREDO</code></td>
+
+ <td align="center">0x1000</td>
+
+ <td>This is part of an Undo or Redo with multi-line changes.</td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_STARTACTION</code></td>
+
+ <td align="center">0x2000</td>
+
+ <td>This is set on a SC_PERFORMED_USER action when it is the
+ first or only step in an undo transaction. This can be used to integrate the Scintilla
+ undo stack with an undo stack in the container application by adding a Scintilla
+ action to the container's stack for the currently opened container transaction or
+ to open a new container transaction if there is no open container transaction.
+ </td>
+
+ <td>None</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code id="SC_MOD_CONTAINER">SC_MOD_CONTAINER</code></td>
+
+ <td align="center">0x40000</td>
+
+ <td>This is set on for actions that the container stored into the undo stack with
+ <a class="message" href="#SCI_ADDUNDOACTION"><code>SCI_ADDUNDOACTION</code></a>.
+ </td>
+
+ <td>token</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>SC_MODEVENTMASKALL</code></td>
+
+ <td align="center">0x7FFFF</td>
+
+ <td>This is a mask for all valid flags. This is the default mask state set by <a
+ class="message" href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>.</td>
+
+ <td>None</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCEN_CHANGE">SCEN_CHANGE</b><br />
+ <code>SCEN_CHANGE</code> (768) is fired when the text (not the style) of the document changes.
+ This notification is sent using the <code>WM_COMMAND</code> message on Windows and the
+ "Command" signal on GTK+ as this is the behavior of the standard Edit control
+ (<code>SCEN_CHANGE</code> has the same value as the Windows Edit control
+ <code>EN_CHANGE</code>). No other information is sent. If you need more detailed information
+ use <a class="message" href="#SCN_MODIFIED"><code>SCN_MODIFIED</code></a>. You can filter the
+ types of changes you are notified about with <a class="message"
+ href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>.</p>
+
+ <p><b id="SCI_SETMODEVENTMASK">SCI_SETMODEVENTMASK(int eventMask)</b><br />
+ <b id="SCI_GETMODEVENTMASK">SCI_GETMODEVENTMASK</b><br />
+ These messages set and get an event mask that determines which document change events are
+ notified to the container with <a class="message"
+ href="#SCN_MODIFIED"><code>SCN_MODIFIED</code></a> and <a class="message"
+ href="#SCEN_CHANGE"><code>SCEN_CHANGE</code></a>. For example, a container may decide to see
+ only notifications about changes to text and not styling changes by calling
+ <code>SCI_SETMODEVENTMASK(SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)</code>.</p>
+
+ <p>The possible notification types are the same as the <code>modificationType</code> bit flags
+ used by <code>SCN_MODIFIED</code>: <code>SC_MOD_INSERTTEXT</code>,
+ <code>SC_MOD_DELETETEXT</code>, <code>SC_MOD_CHANGESTYLE</code>,
+ <code>SC_MOD_CHANGEFOLD</code>, <code>SC_PERFORMED_USER</code>, <code>SC_PERFORMED_UNDO</code>,
+ <code>SC_PERFORMED_REDO</code>, <code>SC_MULTISTEPUNDOREDO</code>,
+ <code>SC_LASTSTEPINUNDOREDO</code>, <code>SC_MOD_CHANGEMARKER</code>,
+ <code>SC_MOD_BEFOREINSERT</code>, <code>SC_MOD_BEFOREDELETE</code>,
+ <code>SC_MULTILINEUNDOREDO</code>, and <code>SC_MODEVENTMASKALL</code>.</p>
+
+ <p><b id="SCEN_SETFOCUS">SCEN_SETFOCUS</b><br />
+ <b id="SCEN_KILLFOCUS">SCEN_KILLFOCUS</b><br />
+ <code>SCEN_SETFOCUS</code> (512) is fired when Scintilla receives focus and
+ <code>SCEN_KILLFOCUS</code> (256) when it loses focus. These notifications are sent using the
+ <code>WM_COMMAND</code> message on Windows and the "Command" signal on GTK+ as this is the
+ behavior of the standard Edit control. Unfortunately, these codes do not match the Windows Edit
+ notification codes <code>EN_SETFOCUS</code> (256) and <code>EN_KILLFOCUS</code> (512). It is
+ now too late to change the Scintilla codes as clients depend on the current values.</p>
+
+ <p><b id="SCN_MACRORECORD">SCN_MACRORECORD</b><br />
+ The <code><a class="message" href="#SCI_STARTRECORD">SCI_STARTRECORD</a></code> and <a
+ class="message" href="#SCI_STOPRECORD"><code>SCI_STOPRECORD</code></a> messages enable and
+ disable macro recording. When enabled, each time a recordable change occurs, the
+ <code>SCN_MACRORECORD</code> notification is sent to the container. It is up to the container
+ to record the action. To see the complete list of <code>SCI_*</code> messages that are
+ recordable, search the Scintilla source <code>Editor.cxx</code> for
+ <code>Editor::NotifyMacroRecord</code>. The fields of <code>SCNotification</code> set in this
+ notification are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Macro record notification data">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>message</code></td>
+
+ <td align="left">The <code>SCI_*</code> message that caused the notification.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>wParam</code></td>
+
+ <td align="left">The value of <code>wParam</code> in the <code>SCI_*</code> message.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>lParam</code></td>
+
+ <td align="left">The value of <code>lParam</code> in the <code>SCI_*</code> message.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCN_MARGINCLICK">SCN_MARGINCLICK</b><br />
+ This notification tells the container that the mouse was clicked inside a <a class="jump"
+ href="#Margins">margin</a> that was marked as sensitive (see <a class="message"
+ href="#SCI_SETMARGINSENSITIVEN"><code>SCI_SETMARGINSENSITIVEN</code></a>). This can be used to
+ perform folding or to place breakpoints. The following <code>SCNotification</code> fields are
+ used:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Margin click notification">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>modifiers</code></td>
+
+ <td align="left">The appropriate combination of <code>SCI_SHIFT</code>,
+ <code>SCI_CTRL</code> and <code>SCI_ALT</code> to indicate the keys that were held down
+ at the time of the margin click.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>position</code></td>
+
+ <td align="left">The position of the start of the line in the document that corresponds
+ to the margin click.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>margin</code></td>
+
+ <td align="left">The margin number that was clicked.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCN_NEEDSHOWN">SCN_NEEDSHOWN</b><br />
+ Scintilla has determined that a range of lines that is currently invisible should be made
+ visible. An example of where this may be needed is if the end of line of a contracted fold
+ point is deleted. This message is sent to the container in case it wants to make the line
+ visible in some unusual way such as making the whole document visible. Most containers will
+ just ensure each line in the range is visible by calling <a class="message"
+ href="#SCI_ENSUREVISIBLE"><code>SCI_ENSUREVISIBLE</code></a>. The <code>position</code> and
+ <code>length</code> fields of <code>SCNotification</code> indicate the range of the document
+ that should be made visible. The container code will be similar to the following code
+ skeleton:</p>
+<pre>
+firstLine = SCI_LINEFROMPOSITION(scn.position)
+lastLine = SCI_LINEFROMPOSITION(scn.position+scn.length-1)
+for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
+</pre>
+
+ <p><b id="SCN_PAINTED">SCN_PAINTED</b><br />
+ Painting has just been done. Useful when you want to update some other widgets based on a
+ change in Scintilla, but want to have the paint occur first to appear more responsive. There is
+ no other information in <code>SCNotification</code>.</p>
+
+ <p><b id="SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</b><br />
+ The user has selected an item in a <a class="jump" href="#UserLists">user list</a>. The
+ <code>SCNotification</code> fields used are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="User list notification">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>wParam</code></td>
+
+ <td align="left">This is set to the <code>listType</code> parameter from the <a
+ class="message" href="#SCI_USERLISTSHOW"><code>SCI_USERLISTSHOW</code></a> message that
+ initiated the list.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>text</code></td>
+
+ <td align="left">The text of the selection.</td>
+ </tr>
+ </tbody>
+ </table>
+ <br />
+ <br />
+
+
+ <p><b id="SCN_URIDROPPED">SCN_URIDROPPED</b><br />
+ Only on the GTK+ version. Indicates that the user has dragged a URI such as a file name or Web
+ address onto Scintilla. The container could interpret this as a request to open the file. The
+ <code>text</code> field of <code>SCNotification</code> points at the URI text.</p>
+
+ <p><b id="SCN_DWELLSTART">SCN_DWELLSTART</b><br />
+ <b id="SCN_DWELLEND">SCN_DWELLEND</b><br />
+ <code>SCN_DWELLSTART</code> is generated when the user keeps the mouse in one position for the
+ dwell period (see <code><a class="message"
+ href="#SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME</a></code>). <code>SCN_DWELLEND</code> is
+ generated after a <code>SCN_DWELLSTART</code> and the mouse is moved or other activity such as
+ key press indicates the dwell is over. Both notifications set the same fields in
+ <code>SCNotification</code>:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Mouse dwell notification">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>position</code></td>
+
+ <td align="left">This is the nearest position in the document to the position where the
+ mouse pointer was lingering.</td>
+ </tr>
+
+ <tr>
+ <td align="left"><code>x, y</code></td>
+
+ <td align="left">Where the pointer lingered. The <code>position</code> field is set to
+ <code><a class="message"
+ href="#SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE</a>(x, y)</code>.</td>
+ </tr>
+ </tbody>
+ </table>
+ <br />
+ <br />
+
+ <p><b id="SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME</b><br />
+ <b id="SCI_GETMOUSEDWELLTIME">SCI_GETMOUSEDWELLTIME</b><br />
+ These two messages set and get the time the mouse must sit still, in milliseconds, to generate
+ a <code><a class="message" href="#SCN_DWELLSTART">SCN_DWELLSTART</a></code> notification. If
+ set to <code>SC_TIME_FOREVER</code>, the default, no dwell events are generated.</p>
+
+ <p><b id="SCN_ZOOM">SCN_ZOOM</b><br />
+ This notification is generated when the user zooms the display using the keyboard or the
+ <code><a class="message" href="#SCI_SETZOOM">SCI_SETZOOM</a></code> method is called. This
+ notification can be used to recalculate positions, such as the width of the line number margin
+ to maintain sizes in terms of characters rather than pixels. <code>SCNotification</code> has no
+ additional information.</p>
+
+ <p>
+ <b id="SCN_HOTSPOTCLICK">SCN_HOTSPOTCLICK</b><br />
+ <b id="SCN_HOTSPOTDOUBLECLICK">SCN_HOTSPOTDOUBLECLICK</b><br />
+ These notifications are generated when the user clicks or double clicks on
+ text that is in a style with the hotspot attribute set.
+ This notification can be used to link to variable definitions or web pages.
+ The <code>position</code> field is set the text position of the click or
+ double click and the <code>modifiers</code> field set to the key modifiers
+ held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.</p>
+
+ <p>
+ <b id="SCN_INDICATORCLICK">SCN_INDICATORCLICK</b><br />
+ <b id="SCN_INDICATORRELEASE">SCN_INDICATORRELEASE</b><br />
+ These notifications are generated when the user clicks or releases the mouse on
+ text that has an indicator.
+ The <code>position</code> field is set the text position of the click or
+ double click and the <code>modifiers</code> field set to the key modifiers
+ held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.</p>
+
+ <p><b id="SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</b><br />
+ This notification is generated when the user clicks on a calltip.
+ This notification can be used to display the next function prototype when a
+ function name is overloaded with different arguments.
+ The <code>position</code> field is set to 1 if the click is in an up arrow,
+ 2 if in a down arrow, and 0 if elsewhere.</p>
+
+ <p><b id="SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</b><br />
+ The user has selected an item in an <a class="jump" href="#Autocompletion">autocompletion list</a>. The
+ notification is sent before the selection is inserted. Automatic insertion can be cancelled by sending a
+ <code><a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a></code> message
+ before returning from the notification. The <code>SCNotification</code> fields used are:</p>
+
+ <table cellpadding="1" cellspacing="2" border="0" summary="Autocompletion list notification">
+ <tbody>
+ <tr>
+ <th align="left">Field</th>
+
+ <th align="left">Usage</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left"><code>lParam</code></td>
+
+ <td align="left">The start position of the word being completed.</td>
+ </tr>
+ <tr>
+ <td align="left"><code>text</code></td>
+
+ <td align="left">The text of the selection.</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <p><b id="SCN_AUTOCCANCELLED">SCN_AUTOCCANCELLED</b><br />
+ The user has cancelled an <a class="jump" href="#Autocompletion">autocompletion list</a>.
+ There is no other information in SCNotification.</p>
+
+ <p><b id="SCN_AUTOCCHARDELETED">SCN_AUTOCCHARDELETED</b><br />
+ The user deleted a character while autocompletion list was active.
+ There is no other information in SCNotification.</p>
+
+ <h2 id="GTK">GTK+</h2>
+ <p>On GTK+, the following functions create a Scintilla widget, communicate with it and allow
+ resources to be released after all Scintilla widgets have been destroyed.</p>
+ <code><a class="message" href="#scintilla_new">GtkWidget *scintilla_new()</a><br />
+ <a class="message" href="#scintilla_set_id">void scintilla_set_id(ScintillaObject *sci, uptr_t id)</a><br />
+ <a class="message" href="#scintilla_send_message">sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)</a><br />
+ <a class="message" href="#scintilla_release_resources">void scintilla_release_resources()</a><br />
+ </code>
+
+ <p><b id="scintilla_new">GtkWidget *scintilla_new()</b></b><br />
+ Create a new Scintilla widget. The returned pointer can be added to a container and displayed in the same way as other
+ widgets.</p>
+
+ <p><b id="scintilla_set_id">void scintilla_set_id(ScintillaObject *sci, uptr_t id)</b></b><br />
+ Set the control ID which will be used in the idFrom field of the NotifyHeader structure of all
+ notifications for this instance. When an application creates multiple Scintilla widgets, this allows
+ the source of each notification to be found. The value should be small, preferrably less than 16 bits,
+ rather than a pointer as some of the functions will only transmit 16 or 32 bits.</p>
+
+ <p><b id="scintilla_send_message">sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)</b><br />
+ The main entry point allows sending any of the messages described in this document.</p>
+
+ <p><b id="scintilla_release_resources">void scintilla_release_resources()</b><br />
+ Call this to free any remaining resources after all the Scintilla widgets have been destroyed.</p>
+
+ <h2 id="DeprecatedMessages">Deprecated messages and notifications</h2>
+
+ <p>The following messages are currently supported to emulate existing Windows controls, but
+ they will be removed in future versions of Scintilla. If you use these messages you should
+ replace them with the Scintilla equivalent.</p>
+<pre>
+WM_GETTEXT(int length, char *text)
+WM_SETTEXT(&lt;unused&gt;, const char *text)
+EM_GETLINE(int line, char *text)
+EM_REPLACESEL(&lt;unused&gt;, const char *text)
+EM_SETREADONLY
+EM_GETTEXTRANGE(&lt;unused&gt;, TEXTRANGE *tr)
+WM_CUT
+WM_COPY
+WM_PASTE
+WM_CLEAR
+WM_UNDO
+EM_CANUNDO
+EM_EMPTYUNDOBUFFER
+WM_GETTEXTLENGTH
+EM_GETFIRSTVISIBLELINE
+EM_GETLINECOUNT
+EM_GETMODIFY
+EM_SETMODIFY(bool isModified)
+EM_GETRECT(RECT *rect)
+EM_GETSEL(int *start, int *end)
+EM_EXGETSEL(&lt;unused&gt;, CHARRANGE *cr)
+EM_SETSEL(int start, int end)
+EM_EXSETSEL(&lt;unused&gt;, CHARRANGE *cr)
+EM_GETSELTEXT(&lt;unused&gt;, char *text)
+EM_LINEFROMCHAR(int position)
+EM_EXLINEFROMCHAR(int position)
+EM_LINEINDEX(int line)
+EM_LINELENGTH(int position)
+EM_SCROLL(int line)
+EM_LINESCROLL(int column, int line)
+EM_SCROLLCARET()
+EM_CANPASTE
+EM_CHARFROMPOS(&lt;unused&gt;, POINT *location)
+EM_POSFROMCHAR(int position, POINT *location)
+EM_SELECTIONTYPE
+EM_HIDESELECTION(bool hide)
+EM_FINDTEXT(int flags, FINDTEXTEX *ft)
+EM_FINDTEXTEX(int flags, FINDTEXTEX *ft)
+EM_GETMARGINS
+EM_SETMARGINS(EC_LEFTMARGIN or EC_RIGHTMARGIN or EC_USEFONTINFO, int val)
+EM_FORMATRANGE
+</pre>
+
+ <p>The following are features that are only included if you define
+ <code>INCLUDE_DEPRECATED_FEATURES</code> in <code>Scintilla.h</code>. To ensure future
+ compatibility you should change them as indicated.</p>
+
+ <p><b id="SCN_POSCHANGED">SCN_POSCHANGED()</b> Deprecated<br />
+ Fired when the user moves the cursor to a different position in the text. Use <a
+ class="message" href="#SCN_UPDATEUI"><code>SCN_UPDATEUI</code></a> instead.</p>
+
+ <p><b id="SCN_CHECKBRACE">SCN_CHECKBRACE</b> Deprecated<br />
+ Either the text or styling of the document has changed or the selection range has changed.
+ This is replaced by <a class="message" href="#SCN_UPDATEUI"><code>SCN_UPDATEUI</code></a>. You
+ can also use <code><a class="message" href="#SCN_MODIFIED">SCN_MODIFIED</a></code> for more
+ detailed information on text and styling changes,</p>
+
+ <h2 id="EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</h2>
+<pre>
+EM_GETWORDBREAKPROC EM_GETWORDBREAKPROCEX
+EM_SETWORDBREAKPROC EM_SETWORDBREAKPROCEX
+EM_GETWORDWRAPMODE EM_SETWORDWRAPMODE
+EM_LIMITTEXT EM_EXLIMITTEXT
+EM_SETRECT EM_SETRECTNP
+EM_FMTLINES
+EM_GETHANDLE EM_SETHANDLE
+EM_GETPASSWORDCHAR EM_SETPASSWORDCHAR
+EM_SETTABSTOPS
+EM_FINDWORDBREAK
+EM_GETCHARFORMAT EM_SETCHARFORMAT
+EM_GETOLEINTERFACE EM_SETOLEINTERFACE
+EM_SETOLECALLBACK
+EM_GETPARAFORMAT EM_SETPARAFORMAT
+EM_PASTESPECIAL
+EM_REQUESTRESIZE
+EM_GETBKGNDCOLOR EM_SETBKGNDCOLOR
+EM_STREAMIN EM_STREAMOUT
+EM_GETIMECOLOR EM_SETIMECOLOR
+EM_GETIMEOPTIONS EM_SETIMEOPTIONS
+EM_GETOPTIONS EM_SETOPTIONS
+EM_GETPUNCTUATION EM_SETPUNCTUATION
+EM_GETTHUMB
+EM_GETEVENTMASK
+EM_SETEVENTMASK
+EM_DISPLAYBAND
+EM_SETTARGETDEVICE
+</pre>
+
+ <p>Scintilla tries to be a superset of the standard windows Edit and RichEdit controls wherever
+ that makes sense. As it is not intended for use in a word processor, some edit messages can not
+ be sensibly handled. Unsupported messages have no effect.</p>
+
+ <h2 id="BuildingScintilla">Building Scintilla</h2>
+
+ <p>To build Scintilla or SciTE, see the README file present in both the Scintilla and SciTE
+ directories. For Windows, GCC 3.2, Borland C++ or Microsoft Visual Studio .NET can be used
+ for building. There is a make file for building Scintilla but not SciTE with Visual C++ 6 at
+ scintilla/win32/scintilla_vc6.mak. For GTK+, GCC 3.1 should be used. GTK+ 1.2x and 2.0x are
+ supported. The version of GTK+ installed should be detected automatically.
+ When both GTK+ 1 and GTK+ 2 are present, building for GTK+ 1.x requires defining GTK1
+ on the command line.</p>
+
+ <h3>Static linking</h3>
+
+ <p>On Windows, Scintilla is normally used as a dynamic library as a .DLL file. If you want to
+ link Scintilla directly into your application .EXE or .DLL file, then the
+ <code>STATIC_BUILD</code> preprocessor symbol should be defined and
+ <code>Scintilla_RegisterClasses</code> called. <code>STATIC_BUILD</code> prevents compiling the
+ <code>DllMain</code> function which will conflict with any <code>DllMain</code> defined in your
+ code. <code>Scintilla_RegisterClasses</code> takes the <code>HINSTANCE</code> of your
+ application and ensures that the "Scintilla" window class is registered. To make sure that the
+ right pointing arrow cursor used in the margin is displayed by Scintilla add the
+ <code>scintilla/win32/Margin.cur</code> file to your application's resources with the ID
+ <code>IDC_MARGIN</code> which is defined in <code>scintilla/win32/platfromRes.h</code> as
+ 400.</p>
+
+ <h3>Ensuring lexers are linked into Scintilla</h3>
+
+ <p>Depending on the compiler and linker used, the lexers may be stripped out. This is most
+ often caused when building a static library. To ensure the lexers are linked in, the
+ <code>Scintilla_LinkLexers()</code> function may be called.</p>
+
+ <h3>Changing set of lexers</h3>
+
+ <p>To change the set of lexers in Scintilla, add and remove lexer source files
+ (<code>Lex*.cxx</code>) from the <code>scintilla/src directory</code> and run the
+ <code>src/LexGen.py</code> script from the <code>src</code> directory to update the make files
+ and <code>KeyWords.cxx</code>. <code>LexGen.py</code> requires Python 2.1 or later. If you do
+ not have access to Python, you can hand edit <code>KeyWords.cxx</code> in a simple-minded way,
+ following the patterns of other lexers. The important thing is to include
+ <code>LINK_LEXER(lmMyLexer);</code> to correspond with the <code>LexerModule
+ lmMyLexer(...);</code> in your lexer source code.</p>
+
+ <h3>Building with an alternative Regular Expression implementation</h3>
+
+ <p id="AlternativeRegEx">A simple interface provides support for switching the Regular Expressions engine at
+ compile time. You must implement <code>RegexSearchBase</code> for your chosen engine,
+ look at the built-in implementation <code>BuiltinRegex</code> to see how this is done.
+ You then need to implement the factory method <code>CreateRegexSearch</code>
+ to create an instance of your class. You must disable the built-in implementation by defining
+ <code>SCI_OWNREGEX</code>.</p>
+
+ </body>
+</html>
+
diff --git a/scintilla/doc/ScintillaDownload.html b/scintilla/doc/ScintillaDownload.html
new file mode 100644
index 0000000..43c0849
--- /dev/null
+++ b/scintilla/doc/ScintillaDownload.html
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Download Scintilla
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Download
+ Scintilla</font></a>
+ </td>
+ </tr>
+ </table>
+ <table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
+ <tr>
+ <td>
+ <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scintilla212.zip?download">
+ Windows</a>&nbsp;&nbsp;
+ <a href="http://prdownloads.sourceforge.net/scintilla/scintilla212.tgz?download">
+ GTK+/Linux</a>&nbsp;&nbsp;
+ </font>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Download.
+ </h2>
+ <p>
+ The <a href="License.txt">license</a> for using Scintilla or SciTE is similar to that of Python
+ containing very few restrictions.
+ </p>
+ <h3>
+ Release 2.12
+ </h3>
+ <h4>
+ Source Code
+ </h4>
+ The source code package contains all of the source code for Scintilla but no binary
+ executable code and is available in
+ <ul>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla212.zip?download">zip format</a> (1160K) commonly used on Windows</li>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla212.tgz?download">tgz format</a> (1080K) commonly used on Linux and compatible operating systems</li>
+ </ul>
+ Instructions for building on both Windows and Linux are included in the readme file.
+ <h4>
+ Windows Executable Code
+ </h4>
+ There is no download available containing only the Scintilla DLL.
+ However, it is included in the <a href="SciTEDownload.html">SciTE
+ executable full download</a> as SciLexer.DLL.
+ <p>
+ <a href="SciTEDownload.html">SciTE</a> is a good demonstration of Scintilla.
+ </p>
+ <p>
+ Previous versions can be downloaded from the <a href="ScintillaHistory.html">history
+ page</a>.
+ </p>
+ </body>
+</html>
diff --git a/scintilla/doc/ScintillaHistory.html b/scintilla/doc/ScintillaHistory.html
new file mode 100644
index 0000000..4caee76
--- /dev/null
+++ b/scintilla/doc/ScintillaHistory.html
@@ -0,0 +1,6780 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>
+ Scintilla and SciTE
+ </title>
+ <style type="text/css">
+ table {
+ border-collapse: collapse;
+ font-size: 80%;
+ }
+ td {
+ xborder: 1px solid #1F1F1F;
+ padding: 0px 4px;
+ }
+ </style>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ and SciTE</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ History of Scintilla and SciTE
+ </h2>
+ <h3>
+ Contributors
+ </h3>
+ <p>
+ Thanks to all the people that have contributed patches, bug reports and suggestions.
+ </p>
+ <p>
+ Source code and documentation have been contributed by
+ </p>
+ <table>
+ <tr>
+ <td>Atsuo Ishimoto</td>
+ <td>Mark Hammond</td>
+ <td>Francois Le Coguiec</td>
+ <td>Dale Nagata</td>
+ </tr><tr>
+ <td>Ralf Reinhardt</td>
+ <td>Philippe Lhoste</td>
+ <td>Andrew McKinlay</td>
+ <td>Stephan R. A. Deibel</td>
+ </tr><tr>
+ <td>Hans Eckardt</td>
+ <td>Vassili Bourdo</td>
+ <td>Maksim Lin</td>
+ <td>Robin Dunn</td>
+ </tr><tr>
+ <td>John Ehresman</td>
+ <td>Steffen Goeldner</td>
+ <td>Deepak S.</td>
+ <td>Yann Gaillard</td>
+ </tr><tr>
+ <td>Aubin Paul</td>
+ <td>Jason Diamond</td>
+ <td>Ahmad Baitalmal</td>
+ <td>Paul Winwood</td>
+ </tr><tr>
+ <td>Maxim Baranov</td>
+ <td>Ragnar Højland</td>
+ <td>Christian Obrecht</td>
+ <td>Andreas Neukoetter</td>
+ </tr><tr>
+ <td>Adam Gates</td>
+ <td>Steve Lhomme</td>
+ <td>Ferdinand Prantl</td>
+ <td>Jan Dries</td>
+ </tr><tr>
+ <td>Markus Gritsch</td>
+ <td>Tahir Karaca</td>
+ <td>Ahmad Zawawi</td>
+ <td>Laurent le Tynevez</td>
+ </tr><tr>
+ <td>Walter Braeu</td>
+ <td>Ashley Cambrell</td>
+ <td>Garrett Serack</td>
+ <td>Holger Schmidt</td>
+ </tr><tr>
+ <td><a href="http://www.activestate.com">ActiveState</a></td>
+ <td>James Larcombe</td>
+ <td>Alexey Yutkin</td>
+ <td>Jan Hercek</td>
+ </tr><tr>
+ <td>Richard Pecl</td>
+ <td>Edward K. Ream</td>
+ <td>Valery Kondakoff</td>
+ <td>Smári McCarthy</td>
+ </tr><tr>
+ <td>Clemens Wyss</td>
+ <td>Simon Steele</td>
+ <td>Serge A. Baranov</td>
+ <td>Xavier Nodet</td>
+ </tr><tr>
+ <td>Willy Devaux</td>
+ <td>David Clain</td>
+ <td>Brendon Yenson</td>
+ <td>Vamsi Potluru</td>
+ </tr><tr>
+ <td>Praveen Ambekar</td>
+ <td>Alan Knowles</td>
+ <td>Kengo Jinno</td>
+ <td>Valentin Valchev</td>
+ </tr><tr>
+ <td>Marcos E. Wurzius</td>
+ <td>Martin Alderson</td>
+ <td>Robert Gustavsson</td>
+ <td>José Fonseca</td>
+ </tr><tr>
+ <td>Holger Kiemes</td>
+ <td>Francis Irving</td>
+ <td>Scott Kirkwood</td>
+ <td>Brian Quinlan</td>
+ </tr><tr>
+ <td>Ubi</td>
+ <td>Michael R. Duerig</td>
+ <td>Deepak T</td>
+ <td>Don Paul Beletsky</td>
+ </tr><tr>
+ <td>Gerhard Kalab</td>
+ <td>Olivier Dagenais</td>
+ <td>Josh Wingstrom</td>
+ <td>Bruce Dodson</td>
+ </tr><tr>
+ <td>Sergey Koshcheyev</td>
+ <td>Chuan-jian Shen</td>
+ <td>Shane Caraveo</td>
+ <td>Alexander Scripnik</td>
+ </tr><tr>
+ <td>Ryan Christianson</td>
+ <td>Martin Steffensen</td>
+ <td>Jakub Vrána</td>
+ <td>The Black Horus</td>
+ </tr><tr>
+ <td>Bernd Kreuss</td>
+ <td>Thomas Lauer</td>
+ <td>Mike Lansdaal</td>
+ <td>Yukihiro Nakai</td>
+ </tr><tr>
+ <td>Jochen Tucht</td>
+ <td>Greg Smith</td>
+ <td>Steve Schoettler</td>
+ <td>Mauritius Thinnes</td>
+ </tr><tr>
+ <td>Darren Schroeder</td>
+ <td>Pedro Guerreiro</td>
+ <td>Dan Petitt</td>
+ <td>Biswapesh Chattopadhyay</td>
+ </tr><tr>
+ <td>Kein-Hong Man</td>
+ <td>Patrizio Bekerle</td>
+ <td>Nigel Hathaway</td>
+ <td>Hrishikesh Desai</td>
+ </tr><tr>
+ <td>Sergey Puljajev</td>
+ <td>Mathias Rauen</td>
+ <td>Angelo Mandato</td>
+ <td>Denis Sureau</td>
+ </tr><tr>
+ <td>Kaspar Schiess</td>
+ <td>Christoph Hösler</td>
+ <td>João Paulo F Farias</td>
+ <td>Ron Schofield</td>
+ </tr><tr>
+ <td>Stefan Wosnik</td>
+ <td>Marius Gheorghe</td>
+ <td>Naba Kumar</td>
+ <td>Sean O'Dell</td>
+ </tr><tr>
+ <td>Stefanos Togoulidis</td>
+ <td>Hans Hagen</td>
+ <td>Jim Cape</td>
+ <td>Roland Walter</td>
+ </tr><tr>
+ <td>Brian Mosher</td>
+ <td>Nicholas Nemtsev</td>
+ <td>Roy Wood</td>
+ <td>Peter-Henry Mander</td>
+ </tr><tr>
+ <td>Robert Boucher</td>
+ <td>Christoph Dalitz</td>
+ <td>April White</td>
+ <td>S. Umar</td>
+ </tr><tr>
+ <td>Trent Mick</td>
+ <td>Filip Yaghob</td>
+ <td>Avi Yegudin</td>
+ <td>Vivi Orunitia</td>
+ </tr><tr>
+ <td>Manfred Becker</td>
+ <td>Dimitris Keletsekis</td>
+ <td>Yuiga</td>
+ <td>Davide Scola</td>
+ </tr><tr>
+ <td>Jason Boggs</td>
+ <td>Reinhold Niesner</td>
+ <td>Jos van der Zande</td>
+ <td>Pescuma</td>
+ </tr><tr>
+ <td>Pavol Bosik</td>
+ <td>Johannes Schmid</td>
+ <td>Blair McGlashan</td>
+ <td>Mikael Hultgren</td>
+ </tr><tr>
+ <td>Florian Balmer</td>
+ <td>Hadar Raz</td>
+ <td>Herr Pfarrer</td>
+ <td>Ben Key</td>
+ </tr><tr>
+ <td>Gene Barry</td>
+ <td>Niki Spahiev</td>
+ <td>Carsten Sperber</td>
+ <td>Phil Reid</td>
+ </tr><tr>
+ <td>Iago Rubio</td>
+ <td>Régis Vaquette</td>
+ <td>Massimo Corà</td>
+ <td>Elias Pschernig</td>
+ </tr><tr>
+ <td>Chris Jones</td>
+ <td>Josiah Reynolds</td>
+ <td>Robert Roessler <a href="http://www.rftp.com">rftp.com</a></td>
+ <td>Steve Donovan</td>
+ </tr><tr>
+ <td>Jan Martin Pettersen</td>
+ <td>Sergey Philippov</td>
+ <td>Borujoa</td>
+ <td>Michael Owens</td>
+ </tr><tr>
+ <td>Franck Marcia</td>
+ <td>Massimo Maria Ghisalberti</td>
+ <td>Frank Wunderlich</td>
+ <td>Josepmaria Roca</td>
+ </tr><tr>
+ <td>Tobias Engvall</td>
+ <td>Suzumizaki Kimitaka</td>
+ <td>Michael Cartmell</td>
+ <td>Pascal Hurni</td>
+ </tr><tr>
+ <td>Andre</td>
+ <td>Randy Butler</td>
+ <td>Georg Ritter</td>
+ <td>Michael Goffioul</td>
+ </tr><tr>
+ <td>Ben Harper</td>
+ <td>Adam Strzelecki</td>
+ <td>Kamen Stanev</td>
+ <td>Steve Menard</td>
+ </tr><tr>
+ <td>Oliver Yeoh</td>
+ <td>Eric Promislow</td>
+ <td>Joseph Galbraith</td>
+ <td>Jeffrey Ren</td>
+ </tr><tr>
+ <td>Armel Asselin</td>
+ <td>Jim Pattee</td>
+ <td>Friedrich Vedder</td>
+ <td>Sebastian Pipping</td>
+ </tr><tr>
+ <td>Andre Arpin</td>
+ <td>Stanislav Maslovski</td>
+ <td>Martin Stone</td>
+ <td>Fabien Proriol</td>
+ </tr><tr>
+ <td>mimir</td>
+ <td>Nicola Civran</td>
+ <td>Snow</td>
+ <td>Mitchell Foral</td>
+ </tr><tr>
+ <td>Pieter Holtzhausen</td>
+ <td>Waldemar Augustyn</td>
+ <td>Jason Haslam</td>
+ <td>Sebastian Steinlechner</td>
+ </tr><tr>
+ <td>Chris Rickard</td>
+ <td>Rob McMullen</td>
+ <td>Stefan Schwendeler</td>
+ <td>Cristian Adam</td>
+ </tr><tr>
+ <td>Nicolas Chachereau</td>
+ <td>Istvan Szollosi</td>
+ <td>Xie Renhui</td>
+ <td>Enrico Tröger</td>
+ </tr><tr>
+ <td>Todd Whiteman</td>
+ <td>Yuval Papish</td>
+ <td>instanton</td>
+ <td>Sergio Lucato</td>
+ </tr><tr>
+ <td>VladVRO</td>
+ <td>Dmitry Maslov</td>
+ <td>chupakabra</td>
+ <td>Juan Carlos Arevalo Baeza</td>
+ </tr><tr>
+ <td>Nick Treleaven</td>
+ <td>Stephen Stagg</td>
+ <td>Jean-Paul Iribarren</td>
+ <td>Tim Gerundt</td>
+ </tr><tr>
+ <td>Sam Harwell</td>
+ <td>Boris</td>
+ <td>Jason Oster</td>
+ <td>Gertjan Kloosterman</td>
+ </tr><tr>
+ <td>alexbodn</td>
+ <td>Sergiu Dotenco</td>
+ <td>Anders Karlsson</td>
+ <td>ozlooper</td>
+ </tr><tr>
+ <td>Marko Njezic</td>
+ <td>Eugen Bitter</td>
+ <td>Christoph Baumann</td>
+ <td>Christopher Bean</td>
+ </tr><tr>
+ <td>Sergey Kishchenko</td>
+ <td>Kai Liu</td>
+ <td>Andreas Rumpf</td>
+ <td>James Moffatt</td>
+ </tr><tr>
+ <td>Yuzhou Xin</td>
+ <td>Nic Jansma</td>
+ <td>Evan Jones</td>
+ <td>Mike Lischke</td>
+ </tr><tr>
+ <td>Eric Kidd</td>
+ <td>maXmo</td>
+ <td>David Severwright</td>
+ <td>Jon Strait</td>
+ </tr><tr>
+ <td>Oliver Kiddle</td>
+ <td>Etienne Girondel</td>
+ <td>Haimag Ren</td>
+ <td>Andrey Moskalyov</td>
+ </tr><tr>
+ <td>Xavi</td>
+ </tr>
+ </table>
+ <p>
+ Images used in GTK+ version
+ </p>
+ <ul>
+ <li>
+ <a href="http://sourceforge.net/projects/icon-collection/">
+ Icons</a> Copyright(C) 1998 by Dean S. Jones<br />
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite212.zip?download">Release 2.12</a>
+ </h3>
+ <ul>
+ <li>
+ Released 1 June 2010.
+ </li>
+ <li>
+ Drawing optimizations improve speed and fix some visible flashing when scrolling.
+ </li>
+ <li>
+ Copy Path command added to File menu in SciTE.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2986745&group_id=2439">Feature #2986745.</a>
+ </li>
+ <li>
+ Optional warning displayed by SciTE when saving a file which has been modified by another process.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2975041&group_id=2439">Feature #2975041.</a>
+ </li>
+ <li>
+ Flagship lexer for xBase languages updated to follow the language much more closely.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2992689&group_id=2439">Feature #2992689.</a>
+ </li>
+ <li>
+ HTML lexer highlights Django templates in more regions.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3002874&group_id=2439">Feature #3002874.</a>
+ </li>
+ <li>
+ Dropping files on SciTE on Windows, releases the drag object earlier and opens the files asynchronously,
+ leading to smoother user experience.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2986724&group_id=2439">Feature #2986724.</a>
+ </li>
+ <li>
+ SciTE HTML exports take the Use Monospaced Font setting into account.
+ </li>
+ <li>
+ SciTE window title "[n of m]" localised.
+ </li>
+ <li>
+ When new line inserted at start of line, markers are moved down.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2986727&group_id=2439">Bug #2986727.</a>
+ </li>
+ <li>
+ On Windows, dropped text has its line ends converted, similar to pasting.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3005328&group_id=2439">Bug #3005328.</a>
+ </li>
+ <li>
+ Fixed bug with middle-click paste in block select mode where text was pasted next to selection rather than at cursor.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2984460&group_id=2439">Bug #2984460.</a>
+ </li>
+ <li>
+ Fixed SciTE crash where a style had a size parameter without a value.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3003834&group_id=2439">Bug #3003834.</a>
+ </li>
+ <li>
+ Debug assertions in multiple lexers fixed.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3000566&group_id=2439">Bug #3000566.</a>
+ </li>
+ <li>
+ CSS lexer fixed bug where @font-face displayed incorrectly
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2994224&group_id=2439">Bug #2994224.</a>
+ </li>
+ <li>
+ CSS lexer fixed bug where open comment caused highlighting error.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1683672&group_id=2439">Bug #1683672.</a>
+ </li>
+ <li>
+ Shell file lexer fixed highlight glitch with here docs where the first line is a comment.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830239&group_id=2439">Bug #2830239.</a>
+ </li>
+ <li>
+ Bug fixed in SciTE openpath property that caused Open Selected File to fail to open the selected file.
+ </li>
+ <li>
+ Bug fixed in SciTE FileExt property when file name with no extension evaluated to whole path.
+ </li>
+ <li>
+ Fixed SciTE on Windows printing bug where the $(CurrentTime), $(CurrentPage) variables were not expanded.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2994612&group_id=2439">Bug #2994612.</a>
+ </li>
+ <li>
+ SciTE compiles for 64-bit Windows and runs without crashing.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2986312&group_id=2439">Bug #2986312.</a>
+ </li>
+ <li>
+ Full Screen mode in Windows Vista/7 improved to hide Start button and size borders a little better.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3002813&group_id=2439">Bug #3002813.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite211.zip?download">Release 2.11</a>
+ </h3>
+ <ul>
+ <li>
+ Released 9 April 2010.
+ </li>
+ <li>
+ Fixes compatibility of Scintilla.h with the C language.
+ </li>
+ <li>
+ With a rectangular selection SCI_GETSELECTIONSTART and SCI_GETSELECTIONEND return limits of the
+ rectangular selection rather than the limits of the main selection.
+ </li>
+ <li>
+ When SciTE on Windows is minimized to tray, only takes a single click to restore rather than a double click.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=981917&group_id=2439">Feature #981917.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite210.zip?download">Release 2.10</a>
+ </h3>
+ <ul>
+ <li>
+ Released 4 April 2010.
+ </li>
+ <li>
+ Version 1.x of GTK+ is no longer supported.
+ </li>
+ <li>
+ SciTE is no longer supported on Windows 95, 98 or ME.
+ </li>
+ <li>
+ Case-insensitive search works for non-ASCII characters in UTF-8 and 8-bit encodings.
+ Non-regex search in DBCS encodings is always case-sensitive.
+ </li>
+ <li>
+ Non-ASCII characters may be changed to upper and lower case.
+ </li>
+ <li>
+ SciTE on Windows can access all files including those with names outside the user's preferred character encoding.
+ </li>
+ <li>
+ SciTE may be extended with lexers written in Lua.
+ </li>
+ <li>
+ When there are multiple selections, the paste command can go either to the main selection or to each
+ selection. This is controlled with SCI_SETMULTIPASTE.
+ </li>
+ <li>
+ More forms of bad UTF-8 are detected including overlong sequences, surrogates, and characters outside
+ the valid range. Bad UTF-8 bytes are now displayed as 2 hex digits preceded by 'x'.
+ </li>
+ <li>
+ SCI_GETTAG retrieves the value of captured expressions within regular expression searches.
+ </li>
+ <li>
+ Django template highlighting added to the HTML lexer.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2974889&group_id=2439">Feature #2974889.</a>
+ </li>
+ <li>
+ Verilog line comments can be folded.
+ </li>
+ <li>
+ SciTE on Windows allows specifying a filter for the Save As dialog.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2943445&group_id=2439">Feature #2943445.</a>
+ </li>
+ <li>
+ Bug fixed when multiple selection disabled where rectangular selections could be expanded into multiple selections.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2948260&group_id=2439">Bug #2948260.</a>
+ </li>
+ <li>
+ Bug fixed when document horizontally scrolled and up/down-arrow did not return to the same
+ column after horizontal scroll occurred.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2950799&group_id=2439">Bug #2950799.</a>
+ </li>
+ <li>
+ Bug fixed to remove hotspot highlight when mouse is moved out of the document. Windows only fix.
+ <a href="https://sourceforge.net/tracker/?func=detail&aid=2951353&group_id=2439&atid=102439">Bug #2951353.</a>
+ </li>
+ <li>
+ R lexer now performs case-sensitive check for keywords.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2956543&group_id=2439">Bug #2956543.</a>
+ </li>
+ <li>
+ Bug fixed on GTK+ where text disappeared when a wrap occurred.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2958043&group_id=2439">Bug #2958043.</a>
+ </li>
+ <li>
+ Bug fixed where regular expression replace cannot escape the '\' character by using '\\'.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2959876&group_id=2439">Bug #2959876.</a>
+ </li>
+ <li>
+ Bug fixed on GTK+ when virtual space disabled, middle-click could still paste text beyond end of line.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2971618&group_id=2439">Bug #2971618.</a>
+ </li>
+ <li>
+ SciTE crash fixed when double clicking on a malformed error message in the output pane.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2976551&group_id=2439">Bug #2976551.</a>
+ </li>
+ <li>
+ Improved performance on GTK+ when changing parameters associated with scroll bars to the same value.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2964357&group_id=2439">Bug #2964357.</a>
+ </li>
+ <li>
+ Fixed bug with pressing Shift+Tab with a rectangular selection so that it performs an un-indent
+ similar to how Tab performs an indent.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite203.zip?download">Release 2.03</a>
+ </h3>
+ <ul>
+ <li>
+ Released 14 February 2010.
+ </li>
+ <li>
+ Added SCI_SETFIRSTVISIBLELINE to match SCI_GETFIRSTVISIBLELINE.
+ </li>
+ <li>
+ Erlang lexer extended set of numeric bases recognised; separate style for module:function_name; detects
+ built-in functions, known module attributes, and known preprocessor instructions; recognizes EDoc and EDoc macros;
+ separates types of comments.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2942448&group_id=2439">Bug #2942448.</a>
+ </li>
+ <li>
+ Python lexer extended with lexer.python.strings.over.newline option that allows non-triple-quoted strings to extend
+ past line ends. This allows use of the Ren'Py language.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2945550&group_id=2439">Feature #2945550.</a>
+ </li>
+ <li>
+ Fixed bugs with cursor movement after deleting a rectangular selection.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2942131&group_id=2439">Bug #2942131.</a>
+ </li>
+ <li>
+ Fixed bug where calling SCI_SETSEL when there is a rectangular selection left
+ the additional selections selected.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2947064&group_id=2439">Bug #2947064.</a>
+ </li>
+ <li>
+ Fixed macro recording bug where not all bytes in multi-byte character insertions were reported through
+ SCI_REPLACESEL.
+ </li>
+ <li>
+ Fixed SciTE bug where using Ctrl+Enter followed by Ctrl+Space produced an autocompletion list
+ with only a single line containing all the identifiers.
+ </li>
+ <li>
+ Fixed SciTE on GTK+ bug where running a tool made the user interface completely unresponsive.
+ </li>
+ <li>
+ Fixed SciTE on Windows Copy to RTF bug.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2108574&group_id=2439">Bug #2108574.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite202.zip?download">Release 2.02</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 25 January 2010.
+ </li>
+ <li>
+ Markdown lexer added.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2844081&group_id=2439">Feature #2844081.</a>
+ </li>
+ <li>
+ On GTK+, include code that understands the ranges of lead bytes for code pages 932, 936, and 950
+ so that most Chinese and Japanese text can be used on systems that are not set to the corresponding locale.
+ </li>
+ <li>
+ Allow changing the size of dots in visible whitespace using SCI_SETWHITESPACESIZE.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2839427&group_id=2439">Feature #2839427.</a>
+ </li>
+ <li>
+ Additional carets can be hidden with SCI_SETADDITIONALCARETSVISIBLE.
+ </li>
+ <li>
+ Can choose anti-aliased, non-anti-aliased or lcd-optimized text using SCI_SETFONTQUALITY.
+ </li>
+ <li>
+ Retrieve the current selected text in the autocompletion list with SCI_AUTOCGETCURRENTTEXT.
+ </li>
+ <li>
+ Retrieve the name of the current lexer with SCI_GETLEXERLANGUAGE.
+ </li>
+ <li>
+ Progress 4GL lexer improves handling of comments in preprocessor declaration.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2902206&group_id=2439">Feature #2902206.</a>
+ </li>
+ <li>
+ HTML lexer extended to handle Mako template language.
+ </li>
+ <li>
+ SQL folder extended for SQL Anywhere "EXISTS" and "ENDIF" keywords.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2887524&group_id=2439">Feature #2887524.</a>
+ </li>
+ <li>
+ SciTE adds APIPath and AbbrevPath variables.
+ </li>
+ <li>
+ SciTE on GTK+ uses pipes instead of temporary files for running tools. This should be more secure.
+ </li>
+ <li>
+ Fixed crash when calling SCI_STYLEGETFONT for a style which does not have a font set.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2857425&group_id=2439">Bug #2857425.</a>
+ </li>
+ <li>
+ Fixed crash caused by not having sufficient styles allocated after choosing a lexer.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2881279&group_id=2439">Bug #2881279.</a>
+ </li>
+ <li>
+ Fixed crash in SciTE using autocomplete word when word characters includes space.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2840141&group_id=2439">Bug #2840141.</a>
+ </li>
+ <li>
+ Fixed bug with handling upper-case file extensions SciTE on GTK+.
+ </li>
+ <li>
+ Fixed SciTE loading files from sessions with folded folds where it would not
+ be scrolled to the correct location.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2882775&group_id=2439">Bug #2882775.</a>
+ </li>
+ <li>
+ Fixed SciTE loading files from sessions when file no longer exists.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2883437&group_id=2439">Bug #2883437.</a>
+ </li>
+ <li>
+ Fixed SciTE export to HTML using the wrong background colour.
+ </li>
+ <li>
+ Fixed crash when adding an annotation and then adding a new line after the annotation.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2929708&group_id=2439">Bug #2929708.</a>
+ </li>
+ <li>
+ Fixed crash in SciTE setting a property to nil from Lua.
+ </li>
+ <li>
+ SCI_GETSELTEXT fixed to return correct length.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2929441&group_id=2439">Bug #2929441.</a>
+ </li>
+ <li>
+ Fixed text positioning problems with selection in some circumstances.
+ </li>
+ <li>
+ Fixed text positioning problems with ligatures on GTK+.
+ </li>
+ <li>
+ Fixed problem pasting into rectangular selection with caret at bottom caused text to go from the caret down
+ rather than replacing the selection.
+ </li>
+ <li>
+ Fixed problem replacing in a rectangular selection where only the final line was changed.
+ </li>
+ <li>
+ Fixed inability to select a rectangular area using Alt+Shift+Click at both corners.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2899746&group_id=2439">Bug #2899746.</a>
+ </li>
+ <li>
+ Fixed problem moving to start/end of a rectangular selection with left/right key.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2871358&group_id=2439">Bug #2871358.</a>
+ </li>
+ <li>
+ Fixed problem with Select All when there's a rectangular selection.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2930488&group_id=2439">Bug #2930488.</a>
+ </li>
+ <li>
+ Fixed SCI_LINEDUPLICATE on a rectangular selection to not produce multiple discontinuous selections.
+ </li>
+ <li>
+ Virtual space removed when performing delete word left or delete line left.
+ Virtual space converted to real space for delete word right.
+ Preserve virtual space when pressing Delete key.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2882566&group_id=2439">Bug #2882566.</a>
+ </li>
+ <li>
+ Fixed problem where Shift+Alt+Down did not move through wrapped lines.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2871749&group_id=2439">Bug #2871749.</a>
+ </li>
+ <li>
+ Fixed incorrect background colour when using coloured lines with virtual space.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2914691&group_id=2439">Bug #2914691.</a>
+ </li>
+ <li>
+ Fixed failure to display wrap symbol for SC_WRAPVISUALFLAGLOC_END_BY_TEXT.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2936108&group_id=2439">Bug #2936108.</a>
+ </li>
+ <li>
+ Fixed blank background colour with EOLFilled style on last line.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2890105&group_id=2439">Bug #2890105.</a>
+ </li>
+ <li>
+ Fixed problem in VB lexer with keyword at end of file.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2901239&group_id=2439">Bug #2901239.</a>
+ </li>
+ <li>
+ Fixed SciTE bug where double clicking on a tab closed the file.
+ </li>
+ <li>
+ Fixed SciTE brace matching commands to only work when the caret is next to the brace, not when
+ it is in virtual space.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2885560&group_id=2439">Bug #2885560.</a>
+ </li>
+ <li>
+ Fixed SciTE on Windows Vista to access files in the Program Files directory rather than allow Windows
+ to virtualize access.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2916685&group_id=2439">Bug #2916685.</a>
+ </li>
+ <li>
+ Fixed NSIS folder to handle keywords that start with '!'.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2872157&group_id=2439">Bug #2872157.</a>
+ </li>
+ <li>
+ Changed linkage of Scintilla_LinkLexers to "C" so that it can be used by clients written in C.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2844718&group_id=2439">Bug #2844718.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite201.zip?download">Release 2.01</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 19 August 2009.
+ </li>
+ <li>
+ Fix to positioning rectangular paste when viewing line ends.
+ </li>
+ <li>
+ Don't insert new lines and indentation for line ends at end of rectangular paste.
+ </li>
+ <li>
+ When not in additional selection typing mode, cutting a rectangular selection removes all of the selected text.
+ </li>
+ <li>
+ Rectangular selections are copied to the clipboard in document order, not in the order of selection.
+ </li>
+ <li>
+ SCI_SETCURRENTPOS and SCI_SETANCHOR work in rectangular mode.
+ </li>
+ <li>
+ On GTK+, drag and drop to a later position in the document now drops at the position.
+ </li>
+ <li>
+ Fix bug where missing property did not use default value.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite200.zip?download">Release 2.0</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 11 August 2009.
+ </li>
+ <li>
+ Multiple pieces of text can be selected simultaneously by holding control while dragging the mouse.
+ Typing, backspace and delete may affect all selections together.
+ </li>
+ <li>
+ Virtual space allows selecting beyond the last character on a line.
+ </li>
+ <li>
+ SciTE on GTK+ path bar is now optional and defaults to off.
+ </li>
+ <li>
+ MagikSF lexer recognises numbers correctly.
+ </li>
+ <li>
+ Folding of Python comments and blank lines improved. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=210240&group_id=2439">Bug #210240.</a>
+ </li>
+ <li>
+ Bug fixed where background colour of last character in document leaked past that character.
+ </li>
+ <li>
+ Crash fixed when adding marker beyond last line in document. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830307&group_id=2439">Bug #2830307.</a>
+ </li>
+ <li>
+ Resource leak fixed in SciTE for Windows when printing fails. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2816524&group_id=2439">Bug #2816524.</a>
+ </li>
+ <li>
+ Bug fixed on Windows where the system caret was destroyed during destruction when another window
+ was using the system caret. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830223&group_id=2439">Bug #2830223.</a>
+ </li>
+ <li>
+ Bug fixed where indentation guides were drawn over text when the indentation used a style with a different
+ space width to the default style.
+ </li>
+ <li>
+ SciTE bug fixed where box comment added a bare line feed rather than the chosen line end. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2818104&group_id=2439">Bug #2818104.</a>
+ </li>
+ <li>
+ Reverted fix that led to wrapping whole document when displaying the first line of the document.
+ </li>
+ <li>
+ Export to LaTeX in SciTE fixed to work in more cases and not use as much space. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1286548&group_id=2439">Bug #1286548.</a>
+ </li>
+ <li>
+ Bug fixed where EN_CHANGE notification was sent when performing a paste operation in a
+ read-only document. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2825485&group_id=2439">Bug #2825485.</a>
+ </li>
+ <li>
+ Refactored code so that Scintilla exposes less of its internal implementation and uses the C++ standard
+ library for some basic collections. Projects that linked to Scintilla's SString or PropSet classes
+ should copy this code from a previous version of Scintilla or from SciTE.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite179.zip?download">Release 1.79</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 July 2009.
+ </li>
+ <li>
+ Memory exhaustion and other exceptions handled by placing an error value into the
+ status property rather than crashing.
+ Scintilla now builds with exception handling enabled and requires exception handling to be enabled. <br />
+ This is a major change and application developers should consider how they will deal with Scintilla exhausting
+ memory since Scintilla may not be in a stable state.
+ </li>
+ <li>
+ Deprecated APIs removed. The symbols removed are:
+ <ul>
+ <li>SCI_SETCARETPOLICY</li>
+<li> CARET_CENTER</li>
+<li> CARET_XEVEN</li>
+<li> CARET_XJUMPS</li>
+<li> SC_FOLDFLAG_BOX</li>
+<li> SC_FOLDLEVELBOXHEADERFLAG</li>
+<li> SC_FOLDLEVELBOXFOOTERFLAG</li>
+<li> SC_FOLDLEVELCONTRACTED</li>
+<li> SC_FOLDLEVELUNINDENT</li>
+<li> SCN_POSCHANGED</li>
+<li> SCN_CHECKBRACE</li>
+<li> SCLEX_ASP</li>
+<li> SCLEX_PHP</li>
+</ul>
+ </li>
+ <li>
+ Cocoa platform added.
+ </li>
+ <li>
+ Names of struct types in Scintilla.h now start with "Sci_" to avoid possible clashes with platform
+ definitions. Currently, the old names still work but these will be phased out.
+ </li>
+ <li>
+ When lines are wrapped, subsequent lines may be indented to match the indent of the initial line,
+ or one more indentation level. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2796119&group_id=2439">Feature #2796119.</a>
+ </li>
+ <li>
+ APIs added for finding the character at a point rather than an inter-character position. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2646738&group_id=2439">Feature #2646738.</a>
+ </li>
+ <li>
+ A new marker SC_MARK_BACKGROUND_UNDERLINE is drawn in the text area as an underline
+ the full width of the window.
+ </li>
+ <li>
+ Batch file lexer understands variables surrounded by '!'.
+ </li>
+ <li>
+ CAML lexer also supports SML.
+ </li>
+ <li>
+ D lexer handles string and numeric literals more accurately. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2793782&group_id=2439">Feature #2793782.</a>
+ </li>
+ <li>
+ Forth lexer is now case-insensitive and better supports numbers like $hex and %binary. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2804894&group_id=2439">Feature #2804894.</a>
+ </li>
+ <li>
+ Lisp lexer treats '[', ']', '{', and '}' as balanced delimiters which is common usage. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2794989&group_id=2439">Feature #2794989.</a>
+ <br />
+ It treats keyword argument names as being equivalent to symbols. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2794901&group_id=2439">Feature #2794901.</a>
+ </li>
+ <li>
+ Pascal lexer bug fixed to prevent hang when 'interface' near beginning of file. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2802863&group_id=2439">Bug #2802863.</a>
+ </li>
+ <li>
+ Perl lexer bug fixed where previous lexical states persisted causing "/" special case styling and
+ subroutine prototype styling to not be correct. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2809168&group_id=2439">Bug #2809168.</a>
+ </li>
+ <li>
+ XML lexer fixes bug where Unicode entities like '&amp;—' were broken into fragments. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2804760&group_id=2439">Bug #2804760.</a>
+ </li>
+ <li>
+ SciTE on GTK+ enables scrolling the tab bar on recent versions of GTK+. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2061821&group_id=2439">Feature #2061821.</a>
+ </li>
+ <li>
+ SciTE on Windows allows tab bar tabs to be reordered by drag and drop.
+ </li>
+ <li>
+ Unit test script for Scintilla on Windows included with source code.
+ </li>
+ <li>
+ User defined menu items are now localised when there is a matching translation.
+ </li>
+ <li>
+ Width of icon column of autocompletion lists on GTK+ made more consistent.
+ </li>
+ <li>
+ Bug with slicing UTF-8 text into character fragments when there is a sequence of 100 or more 3 byte characters. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2780566&group_id=2439">Bug #2780566.</a>
+ </li>
+ <li>
+ Folding bugs introduced in 1.78 fixed. Some of the fix was generic and there was also a specific fix for C++.
+ </li>
+ <li>
+ Bug fixed where a rectangular paste was not padding the line with sufficient spaces to align the pasted text.
+ </li>
+ <li>
+ Bug fixed with showing all text on each line of multi-line annotations when styling the whole annotation using SCI_ANNOTATIONSETSTYLE. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2789430&group_id=2439">Bug #2789430.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite178.zip?download">Release 1.78</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 28 April 2009.
+ </li>
+ <li>
+ Annotation lines may be added to each line.
+ </li>
+ <li>
+ A text margin may be defined with different text on each line.
+ </li>
+ <li>
+ Application actions may be added to the undo history.
+ </li>
+ <li>
+ Can query the symbol defined for a marker.
+ An available symbol added for applications to indicate that plugins may allocate a marker.
+ </li>
+ <li>
+ Can increase the amount of font ascent and descent.
+ </li>
+ <li>
+ COBOL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
+ </li>
+ <li>
+ Nimrod lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2642620&group_id=2439">Feature #2642620.</a>
+ </li>
+ <li>
+ PowerPro lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2195308&group_id=2439">Feature #2195308.</a>
+ </li>
+ <li>
+ SML lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2710950&group_id=2439">Feature #2710950.</a>
+ </li>
+ <li>
+ SORCUS Installation file lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2343375&group_id=2439">Feature #2343375.</a>
+ </li>
+ <li>
+ TACL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
+ </li>
+ <li>
+ TAL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
+ </li>
+ <li>
+ Rewritten Pascal lexer with improved folding and other fixes. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2190650&group_id=2439">Feature #2190650.</a>
+ </li>
+ <li>
+ INDIC_ROUNDBOX translucency level can be modified. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2586290&group_id=2439">Feature #2586290.</a>
+ </li>
+ <li>
+ C++ lexer treats angle brackets in #include directives as quotes when styling.within.preprocessor. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2551033&group_id=2439">Bug #2551033.</a>
+ </li>
+ <li>
+ Inno Setup lexer is sensitive to whether within the [Code] section and handles comments better. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2552973&group_id=2439">Bug #2552973.</a>
+ </li>
+ <li>
+ HTML lexer does not go into script mode when script tag is self-closing.
+ </li>
+ <li>
+ HTML folder fixed where confused by comments when fold.html.preprocessor off. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2532774&group_id=2439">Bug #2532774.</a>
+ </li>
+ <li>
+ Perl lexer fixes problem with string matching caused by line endings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2648342&group_id=2439">Bug #2648342.</a>
+ </li>
+ <li>
+ Progress lexer fixes problem with "last-event:function" phrase. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2483619&group_id=2439">Bug #2483619.</a>
+ </li>
+ <li>
+ Properties file lexer extended to handle RFC2822 text when lexer.props.allow.initial.spaces on.
+ </li>
+ <li>
+ Python lexer adds options for Python 3 and Cython.
+ </li>
+ <li>
+ Shell lexer fixes heredoc problem caused by line endings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2635257&group_id=2439">Bug #2635257.</a>
+ </li>
+ <li>
+ TeX lexer handles comment at end of line correctly. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2698766&group_id=2439">Bug #2698766.</a>
+ </li>
+ <li>
+ SciTE retains selection range when performing a replace selection command. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2339160&group_id=2439">Feature #2339160.</a>
+ </li>
+ <li>
+ SciTE definition of word characters fixed to match documentaiton. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2464531&group_id=2439">Bug #2464531.</a>
+ </li>
+ <li>
+ SciTE on GTK+ performing Search or Replace when dialog already shown now brings dialog to foreground.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2634224&group_id=2439">Bug #2634224.</a>
+ </li>
+ <li>
+ Fixed encoding bug with calltips on GTK+.
+ </li>
+ <li>
+ Block caret drawn in correct place on wrapped lines. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2126144&group_id=2439">Bug #2126144.</a>
+ </li>
+ <li>
+ Compilation for 64 bit Windows works using MinGW. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2515578&group_id=2439">Bug #2515578.</a>
+ </li>
+ <li>
+ Incorrect memory freeing fixed on OS X.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2354098&group_id=2439">Bug #2354098</a>,
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2671749&group_id=2439">Bug #2671749.</a>
+ </li>
+ <li>
+ SciTE on GTK+ crash fixed on startup when child process exits before initialisation complete.
+ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2716987&group_id=2439">Bug #2716987.</a>
+ </li>
+ <li>
+ Crash fixed when AutoCompleteGetCurrent called with no active autocompletion.
+ </li>
+ <li>
+ Flickering diminished when pressing Tab. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2723006&group_id=2439">Bug #2723006.</a>
+ </li>
+ <li>
+ Namespace compilation issues with GTK+ on OS X fixed.
+ </li>
+ <li>
+ Increased maximum length of SciTE's Language menu on GTK+ to 100 items. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2528241&group_id=2439">Bug #2528241.</a>
+ </li>
+ <li>
+ Fixed incorrect Python lexing for multi-line continued strings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2450963&group_id=2439">Bug #2450963.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite177.zip?download">Release 1.77</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 18 October 2008.
+ </li>
+ <li>
+ Direct temporary access to Scintilla's text buffer to allow simple efficient interfacing
+ to libraries like regular expression libraries.
+ </li>
+ <li>
+ Scintilla on Windows can interpret keys as Unicode even when a narrow character
+ window with SCI_SETKEYSUNICODE.
+ </li>
+ <li>
+ Notification sent when autocompletion cancelled.
+ </li>
+ <li>
+ MySQL lexer added.
+ </li>
+ <li>
+ Lexer for gettext .po files added.
+ </li>
+ <li>
+ Abaqus lexer handles program structure more correctly.
+ </li>
+ <li>
+ Assembler lexer works with non-ASCII text.
+ </li>
+ <li>
+ C++ lexer allows mixed case doc comment tags.
+ </li>
+ <li>
+ CSS lexer updated and works with non-ASCII.
+ </li>
+ <li>
+ Diff lexer adds style for changed lines, handles subversion diffs better and
+ fixes styling and folding for lines containing chunk dividers ("---").
+ </li>
+ <li>
+ FORTRAN lexer accepts more styles of compiler directive.
+ </li>
+ <li>
+ Haskell lexer allows hexadecimal literals.
+ </li>
+ <li>
+ HTML lexer improves PHP and JavaScript folding.
+ PHP heredocs, nowdocs, strings and comments processed more accurately.
+ Internet Explorer's non-standard &gt;comment&lt; tag supported.
+ Script recognition in XML can be controlled with lexer.xml.allow.scripts property.
+ </li>
+ <li>
+ Lua lexer styles last character correctly.
+ </li>
+ <li>
+ Perl lexer update.
+ </li>
+ <li>
+ Comment folding implemented for Ruby.
+ </li>
+ <li>
+ Better TeX folding.
+ </li>
+ <li>
+ Verilog lexer updated.
+ </li>
+ <li>
+ Windows Batch file lexer handles %~ and %*.
+ </li>
+ <li>
+ YAML lexer allows non-ASCII text.
+ </li>
+ <li>
+ SciTE on GTK+ implements "Replace in Buffers" in advanced mode.
+ </li>
+ <li>
+ The extender OnBeforeSave method can override the default file saving behaviour by retuning true.
+ </li>
+ <li>
+ Window position and recent files list may be saved into the session file.
+ </li>
+ <li>
+ Right button press outside the selection moves the caret.
+ </li>
+ <li>
+ SciTE load.on.activate works when closing a document reveals a changed document.
+ </li>
+ <li>
+ SciTE bug fixed where eol.mode not used for initial buffer.
+ </li>
+ <li>
+ SciTE bug fixed where a file could be saved as the same name as another
+ buffer leading to confusing behaviour.
+ </li>
+ <li>
+ Fixed display bug for long lines in same style on Windows.
+ </li>
+ <li>
+ Fixed SciTE crash when finding matching preprocessor command used on some files.
+ </li>
+ <li>
+ Drawing performance improved for files with many blank lines.
+ </li>
+ <li>
+ Folding bugs fixed where changing program text produced a decrease in fold level on a fold header line.
+ </li>
+ <li>
+ Clearing document style now clears all indicators.
+ </li>
+ <li>
+ SciTE's embedded Lua updated to 5.1.4.
+ </li>
+ <li>
+ SciTE will compile with versions of GTK+ before 2.8 again.
+ </li>
+ <li>
+ SciTE on GTK+ bug fixed where multiple files not opened.
+ </li>
+ <li>
+ Bug fixed with SCI_VCHOMEWRAP and SCI_VCHOMEWRAPEXTEND on white last line.
+ </li>
+ <li>
+ Regular expression bug fixed where "^[^(]+$" matched empty lines.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite176.zip?download">Release 1.76</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 16 March 2008.
+ </li>
+ <li>
+ Support for PowerShell.
+ </li>
+ <li>
+ Lexer added for Magik.
+ </li>
+ <li>
+ Director extension working on GTK+.
+ </li>
+ <li>
+ Director extension may set focus to SciTE through "focus:" message on GTK+.
+ </li>
+ <li>
+ C++ folder handles final line better in some cases.
+ </li>
+ <li>
+ SCI_COPYALLOWLINE added which is similar to SCI_COPY except that if the selection is empty then
+ the line holding the caret is copied. On Windows an extra clipboard format allows pasting this as a whole
+ line before the current selection. This behaviour is compatible with Visual Studio.
+ </li>
+ <li>
+ On Windows, the horizontal scroll bar can handle wider files.
+ </li>
+ <li>
+ On Windows, a system palette leak was fixed. Should not affect many as palette mode is rarely used.
+ </li>
+ <li>
+ Install command on GTK+ no longer tries to set explicit owner.
+ </li>
+ <li>
+ Perl lexer handles defined-or operator "//".
+ </li>
+ <li>
+ Octave lexer fixes "!=" operator.
+ </li>
+ <li>
+ Optimized selection change drawing to not redraw as much when not needed.
+ </li>
+ <li>
+ SciTE on GTK+ no longer echoes Lua commands so is same as on Windows.
+ </li>
+ <li>
+ Automatic vertical scrolling limited to one line at a time so is not too fast.
+ </li>
+ <li>
+ Crash fixed when line states set beyond end of line states. This occurred when lexers did not
+ set a line state for each line.
+ </li>
+ <li>
+ Crash in SciTE on Windows fixed when search for 513 character string fails.
+ </li>
+ <li>
+ SciTE disables translucent features on Windows 9x due to crashes reported when using translucency.
+ </li>
+ <li>
+ Bug fixed where whitespace background was not seen on wrapped lines.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite175.zip?download">Release 1.75</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 22 November 2007.
+ </li>
+ <li>
+ Some WordList and PropSet functionality moved from Scintilla to SciTE.
+ Projects that link to Scintilla's code for these classes may need to copy
+ code from SciTE.
+ </li>
+ <li>
+ Borland C++ can no longer build Scintilla.
+ </li>
+ <li>
+ Invalid bytes in UTF-8 mode are displayed as hex blobs. This also prevents crashes due to
+ passing invalid UTF-8 to platform calls.
+ </li>
+ <li>
+ Indentation guides enhanced to be visible on completely empty lines when possible.
+ </li>
+ <li>
+ The horizontal scroll bar may grow to match the widest line displayed.
+ </li>
+ <li>
+ Allow autocomplete popups to appear outside client rectangle in some cases.
+ </li>
+ <li>
+ When line state changed, SC_MOD_CHANGELINESTATE modification notification sent and
+ margin redrawn.
+ </li>
+ <li>
+ SciTE scripts can access the menu command values IDM_*.
+ </li>
+ <li>
+ SciTE's statement.end property has been implemented again.
+ </li>
+ <li>
+ SciTE shows paths and matches in different styles for Find In Files.
+ </li>
+ <li>
+ Incremental search in SciTE for Windows is modeless to make it easier to exit.
+ </li>
+ <li>
+ Folding performance improved.
+ </li>
+ <li>
+ SciTE for GTK+ now includes a Browse button in the Find In Files dialog.
+ </li>
+ <li>
+ On Windows versions that support Unicode well, Scintilla is a wide character window
+ which allows input for some less common languages like Armenian, Devanagari,
+ Tamil, and Georgian. To fully benefit, applications should use wide character calls.
+ </li>
+ <li>
+ Lua function names are exported from SciTE to allow some extension libraries to work.
+ </li>
+ <li>
+ Lexers added for Abaqus, Ansys APDL, Asymptote, and R.
+ </li>
+ <li>
+ SCI_DELWORDRIGHTEND added for closer compatibility with GTK+ entry widget.
+ </li>
+ <li>
+ The styling buffer may now use all 8 bits in each byte for lexical states with 0 bits for indicators.
+ </li>
+ <li>
+ Multiple characters may be set for SciTE's calltip.&lt;lexer&gt;.parameters.start property.
+ </li>
+ <li>
+ Bash lexer handles octal literals.
+ </li>
+ <li>
+ C++/JavaScript lexer recognises regex literals in more situations.
+ </li>
+ <li>
+ Haskell lexer fixed for quoted strings.
+ </li>
+ <li>
+ HTML/XML lexer does not notice XML indicator if there is
+ non-whitespace between the "&lt;?" and "XML".
+ ASP problem fixed where &lt;/ is used inside a comment.
+ </li>
+ <li>
+ Error messages from Lua 5.1 are recognised.
+ </li>
+ <li>
+ Folding implemented for Metapost.
+ </li>
+ <li>
+ Perl lexer enhanced for handling minus-prefixed barewords,
+ underscores in numeric literals and vector/version strings,
+ ^D and ^Z similar to __END__,
+ subroutine prototypes as a new lexical class,
+ formats and format blocks as new lexical classes, and
+ '/' suffixed keywords and barewords.
+ </li>
+ <li>
+ Python lexer styles all of a decorator in the decorator style rather than just the name.
+ </li>
+ <li>
+ YAML lexer styles colons as operators.
+ </li>
+ <li>
+ Fixed SciTE bug where undo would group together multiple separate modifications.
+ </li>
+ <li>
+ Bug fixed where setting background colour of calltip failed.
+ </li>
+ <li>
+ SciTE allows wildcard suffixes for file pattern based properties.
+ </li>
+ <li>
+ SciTE on GTK+ bug fixed where user not prompted to save untitled buffer.
+ </li>
+ <li>
+ SciTE bug fixed where property values from one file were not seen by lower priority files.
+ </li>
+ <li>
+ Bug fixed when showing selection with a foreground colour change which highlighted
+ an incorrect range in some positions.
+ </li>
+ <li>
+ Cut now invokes SCN_MODIFYATTEMPTRO notification.
+ </li>
+ <li>
+ Bug fixed where caret not shown at beginning of wrapped lines.
+ Caret made visible in some cases after wrapping and scroll bar updated after wrapping.
+ </li>
+ <li>
+ Modern indicators now work on wrapped lines.
+ </li>
+ <li>
+ Some crashes fixed for 64-bit GTK+.
+ </li>
+ <li>
+ On GTK+ clipboard features improved for VMWare tools copy and paste.
+ SciTE exports the clipboard more consistently on shut down.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite174.zip?download">Release 1.74</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 18 June 2007.
+ </li>
+ <li>
+ OS X support.
+ </li>
+ <li>
+ Indicators changed to be a separate data structure allowing more indicators. Storing indicators in high bits
+ of styling bytes is deprecated and will be removed in the next version.
+ </li>
+ <li>
+ Unicode support extended to all Unicode characters not just the Basic Multilingual Plane.
+ </li>
+ <li>
+ Performance improved on wide lines by breaking long runs in a single style into shorter segments.
+ </li>
+ <li>
+ Performance improved by caching layout of short text segments.
+ </li>
+ <li>
+ SciTE includes Lua 5.1.
+ </li>
+ <li>
+ Caret may be displayed as a block.
+ </li>
+ <li>
+ Lexer added for GAP.
+ </li>
+ <li>
+ Lexer added for PL/M.
+ </li>
+ <li>
+ Lexer added for Progress.
+ </li>
+ <li>
+ SciTE session files have changed format to be like other SciTE .properties files
+ and now use the extension .session.
+ Bookmarks and folds may optionally be saved in session files.
+ Session files created with previous versions of SciTE will not load into this version.
+ </li>
+ <li>
+ SciTE's extension and scripting interfaces add OnKey, OnDwellStart, and OnClose methods.
+ </li>
+ <li>
+ On GTK+, copying to the clipboard does not include the text/urilist type since this caused problems when
+ pasting into Open Office.
+ </li>
+ <li>
+ On GTK+, Scintilla defaults caret blink rate to platform preference.
+ </li>
+ <li>
+ Dragging does not start until the mouse has been dragged a certain amount.
+ This stops spurious drags when just clicking inside the selection.
+ </li>
+ <li>
+ Bug fixed where brace highlight not shown when caret line background set.
+ </li>
+ <li>
+ Bug fixed in Ruby lexer where out of bounds access could occur.
+ </li>
+ <li>
+ Bug fixed in XML folding where tags were not being folded because they are singletons in HTML.
+ </li>
+ <li>
+ Bug fixed when many font names used.
+ </li>
+ <li>
+ Layout bug fixed on GTK+ where fonts have ligatures available.
+ </li>
+ <li>
+ Bug fixed with SCI_LINETRANSPOSE on a blank line.
+ </li>
+ <li>
+ SciTE hang fixed when using UNC path with directory properties feature.
+ </li>
+ <li>
+ Bug on Windows fixed by examining dropped text for Unicode even in non-Unicode mode so it
+ can work when source only provides Unicode or when using an encoding different from the
+ system default.
+ </li>
+ <li>
+ SciTE bug on GTK+ fixed where Stop Executing did not work when more than a single process started.
+ </li>
+ <li>
+ SciTE bug on GTK+ fixed where mouse wheel was not switching between buffers.
+ </li>
+ <li>
+ Minor line end fix to PostScript lexer.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite173.zip?download">Release 1.73</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 31 March 2007.
+ </li>
+ <li>
+ SciTE adds a Directory properties file to configure behaviour for files in a directory and its subdirectories.
+ </li>
+ <li>
+ Style changes may be made during text modification events.
+ </li>
+ <li>
+ Regular expressions recognize \d, \D, \s, \S, \w, \W, and \xHH.
+ </li>
+ <li>
+ Support for cmake language added.
+ </li>
+ <li>
+ More Scintilla properties can be queried.
+ </li>
+ <li>
+ Edge line drawn under text.
+ </li>
+ <li>
+ A savesession command added to SciTE director interface.
+ </li>
+ <li>
+ SciTE File | Encoding menu item names changed to be less confusing.
+ </li>
+ <li>
+ SciTE on GTK+ dialog buttons reordered to follow guidelines.
+ </li>
+ <li>
+ SciTE on GTK+ removed GTK+ 1.x compatible file dialog code.
+ </li>
+ <li>
+ SciTE on GTK+ recognises key names KeypadMultiply and KeypadDivide.
+ </li>
+ <li>
+ Background colour of line wrapping visual flag changed to STYLE_DEFAULT.
+ </li>
+ <li>
+ Makefile lexing enhanced for ':=' operator and when lines start with tab.
+ </li>
+ <li>
+ TADS3 lexer and folder improved.
+ </li>
+ <li>
+ SCN_DOUBLECLICK notification may set SCI_SHIFT, SCI_CTRL, and SCI_ALT flags on modifiers field.
+ </li>
+ <li>
+ Slow folding of large constructs in Python fixed.
+ </li>
+ <li>
+ MSSQL folding fixed to be case-insensitive and fold at more keywords.
+ </li>
+ <li>
+ SciTE's brace matching works better for HTML.
+ </li>
+ <li>
+ Determining API list items checks for specified parameters start character before default '('.
+ </li>
+ <li>
+ Hang fixed in HTML lexer.
+ </li>
+ <li>
+ Bug fixed in with LineTranspose command where markers could move to different line.
+ </li>
+ <li>
+ Memory released when buffer completely emptied.
+ </li>
+ <li>
+ If translucency not available on Windows, draw rectangular outline instead.
+ </li>
+ <li>
+ Bash lexer handles "-x" in "--x-includes..." better.
+ </li>
+ <li>
+ AutoIt3 lexer fixes string followed by '+'.
+ </li>
+ <li>
+ LinesJoin fixed where it stopped early due to not adjusting for inserted spaces..
+ </li>
+ <li>
+ StutteredPageDown fixed when lines wrapped.
+ </li>
+ <li>
+ FormatRange fixed to not double count line number width which could lead to a large space.
+ </li>
+ <li>
+ SciTE Export As PDF and Latex commands fixed to format floating point numbers with '.' even in locales
+ that use ','.
+ </li>
+ <li>
+ SciTE bug fixed where File | New could produce buffer with contents of previous file when using read-only mode.
+ </li>
+ <li>
+ SciTE retains current scroll position when switching buffers and fold.on.open set.
+ </li>
+ <li>
+ SciTE crash fixed where '*' used to invoke parameters dialog.
+ </li>
+ <li>
+ SciTE bugs when writing large UCS-2 files fixed.
+ </li>
+ <li>
+ Bug fixed when scrolling inside a SCN_PAINTED event by invalidating window
+ rather than trying to perform synchronous painting.
+ </li>
+ <li>
+ SciTE for GTK+ View | Full Screen works on recent versions of GTK+.
+ </li>
+ <li>
+ SciTE for Windows enables and disables toolbar commands correctly.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite172.zip?download">Release 1.72</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 15 January 2007.
+ </li>
+ <li>
+ Performance of per-line data improved.
+ </li>
+ <li>
+ SC_STARTACTION flag set on the first modification notification in an undo
+ transaction to help synchronize the container's undo stack with Scintilla's.
+ </li>
+ <li>
+ On GTK+ drag and drop defaults to move rather than copy.
+ </li>
+ <li>
+ Scintilla supports extending appearance of selection to right hand margin.
+ </li>
+ <li>
+ Incremental search available on GTK+.
+ </li>
+ <li>
+ SciTE Indentation Settings dialog available on GTK+ and adds a "Convert" button.
+ </li>
+ <li>
+ Find in Files can optionally ignore binary files or directories that start with ".".
+ </li>
+ <li>
+ Lexer added for "D" language.
+ </li>
+ <li>
+ Export as HTML shows folding with underline lines and +/- symbols.
+ </li>
+ <li>
+ Ruby lexer interprets interpolated strings as expressions.
+ </li>
+ <li>
+ Lua lexer fixes some cases of numeric literals.
+ </li>
+ <li>
+ C++ folder fixes bug with "@" in doc comments.
+ </li>
+ <li>
+ NSIS folder handles !if and related commands.
+ </li>
+ <li>
+ Inno setup lexer adds styling for single and double quoted strings.
+ </li>
+ <li>
+ Matlab lexer handles backslashes in string literals correctly.
+ </li>
+ <li>
+ HTML lexer fixed to allow "?&gt;" in comments in Basic script.
+ </li>
+ <li>
+ Added key codes for Windows key and Menu key.
+ </li>
+ <li>
+ Lua script method scite.MenuCommand(x) performs a menu command.
+ </li>
+ <li>
+ SciTE bug fixed with box comment command near start of file setting selection to end of file.
+ </li>
+ <li>
+ SciTE on GTK+, fixed loop that occurred with automatic loading for an unreadable file.
+ </li>
+ <li>
+ SciTE asks whether to save files when Windows shuts down.
+ </li>
+ <li>
+ Save Session on Windows now defaults the extension to "ses".
+ </li>
+ <li>
+ Bug fixed with single character keywords.
+ </li>
+ <li>
+ Fixed infinite loop for SCI_GETCOLUMN for position beyond end of document.
+ </li>
+ <li>
+ Fixed failure to accept typing on Solaris/GTK+ when using default ISO-8859-1 encoding.
+ </li>
+ <li>
+ Fixed warning from Lua in SciTE when creating a new buffer when already have
+ maximum number of buffers open.
+ </li>
+ <li>
+ Crash fixed with "%%" at end of batch file.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite171.zip?download">Release 1.71</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 21 August 2006.
+ </li>
+ <!--li>
+ On GTK+ drag and drop defaults to move rather than copy.
+ </li-->
+ <li>
+ Double click notification includes line and position.
+ </li>
+ <li>
+ VB lexer bugs fixed for preprocessor directive below a comment or some other states and
+ to use string not closed style back to the starting quote when there are internal doubled quotes.
+ </li>
+ <li>
+ C++ lexer allows identifiers to contain '$' and non-ASCII characters such as UTF-8.
+ The '$' character can be disallowed with lexer.cpp.allow.dollars=0.
+ </li>
+ <li>
+ Perl lexer allows UTF-8 identifiers and has some other small improvements.
+ </li>
+ <li>
+ SciTE's $(CurrentWord) uses word.characters.&lt;filepattern&gt; to define the word
+ rather than a hardcoded list of word characters.
+ </li>
+ <li>
+ SciTE Export as HTML adds encoding information for UTF-8 file and fixes DOCTYPE.
+ </li>
+ <li>
+ SciTE session and .recent files default to the user properties directory rather than global
+ properties directory.
+ </li>
+ <li>
+ Left and right scroll events handled correctly on GTK+ and horizontal scroll bar has more sensible
+ distances for page and arrow clicks.
+ </li>
+ <li>
+ SciTE on GTK+ tab bar fixed to work on recent versions of GTK+.
+ </li>
+ <li>
+ On GTK+, if the approximate character set conversion is unavailable, a second attempt is made
+ without approximations. This may allow keyboard input and paste to work on older systems.
+ </li>
+ <li>
+ SciTE on GTK+ can redefine the Insert key.
+ </li>
+ <li>
+ SciTE scripting interface bug fixed where some string properties could not be changed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite170.zip?download">Release 1.70</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 20 June 2006.
+ </li>
+ <li>
+ On GTK+, character set conversion is performed using an option that allows approximate conversions rather
+ than failures when a character can not be converted. This may lead to similar characters being inserted or
+ when no similar character is available a '?' may be inserted.
+ </li>
+ <li>
+ On GTK+, the internationalised IM (Input Method) feature is used for all typed input for all character sets.
+ </li>
+ <li>
+ Scintilla has new margin types SC_MARGIN_BACK and SC_MARGIN_FORE that use the default
+ style's background and foreground colours (normally white and black) as the background to the margin.
+ </li>
+ <li>
+ Scintilla/GTK+ allows file drops on Windows when drop is of type DROPFILES_DND
+ as well as text/uri-list.
+ </li>
+ <li>
+ Code page can only be set to one of the listed valid values.
+ </li>
+ <li>
+ Text wrapping fixed for cases where insertion was not wide enough to trigger
+ wrapping before being styled but was after styling.
+ </li>
+ <li>
+ SciTE find marks are removed before printing or exporting to avoid producing incorrect styles.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite169.zip?download">Release 1.69</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 29 May 2006.
+ </li>
+ <li>
+ SciTE supports z-order based buffer switching on Ctrl+Tab.
+ </li>
+ <li>
+ Translucent support for selection and whole line markers.
+ </li>
+ <li>
+ SciTE may have per-language abbreviations files.
+ </li>
+ <li>
+ Support for Spice language.
+ </li>
+ <li>
+ On GTK+ autocompletion lists are optimised and use correct selection colours.
+ </li>
+ <li>
+ On GTK+ the URI data type is preferred in drag and drop so that applications
+ will see files dragged from the shell rather than dragging the text of the file name
+ into the document.
+ </li>
+ <li>
+ Increased number of margins to 5.
+ </li>
+ <li>
+ Basic lexer allows include directive $include: "file name".
+ </li>
+ <li>
+ SQL lexer no longer bases folding on indentation.
+ </li>
+ <li>
+ Line ends are transformed when copied to clipboard on
+ Windows/GTK+2 as well as Windows/GTK+ 1.
+ </li>
+ <li>
+ Lexing code masks off the indicator bits on the start style before calling the lexer
+ to avoid confusing the lexer when an application has used an indicator.
+ </li>
+ <li>
+ SciTE savebefore:yes only saves the file when it has been changed.
+ </li>
+ <li>
+ SciTE adds output.initial.hide setting to allow setting the size of the output pane
+ without it showing initially.
+ </li>
+ <li>
+ SciTE on Windows Go To dialog allows line number with more digits.
+ </li>
+ <li>
+ Bug in HTML lexer fixed where a segment of PHP could switch scripting language
+ based on earlier text on that line.
+ </li>
+ <li>
+ Memory bug fixed when freeing regions on GTK+.
+ Other minor bugs fixed on GTK+.
+ </li>
+ <li>
+ Deprecated GTK+ calls in Scintilla replaced with current calls.
+ </li>
+ <li>
+ Fixed a SciTE bug where closing the final buffer, if read-only, left the text present in an
+ untitled buffer.
+ </li>
+ <li>
+ Bug fixed in bash lexer that prevented folding.
+ </li>
+ <li>
+ Crash fixed in bash lexer when backslash at end of file.
+ </li>
+ <li>
+ Crash on recent releases of GTK+ 2.x avoided by changing default font from X
+ core font to Pango font "!Sans".
+ </li>
+ <li>
+ Fix for SciTE properties files where multiline properties continued over completely blank lines.
+ </li>
+ <li>
+ Bug fixed in SciTE/GTK+ director interface where more data available than
+ buffer size.
+ </li>
+ <li>
+ Minor visual fixes to SciTE splitter on GTK+.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite168.zip?download">Release 1.68</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 9 March 2006.
+ </li>
+ <li>
+ Translucent drawing implemented for caret line and box indicators.
+ </li>
+ <li>
+ Lexer specifically for TCL is much more accurate than reusing C++ lexer.
+ </li>
+ <li>
+ Support for Inno Setup scripts.
+ </li>
+ <li>
+ Support for Opal language.
+ </li>
+ <li>
+ Calltips may use a new style, STYLE_CALLTIP which allows choosing a
+ different font for calltips.
+ </li>
+ <li>
+ Python lexer styles comments on decorators.
+ </li>
+ <li>
+ HTML lexer refined handling of "?>" and "%>" within server
+ side scripts.
+ </li>
+ <li>
+ Batch file lexer improved.
+ </li>
+ <li>
+ Eiffel lexer doesn't treat '.' as a name character.
+ </li>
+ <li>
+ Lua lexer handles length operator, #, and hex literals.
+ </li>
+ <li>
+ Properties file lexer has separate style for keys.
+ </li>
+ <li>
+ PL/SQL folding improved.
+ </li>
+ <li>
+ SciTE Replace dialog always searches in forwards direction.
+ </li>
+ <li>
+ SciTE can detect language of file from initial #! line.
+ </li>
+ <li>
+ SciTE on GTK+ supports output.scroll=2 setting.
+ </li>
+ <li>
+ SciTE can perform an import a properties file from the command line.
+ </li>
+ <li>
+ Set of word characters used for regular expression \&lt; and \&gt;.
+ </li>
+ <li>
+ Bug fixed with SCI_COPYTEXT stopping too early.
+ </li>
+ <li>
+ Bug fixed with splitting lines so that all lines are split.
+ </li>
+ <li>
+ SciTE calls OnSwitchFile when closing one buffer causes a switch to another.
+ </li>
+ <li>
+ SciTE bug fixed where properties were being reevaluated without good reason
+ after running a macro.
+ </li>
+ <li>
+ Crash fixed when clearing document with some lines contracted in word wrap mode.
+ </li>
+ <li>
+ Palette expands as more entries are needed.
+ </li>
+ <li>
+ SCI_POSITIONFROMPOINT returns more reasonable value when close to
+ last text on a line.
+ </li>
+ <li>
+ On Windows, long pieces of text may be drawn in segments if they fail to draw
+ as a whole.
+ </li>
+ <li>
+ Bug fixed with bad drawing when some visual changes made inside SCN_UPDATEUI
+ notification.
+ </li>
+ <li>
+ SciTE bug fixed with groupundo setting.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite167.zip?download">Release 1.67</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 17 December 2005.
+ </li>
+ <li>
+ Scintilla checks the paint region more accurately when seeing if an area is being
+ repainted. Platform layer implementations may need to change for this to take
+ effect. This fixes some drawing and styling bugs. Also optimized some parts of
+ marker code to only redraw the line of the marker rather than whole of the margin.
+ </li>
+ <li>
+ Quoted identifier style for SQL. SQL folding performed more simply.
+ </li>
+ <li>
+ Ruby lexer improved to better handle here documents and non-ASCII
+ characters.
+ </li>
+ <li>
+ Lua lexer supports long string and block comment syntax from Lua 5.1.
+ </li>
+ <li>
+ Bash lexer handles here documents better.
+ </li>
+ <li>
+ JavaScript lexing recognises regular expressions more accurately and includes flag
+ characters in the regular expression style. This is both in JavaScript files and when
+ JavaScript is embedded in HTML.
+ </li>
+ <li>
+ Scintilla API provided to reveal how many style bits are needed for the
+ current lexer.
+ </li>
+ <li>
+ Selection duplicate added.
+ </li>
+ <li>
+ Scintilla API for adding a set of markers to a line.
+ </li>
+ <li>
+ DBCS encodings work on Windows 9x.
+ </li>
+ <li>
+ Convention defined for property names to be used by lexers and folders
+ so they can be automatically discovered and forwarded from containers.
+ </li>
+ <li>
+ Default bookmark in SciTE changed to a blue sphere image.
+ </li>
+ <li>
+ SciTE stores the time of last asking for a save separately for each buffer
+ which fixes bugs with automatic reloading.
+ </li>
+ <li>
+ On Windows, pasted text has line ends converted to current preference.
+ GTK+ already did this.
+ </li>
+ <li>
+ Kid template language better handled by HTML lexer by finishing ASP Python
+ mode when a ?> is found.
+ </li>
+ <li>
+ SciTE counts number of characters in a rectangular selection correctly.
+ </li>
+ <li>
+ 64-bit compatibility improved. One change that may affect user code is that
+ the notification message header changed to include a pointer-sized id field
+ to match the current Windows definition.
+ </li>
+ <li>
+ Empty ranges can no longer be dragged.
+ </li>
+ <li>
+ Crash fixed when calls made that use layout inside the painted notification.
+ </li>
+ <li>
+ Bug fixed where Scintilla created pixmap buffers that were too large leading
+ to failures when many instances used.
+ </li>
+ <li>
+ SciTE sets the directory of a new file to the directory of the currently
+ active file.
+ </li>
+ <li>
+ SciTE allows choosing a code page for the output pane.
+ </li>
+ <li>
+ SciTE HTML exporter no longer honours monospaced font setting.
+ </li>
+ <li>
+ Line layout cache in page mode caches the line of the caret. An assertion is
+ now used to ensure that the layout reentrancy problem that caused this
+ is easier to find.
+ </li>
+ <li>
+ Speed optimized for long lines and lines containing many control characters.
+ </li>
+ <li>
+ Bug fixed in brace matching in DBCS files where byte inside character
+ is same as brace.
+ </li>
+ <li>
+ Indent command does not indent empty lines.
+ </li>
+ <li>
+ SciTE bug fixed for commands that operate on files with empty extensions.
+ </li>
+ <li>
+ SciTE bug fixed where monospaced option was copied for subsequently opened files.
+ </li>
+ <li>
+ SciTE on Windows bug fixed in the display of a non-ASCII search string
+ which can not be found.
+ </li>
+ <li>
+ Bugs fixed with nested calls displaying a new calltip while one is already
+ displayed.
+ </li>
+ <li>
+ Bug fixed when styling PHP strings.
+ </li>
+ <li>
+ Bug fixed when styling C++ continued preprocessor lines.
+ </li>
+ <li>
+ SciTE bug fixed where opening file from recently used list reset choice of
+ language.
+ </li>
+ <li>
+ SciTE bug fixed when compiled with NO_EXTENSIONS and
+ closing one file closes the application.
+ </li>
+ <li>
+ SciTE crash fixed for error messages that look like Lua messages but aren't
+ in the same order.
+ </li>
+ <li>
+ Remaining fold box support deprecated. The symbols SC_FOLDLEVELBOXHEADERFLAG,
+ SC_FOLDLEVELBOXFOOTERFLAG, SC_FOLDLEVELCONTRACTED,
+ SC_FOLDLEVELUNINDENT, and SC_FOLDFLAG_BOX are deprecated.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite166.zip?download">Release 1.66</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 26 August 2005.
+ </li>
+ <li>
+ New, more ambitious Ruby lexer.
+ </li>
+ <li>
+ SciTE Find in Files dialog has options for matching case and whole words which are
+ enabled when the internal find command is used.
+ </li>
+ <li>
+ SciTE output pane can display automatic completion after "$(" typed.
+ An initial ">" on a line is ignored when Enter pressed.
+ </li>
+ <li>
+ C++ lexer recognises keywords within line doc comments. It continues styles over line
+ end characters more consistently so that eolfilled style can be used for preprocessor lines
+ and line comments.
+ </li>
+ <li>
+ VB lexer improves handling of file numbers and date literals.
+ </li>
+ <li>
+ Lua folder handles repeat until, nested comments and nested strings.
+ </li>
+ <li>
+ POV lexer improves handling of comment lines.
+ </li>
+ <li>
+ AU3 lexer and folder updated. COMOBJ style added.
+ </li>
+ <li>
+ Bug fixed with text display on GTK+ with Pango 1.8.
+ </li>
+ <li>
+ Caret painting avoided when not focused.
+ </li>
+ <li>
+ SciTE on GTK+ handles file names used to reference properties as case-sensitive.
+ </li>
+ <li>
+ SciTE on GTK+ Save As and Export commands set the file name field.
+ On GTK+ the Export commands modify the file name in the same way as on Windows.
+ </li>
+ <li>
+ Fixed SciTE problem where confirmation was not displaying when closing a file where all
+ contents had been deleted.
+ </li>
+ <li>
+ Middle click on SciTE tab now closes correct buffer on Windows when tool bar is visible.
+ </li>
+ <li>
+ SciTE bugs fixed where files contained in directory that includes '.' character.
+ </li>
+ <li>
+ SciTE bug fixed where import in user options was reading file from directory of
+ global options.
+ </li>
+ <li>
+ SciTE calltip bug fixed where single line calltips had arrow displayed incorrectly.
+ </li>
+ <li>
+ SciTE folding bug fixed where empty lines were shown for no reason.
+ </li>
+ <li>
+ Bug fixed where 2 byte per pixel XPM images caused crash although they are still not
+ displayed.
+ </li>
+ <li>
+ Autocompletion list size tweaked.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite165.zip?download">Release 1.65</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 August 2005.
+ </li>
+ <li>
+ FreeBasic support.
+ </li>
+ <li>
+ SciTE on Windows handles command line arguments
+ "-" (read standard input into buffer),
+ "--" (read standard input into output pane) and
+ "-@" (read file names from standard input and open each).
+ </li>
+ <li>
+ SciTE includes a simple implementation of Find in Files which is used if no find.command is set.
+ </li>
+ <li>
+ SciTE can close tabs with a mouse middle click.
+ </li>
+ <li>
+ SciTE includes a save.all.for.build setting.
+ </li>
+ <li>
+ Folder for MSSQL.
+ </li>
+ <li>
+ Batch file lexer understands more of the syntax and the behaviour of built in commands.
+ </li>
+ <li>
+ Perl lexer handles here docs better; disambiguates barewords, quote-like delimiters, and repetition operators;
+ handles Pods after __END__; recognises numbers better; and handles some typeglob special variables.
+ </li>
+ <li>
+ Lisp adds more lexical states.
+ </li>
+ <li>
+ PHP allows spaces after &lt;&lt;&lt;.
+ </li>
+ <li>
+ TADS3 has a simpler set of states and recognises identifiers.
+ </li>
+ <li>
+ Avenue elseif folds better.
+ </li>
+ <li>
+ Errorlist lexer treats lines starting with '+++' and '---' as separate
+ styles from '+' and '-' as they indicate file names in diffs.
+ </li>
+ <li>
+ SciTE error recogniser handles file paths in extra explanatory lines from MSVC
+ and in '+++' and '---' lines from diff.
+ </li>
+ <li>
+ Bugs fixed in SciTE and Scintilla folding behaviour when text pasted before
+ folded text caused unnecessary
+ unfolding and cutting text could lead to text being irretrievably hidden.
+ </li>
+ <li>
+ SciTE on Windows uses correct font for dialogs and better font for tab bar
+ allowing better localisation
+ </li>
+ <li>
+ When Windows is used with a secondary monitor before the primary
+ monitor, autocompletion lists are not forced onto the primary monitor.
+ </li>
+ <li>
+ Scintilla calltip bug fixed where down arrow setting wrong value in notification
+ if not in first line. SciTE bug fixed where second arrow only shown on multiple line
+ calltip and was therefore misinterpreting the notification value.
+ </li>
+ <li>
+ Lexers will no longer be re-entered recursively during, for example, fold level setting.
+ </li>
+ <li>
+ Undo of typing in overwrite mode undoes one character at a time rather than requiring a removal
+ and addition step for each character.
+ </li>
+ <li>
+ EM_EXSETSEL(0,-1) fixed.
+ </li>
+ <li>
+ Bug fixed where part of a rectangular selection was not shown as selected.
+ </li>
+ <li>
+ Autocomplete window size fixed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite164.zip?download">Release 1.64</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 6 June 2005.
+ </li>
+ <li>
+ TADS3 support
+ </li>
+ <li>
+ Smalltalk support.
+ </li>
+ <li>
+ Rebol support.
+ </li>
+ <li>
+ Flagship (Clipper / XBase) support.
+ </li>
+ <li>
+ CSound support.
+ </li>
+ <li>
+ SQL enhanced to support SQL*Plus.
+ </li>
+ <li>
+ SC_MARK_FULLRECT margin marker fills the whole marker margin for marked
+ lines with a colour.
+ </li>
+ <li>
+ Performance improved for some large undo and redo operations and modification flags
+ added in notifications.
+ </li>
+ <li>
+ SciTE adds command equivalents for fold margin mouse actions.
+ </li>
+ <li>
+ SciTE adds OnUpdateUI to set of events that can be handled by a Lua script.
+ </li>
+ <li>
+ Properties set in Scintilla can be read.
+ </li>
+ <li>
+ GTK+ SciTE exit confirmation adds Cancel button.
+ </li>
+ <li>
+ More accurate lexing of numbers in PHP and Caml.
+ </li>
+ <li>
+ Perl can fold POD and package sections. POD verbatim section style.
+ Globbing syntax recognised better.
+ </li>
+ <li>
+ Context menu moved slightly on GTK+ so that it will be under the mouse and will
+ stay open if just clicked rather than held.
+ </li>
+ <li>
+ Rectangular selection paste works the same whichever direction the selection was dragged in.
+ </li>
+ <li>
+ EncodedFromUTF8 handles -1 length argument as documented.
+ </li>
+ <li>
+ Undo and redo can cause SCN_MODIFYATTEMPTRO notifications.
+ </li>
+ <li>
+ Indicators display correctly when they start at the second character on a line.
+ </li>
+ <li>
+ SciTE Export As HTML uses standards compliant CSS.
+ </li>
+ <li>
+ SciTE automatic indentation handles keywords for indentation better.
+ </li>
+ <li>
+ SciTE fold.comment.python property removed as does not work.
+ </li>
+ <li>
+ Fixed problem with character set conversion when pasting on GTK+.
+ </li>
+ <li>
+ SciTE default character set changed from ANSI_CHARSET to DEFAULT_CHARSET.
+ </li>
+ <li>
+ Fixed crash when creating empty autocompletion list.
+ </li>
+ <li>
+ Autocomplete window size made larger under some conditions to make truncation less common.
+ </li>
+ <li>
+ Bug fixed where changing case of a selection did not affect initial character of lines
+ in multi-byte encodings.
+ </li>
+ <li>
+ Bug fixed where rectangular selection not displayed after Alt+Shift+Click.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite163.zip?download">Release 1.63</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 4 April 2005.
+ </li>
+ <li>
+ Autocompletion on Windows changed to use popup window, be faster,
+ allow choice of maximum width and height, and to highlight only the text of the
+ selected item rather than both the text and icon if any.
+ </li>
+ <li>
+ Extra items can be added to the context menu in SciTE.
+ </li>
+ <li>
+ Character wrap mode in Scintilla helps East Asian languages.
+ </li>
+ <li>
+ Lexer added for Haskell.
+ </li>
+ <li>
+ Objective Caml support.
+ </li>
+ <li>
+ BlitzBasic and PureBasic support.
+ </li>
+ <li>
+ CSS support updated to handle CSS2.
+ </li>
+ <li>
+ C++ lexer is more selective about document comment keywords.
+ </li>
+ <li>
+ AutoIt 3 lexer improved.
+ </li>
+ <li>
+ Lua lexer styles end of line characters on comment and preprocessor
+ lines so that the eolfilled style can be applied to them.
+ </li>
+ <li>
+ NSIS support updated for line continuations, box comments, SectionGroup and
+ PageEx, and with more up-to-date properties.
+ </li>
+ <li>
+ Clarion lexer updated to perform folding and have more styles.
+ </li>
+ <li>
+ SQL lexer gains second set of keywords.
+ </li>
+ <li>
+ Errorlist lexer recognises Borland Delphi error messages.
+ </li>
+ <li>
+ Method added for determining number of visual lines occupied by a document
+ line due to wrapping.
+ </li>
+ <li>
+ Sticky caret mode does not modify the preferred caret x position when typing
+ and may be useful for typing columns of text.
+ </li>
+ <li>
+ Dwell end notification sent when scroll occurs.
+ </li>
+ <li>
+ On GTK+, Scintilla requisition height is screen height rather than large fixed value.
+ </li>
+ <li>
+ Case insensitive autocompletion prefers exact case match.
+ </li>
+ <li>
+ SCI_PARADOWN and SCI_PARAUP treat lines containing only white
+ space as empty and handle text hidden by folding.
+ </li>
+ <li>
+ Scintilla on Windows supports WM_PRINTCLIENT although there are some
+ limitations.
+ </li>
+ <li>
+ SCN_AUTOCSELECTION notification sent when user selects from autoselection list.
+ </li>
+ <li>
+ SciTE's standard properties file sets buffers to 10, uses Pango fonts on GTK+ and
+ has dropped several languages to make the menu fit on screen.
+ </li>
+ <li>
+ SciTE's encoding cookie detection loosened so that common XML files will load
+ in UTF-8 if that is their declared encoding.
+ </li>
+ <li>
+ SciTE on GTK+ changes menus and toolbars to not be detachable unless turned
+ on with a property. Menus no longer tear off. The toolbar may be set to use the
+ default theme icons rather than SciTE's set. Changed key for View | End of Line
+ because of a conflict. Language menu can contain more items.
+ </li>
+ <li>
+ SciTE on GTK+ 2.x allows the height and width of the file open file chooser to
+ be set, for the show hidden files check box to be set from an option and for it
+ to be opened in the directory of the current file explicitly. Enter key works in
+ save chooser.
+ </li>
+ <li>
+ Scintilla lexers should no longer see bits in style bytes that are outside the set
+ they modify so should be able to correctly lex documents where the container
+ has used indicators.
+ </li>
+ <li>
+ SciTE no longer asks to save before performing a revert.
+ </li>
+ <li>
+ SciTE director interface adds a reloadproperties command to reload properties
+ from files.
+ </li>
+ <li>
+ Allow build on CYGWIN platform.
+ </li>
+ <li>
+ Allow use from LccWin compiler.
+ </li>
+ <li>
+ SCI_COLOURISE for SCLEX_CONTAINER causes a
+ SCN_STYLENEEDED notification.
+ </li>
+ <li>
+ Bugs fixed in lexing of HTML/ASP/JScript.
+ </li>
+ <li>
+ Fix for folding becoming confused.
+ </li>
+ <li>
+ On Windows, fixes for Japanese Input Method Editor and for 8 bit Katakana
+ characters.
+ </li>
+ <li>
+ Fixed buffer size bug avoided when typing long words by making buffer bigger.
+ </li>
+ <li>
+ Undo after automatic indentation more sensible.
+ </li>
+ <li>
+ SciTE menus on GTK+ uses Shift and Ctrl rather than old style abbreviations.
+ </li>
+ <li>
+ SciTE full screen mode on Windows calculates size more correctly.
+ </li>
+ <li>
+ SciTE on Windows menus work better with skinning applications.
+ </li>
+ <li>
+ Searching bugs fixed.
+ </li>
+ <li>
+ Colours reallocated when changing image using SCI_REGISTERIMAGE.
+ </li>
+ <li>
+ Caret stays visible when Enter held down.
+ </li>
+ <li>
+ Undo of automatic indentation more reasonable.
+ </li>
+ <li>
+ High processor usage fixed in background wrapping under some
+ circumstances.
+ </li>
+ <li>
+ Crashing bug fixed on AMD64.
+ </li>
+ <li>
+ SciTE crashing bug fixed when position.height or position.width not set.
+ </li>
+ <li>
+ Crashing bug on GTK+ fixed when setting cursor and window is NULL.
+ </li>
+ <li>
+ Crashing bug on GTK+ preedit window fixed.
+ </li>
+ <li>
+ SciTE crashing bug fixed in incremental search on Windows ME.
+ </li>
+ <li>
+ SciTE on Windows has a optional find and replace dialogs that can search through
+ all buffers and search within a particular style number.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite162.zip?download">Release 1.62</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 31 October 2004.
+ </li>
+ <li>
+ Lexer added for ASN.1.
+ </li>
+ <li>
+ Lexer added for VHDL.
+ </li>
+ <li>
+ On Windows, an invisible system caret is used to allow screen readers to determine
+ where the caret is. The visible caret is still drawn by the painting code.
+ </li>
+ <li>
+ On GTK+, Scintilla has methods to read the target as UTF-8 and to convert
+ a string from UTF-8 to the document encoding. This eases integration with
+ containers that use the UTF-8 encoding which is the API encoding for GTK+ 2.
+ </li>
+ <li>
+ SciTE on GTK+2 and Windows NT/2000/XP allows search and replace of Unicode text.
+ </li>
+ <li>
+ SciTE calltips allow setting the characters used to start and end parameter lists and
+ to separate parameters.
+ </li>
+ <li>
+ FindColumn method converts a line and column into a position, taking into account
+ tabs and multi-byte characters.
+ </li>
+ <li>
+ On Windows, when Scintilla copies text to the clipboard as Unicode, it avoids
+ adding an ANSI copy as the system will automatically convert as required in
+ a context-sensitive manner.
+ </li>
+ <li>
+ SciTE indent.auto setting automatically determines indent.size and use.tabs from
+ document contents.
+ </li>
+ <li>
+ SciTE defines a CurrentMessage property that holds the most recently selected
+ output pane message.
+ </li>
+ <li>
+ SciTE Lua scripting enhanced with
+ <ul>
+ <li>A Lua table called 'buffer' is associated with each buffer and can be used to
+ maintain buffer-specific state.</li>
+ <li>A 'scite' object allows interaction with the application such as opening
+ files from script.</li>
+ <li>Dynamic properties can be reset by assigning nil to a given key in
+ the props table.</li>
+ <li>An 'OnClear' event fires whenever properties and extension scripts are
+ about to be reloaded.</li>
+ <li>On Windows, loadlib is enabled and can be used to access Lua
+ binary modules / DLLs.</li></ul>
+ </li>
+ <li>
+ SciTE Find in Files on Windows can be used in a modeless way and gains a '..'
+ button to move up to the parent directory. It is also wider so that longer paths
+ can be seen.
+ </li>
+ <li>
+ Close buttons added to dialogs in SciTE on Windows.
+ </li>
+ <li>
+ SciTE on GTK+ 2 has a "hidden files" check box in file open dialog.
+ </li>
+ <li>
+ SciTE use.monospaced setting removed. More information in the
+ <a href="SciTEFAQ.html">FAQ</a>.
+ </li>
+ <li>
+ APDL lexer updated with more lexical classes
+ </li>
+ <li>
+ AutoIt3 lexer updated.
+ </li>
+ <li>
+ Ada lexer fixed to support non-ASCII text.
+ </li>
+ <li>
+ Cpp lexer now only matches exactly three slashes as starting a doc-comment so that
+ lines of slashes are seen as a normal comment.
+ Line ending characters are appear in default style on preprocessor and single line
+ comment lines.
+ </li>
+ <li>
+ CSS lexer updated to support CSS2 including second set of keywords.
+ </li>
+ <li>
+ Errorlist lexer now understands Java stack trace lines.
+ </li>
+ <li>
+ SciTE's handling of HTML Tidy messages jumps to column as well as line indicated.
+ </li>
+ <li>
+ Lisp lexer allows multiline strings.
+ </li>
+ <li>
+ Lua lexer treats .. as an operator when between identifiers.
+ </li>
+ <li>
+ PHP lexer handles 'e' in numerical literals.
+ </li>
+ <li>
+ PowerBasic lexer updated for macros and optimised.
+ </li>
+ <li>
+ Properties file folder changed to leave lines before a header at the base level
+ and thus avoid a vertical line when using connected folding symbols.
+ </li>
+ <li>
+ GTK+ on Windows version uses Alt for rectangular selection to be compatible with
+ platform convention.
+ </li>
+ <li>
+ SciTE abbreviations file moved from system directory to user directory
+ so each user can have separate abbreviations.
+ </li>
+ <li>
+ SciTE on GTK+ has improved .desktop file and make install support that may
+ lead to better integration with system shell.
+ </li>
+ <li>
+ Disabling of themed background drawing on GTK+ extended to all cases.
+ </li>
+ <li>
+ SciTE date formatting on Windows performed with the user setting rather than the
+ system setting.
+ </li>
+ <li>
+ GTK+ 2 redraw while scrolling fixed.
+ </li>
+ <li>
+ Recursive property definitions are safer, avoiding expansion when detected.
+ </li>
+ <li>
+ SciTE thread synchronization for scripts no longer uses HWND_MESSAGE
+ so is compatible with older versions of Windows.
+ Other Lua scripting bugs fixed.
+ </li>
+ <li>
+ SciTE on Windows localisation of menu accelerators changed to be compatible
+ with alternative UI themes.
+ </li>
+ <li>
+ SciTE on Windows full screen mode now fits better when menu different height
+ to title bar height.
+ </li>
+ <li>
+ SC_MARK_EMPTY marker is now invisible and does not change the background
+ colour.
+ </li>
+ <li>
+ Bug fixed in HTML lexer to allow use of &lt;?xml in strings in scripts without
+ triggering xml mode.
+ </li>
+ <li>
+ Bug fixed in SciTE abbreviation expansion that could break indentation or crash.
+ </li>
+ <li>
+ Bug fixed when searching for a whole word string that ends one character before
+ end of document.
+ </li>
+ <li>
+ Drawing bug fixed when indicators drawn on wrapped lines.
+ </li>
+ <li>
+ Bug fixed when double clicking a hotspot.
+ </li>
+ <li>
+ Bug fixed where autocompletion would remove typed text if no match found.
+ </li>
+ <li>
+ Bug fixed where display does not scroll when inserting in long wrapped line.
+ </li>
+ <li>
+ Bug fixed where SCI_MARKERDELETEALL would only remove one of the markers
+ on a line that contained multiple markers with the same number.
+ </li>
+ <li>
+ Bug fixed where markers would move when converting line endings.
+ </li>
+ <li>
+ Bug fixed where SCI_LINEENDWRAP would move too far when line ends are visible.
+ </li>
+ <li>
+ Bugs fixed where calltips with unicode or other non-ASCII text would display
+ incorrectly.
+ </li>
+ <li>
+ Bug fixed in determining if at save point after undoing from save point and then
+ performing changes.
+ </li>
+ <li>
+ Bug fixed on GTK+ using unsupported code pages where extraneous text could
+ be drawn.
+ </li>
+ <li>
+ Bug fixed in drag and drop code on Windows where dragging from SciTE to
+ Firefox could hang both applications.
+ </li>
+ <li>
+ Crashing bug fixed on GTK+ when no font allocation succeeds.
+ </li>
+ <li>
+ Crashing bug fixed when autocompleting word longer than 1000 characters.
+ </li>
+ <li>
+ SciTE crashing bug fixed when both Find and Replace dialogs shown by disallowing
+ this situation.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite161.zip?download">Release 1.61</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 29 May 2004.
+ </li>
+ <li>
+ Improvements to selection handling on GTK+.
+ </li>
+ <li>
+ SciTE on GTK+ 2.4 uses the improved file chooser which allows
+ file extension filters, multiple selection, and remembers favourite
+ directories.
+ </li>
+ <li>
+ SciTE Load Session and Save Session commands available on GTK+.
+ </li>
+ <li>
+ SciTE lists Lua Startup Script in Options menu when loaded.
+ </li>
+ <li>
+ In SciTE, OnUserListSelection can be implemented in Lua.
+ </li>
+ <li>
+ SciTE on Windows has a context menu on the file tabs.
+ </li>
+ <li>
+ SQL lexer allows '#' comments and optionally '\' quoting inside strings.
+ </li>
+ <li>
+ Mssql lexer improved.
+ </li>
+ <li>
+ AutoIt3 lexer updated.
+ </li>
+ <li>
+ Perl lexer recognises regular expression use better.
+ </li>
+ <li>
+ Errorlist lexer understands Lua tracebacks and copes with findstr
+ output for file names that end with digits.
+ </li>
+ <li>
+ Drawing of lines on GTK+ improved and made more like Windows
+ without final point.
+ </li>
+ <li>
+ SciTE on GTK+ uses a high resolution window icon.
+ </li>
+ <li>
+ SciTE can be set to warn before loading files larger than a particular size.
+ </li>
+ <li>
+ SciTE Lua scripting bugs fixed included a crashing bug when using
+ an undefined function name that would go before first actual name.
+ </li>
+ <li>
+ SciTE bug fixed where a modified buffer was not saved if it was
+ the last buffer and was not current when the New command used.
+ </li>
+ <li>
+ SciTE monofont mode no longer affects line numbers.
+ </li>
+ <li>
+ Crashing bug in SciTE avoided by not allowing both the Find and Replace
+ dialogs to be visible at one time.
+ </li>
+ <li>
+ Crashing bug in SciTE fixed when Lua scripts were being run
+ concurrently.
+ </li>
+ <li>
+ Bug fixed that caused incorrect line number width in SciTE.
+ </li>
+ <li>
+ PHP folding bug fixed.
+ </li>
+ <li>
+ Regression fixed when setting word characters to not include
+ some of the standard word characters.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite160.zip?download">Release 1.60</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 May 2004.
+ </li>
+ <li>
+ SciTE can be scripted using the Lua programming language.
+ </li>
+ <li>
+ command.mode is a better way to specify tool command options in SciTE.
+ </li>
+ <li>
+ Continuation markers can be displayed so that you can see which lines are wrapped.
+ </li>
+ <li>
+ Lexer for Gui4Cli language.
+ </li>
+ <li>
+ Lexer for Kix language.
+ </li>
+ <li>
+ Lexer for Specman E language.
+ </li>
+ <li>
+ Lexer for AutoIt3 language.
+ </li>
+ <li>
+ Lexer for APDL language.
+ </li>
+ <li>
+ Lexer for Bash language. Also reasonable for other Unix shells.
+ </li>
+ <li>
+ SciTE can load lexers implemented in external shared libraries.
+ </li>
+ <li>
+ Perl treats "." not as part of an identifier and interprets '/' and '->'
+ correctly in more circumstances.
+ </li>
+ <li>
+ PHP recognises variables within strings.
+ </li>
+ <li>
+ NSIS has properties "nsis.uservars" and "nsis.ignorecase".
+ </li>
+ <li>
+ MSSQL lexer adds keyword list for operators and stored procedures,
+ defines '(', ')', and ',' as operators and changes some other details.
+ </li>
+ <li>
+ Input method preedit window on GTK+ 2 may support some Asian languages.
+ </li>
+ <li>
+ Platform interface adds an extra platform-specific flag to Font::Create.
+ Used on wxWidgets to choose antialiased text display but may be used for
+ any task that a platform needs.
+ </li>
+ <li>
+ OnBeforeSave method added to Extension interface.
+ </li>
+ <li>
+ Scintilla methods that return strings can be called with a NULL pointer
+ to find out how long the string should be.
+ </li>
+ <li>
+ Visual Studio .NET project file now in VS .NET 2003 format so can not be used
+ directly in VS .NET 2002.
+ </li>
+ <li>
+ Scintilla can be built with GTK+ 2 on Windows.
+ </li>
+ <li>
+ Updated RPM spec for SciTE on GTK+.
+ </li>
+ <li>
+ GTK+ makefile for SciTE allows selection of destination directory, creates destination
+ directories and sets file modes and owners better.
+ </li>
+ <li>
+ Tab indents now go to next tab multiple rather than add tab size.
+ </li>
+ <li>
+ SciTE abbreviations now use the longest possible match rather than the shortest.
+ </li>
+ <li>
+ Autocompletion does not remove prefix when actioned with no choice selected.
+ </li>
+ <li>
+ Autocompletion cancels when moving beyond the start position, not at the start position.
+ </li>
+ <li>
+ SciTE now shows only calltips for functions that match exactly, not
+ those that match as a prefix.
+ </li>
+ <li>
+ SciTE can repair box comment sections where some lines were added without
+ the box comment middle line prefix.
+ </li>
+ <li>
+ Alt+ works in user.shortcuts on Windows.
+ </li>
+ <li>
+ SciTE on GTK+ enables replace in selection for rectangular selections.
+ </li>
+ <li>
+ Key bindings for command.shortcut implemented in a way that doesn't break
+ when the menus are localised.
+ </li>
+ <li>
+ Drawing of background on GTK+ faster as theme drawing disabled.
+ </li>
+ <li>
+ On GTK+, calltips are moved back onto the screen if they extend beyond the screen bounds.
+ </li>
+ <li>
+ On Windows, the Scintilla object is destroyed on WM_NCDESTROY rather than
+ WM_DESTROY which arrives earlier. This fixes some problems when Scintilla was subclassed.
+ </li>
+ <li>
+ The zorder switching feature removed due to number of crashing bugs.
+ </li>
+ <li>
+ Code for XPM images made more robust.
+ </li>
+ <li>
+ Bug fixed with primary selection on GTK+.
+ </li>
+ <li>
+ On GTK+ 2, copied or cut text can still be pasted after the Scintilla widget is destroyed.
+ </li>
+ <li>
+ Styling change not visible problem fixed when line was cached.
+ </li>
+ <li>
+ Bug in SciTE on Windows fixed where clipboard commands stopped working.
+ </li>
+ <li>
+ Crashing bugs in display fixed in line layout cache.
+ </li>
+ <li>
+ Crashing bug may be fixed on AMD64 processor on GTK+.
+ </li>
+ <li>
+ Rare hanging crash fixed in Python lexer.
+ </li>
+ <li>
+ Display bugs fixed with DBCS characters on GTK+.
+ </li>
+ <li>
+ Autocompletion lists on GTK+ 2 are not sorted by the ListModel as the
+ contents are sorted correctly by Scintilla.
+ </li>
+ <li>
+ SciTE fixed to not open extra untitled buffers with check.if.already.open.
+ </li>
+ <li>
+ Sizing bug fixed on GTK+ when window resized while unmapped.
+ </li>
+ <li>
+ Text drawing crashing bug fixed on GTK+ with non-Pango fonts and long strings.
+ </li>
+ <li>
+ Fixed some issues if characters are unsigned.
+ </li>
+ <li>
+ Fixes in NSIS support.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite159.zip?download">Release 1.59</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 19 February 2004.
+ </li>
+ <li>
+ SciTE Options and Language menus reduced in length by commenting
+ out some languages. Languages can be enabled by editing the global
+ properties file.
+ </li>
+ <li>
+ Verilog language supported.
+ </li>
+ <li>
+ Lexer for Microsoft dialect of SQL. SciTE properties file available from extras page.
+ </li>
+ <li>
+ Perl lexer disambiguates '/' better.
+ </li>
+ <li>
+ NSIS lexer improved with a lexical class for numbers, option for ignoring case
+ of keywords, and folds only occurring when folding keyword first on line.
+ </li>
+ <li>
+ PowerBasic lexer improved with styles for constants and assembler and
+ folding improvements.
+ </li>
+ <li>
+ On GTK+, input method support only invoked for Asian languages and not
+ European languages as the old European keyboard code works better.
+ </li>
+ <li>
+ Scintilla can be requested to allocate a certain amount and so avoid repeated
+ reallocations and memory inefficiencies. SciTE uses this and so should require
+ less memory.
+ </li>
+ <li>
+ SciTE's "toggle current fold" works when invoked on child line as well as
+ fold header.
+ </li>
+ <li>
+ SciTE output pane scrolling can be set to not scroll back to start after
+ completion of command.
+ </li>
+ <li>
+ SciTE has a $(SessionPath) property.
+ </li>
+ <li>
+ SciTE on Windows can use VK_* codes for keys in user.shortcuts.
+ </li>
+ <li>
+ Stack overwrite bug fixed in SciTE's command to move to the end of a
+ preprocessor conditional.
+ </li>
+ <li>
+ Bug fixed where vertical selection appeared to select a different set of characters
+ then would be used by, for example, a copy.
+ </li>
+ <li>
+ SciTE memory leak fixed in fold state remembering.
+ </li>
+ <li>
+ Bug fixed where changing the style of some text outside the
+ standard StyleNeeded notification would not be visible.
+ </li>
+ <li>
+ On GTK+ 2 g_iconv is used in preference to iconv, as it is provided by GTK+
+ so should avoid problems finding the iconv library.
+ </li>
+ <li>
+ On GTK+ fixed a style reference count bug.
+ </li>
+ <li>
+ Memory corruption bug fixed with GetSelText.
+ </li>
+ <li>
+ On Windows Scintilla deletes memory on WM_NCDESTROY rather than
+ the earlier WM_DESTROY to avoid problems when the window is subclassed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite158.zip?download">Release 1.58</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 11 January 2004.
+ </li>
+ <li>
+ Method to discover the currently highlighted element in an autocompletion list.
+ </li>
+ <li>
+ On GTK+, the lexers are now included in the scintilla.a library file. This
+ will require changes to the make files of dependent projects.
+ </li>
+ <li>
+ Octave support added alongside related Matlab language and Matlab support improved.
+ </li>
+ <li>
+ VB lexer gains an unterminated string state and 4 sets of keywords.
+ </li>
+ <li>
+ Ruby lexer handles $' correctly.
+ </li>
+ <li>
+ Error line handling improved for FORTRAN compilers from Absoft and Intel.
+ </li>
+ <li>
+ International input enabled on GTK+ 2 although there is no way to choose an
+ input method.
+ </li>
+ <li>
+ MultiplexExtension in SciTE allows multiple extensions to be used at once.
+ </li>
+ <li>
+ Regular expression replace interprets backslash expressions \a, \b, \f, \n, \r, \t,
+ and \v in the replacement value.
+ </li>
+ <li>
+ SciTE Replace dialog displays number of replacements made when Replace All or
+ Replace in Selection performed.
+ </li>
+ <li>
+ Localisation files may contain a translation.encoding setting which is used
+ on GTK+ 2 to automatically reencode the translation to UTF-8 so it will be
+ the localised text will be displayed correctly.
+ </li>
+ <li>
+ SciTE on GTK+ implements check.if.already.open.
+ </li>
+ <li>
+ Make files for Mac OS X made more robust.
+ </li>
+ <li>
+ Performance improved in SciTE when switching buffers when there
+ is a rectangular selection.
+ </li>
+ <li>
+ Fixed failure to display some text when wrapped.
+ </li>
+ <li>
+ SciTE crashes from Ctrl+Tab buffer cycling fixed.
+ May still be some rare bugs here.
+ </li>
+ <li>
+ Crash fixed when decoding an error message that appears similar to a
+ Borland error message.
+ </li>
+ <li>
+ Fix to auto-scrolling allows containers to implement enhanced double click selection.
+ </li>
+ <li>
+ Hang fixed in idle word wrap.
+ </li>
+ <li>
+ Crash fixed in hotspot display code..
+ </li>
+ <li>
+ SciTE on Windows Incremental Search no longer moves caret back.
+ </li>
+ <li>
+ SciTE hang fixed when performing a replace with a find string that
+ matched zero length strings such as ".*".
+ </li>
+ <li>
+ SciTE no longer styles the whole file when saving buffer fold state
+ as that was slow.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite157.zip?download">Release 1.57</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 27 November 2003.
+ </li>
+ <li>
+ SciTE remembers folding of each buffer.
+ </li>
+ <li>
+ Lexer for Erlang language.
+ </li>
+ <li>
+ Scintilla allows setting the set of white space characters.
+ </li>
+ <li>
+ Scintilla has 'stuttered' page movement commands to first move
+ to top or bottom within current visible lines before scrolling.
+ </li>
+ <li>
+ Scintilla commands for moving to end of words.
+ </li>
+ <li>
+ Incremental line wrap enabled on Windows.
+ </li>
+ <li>
+ SciTE PDF exporter produces output that is more compliant with reader
+ applications, is smaller and allows more configuration.
+ HTML exporter optimizes size of output files.
+ </li>
+ <li>
+ SciTE defines properties PLAT_WINNT and PLAT_WIN95 on the
+ corresponding platforms.
+ </li>
+ <li>
+ SciTE can adjust the line margin width to fit the largest line number.
+ The line.numbers property is split between line.margin.visible and
+ line.margin.width.
+ </li>
+ <li>
+ SciTE on GTK+ allows user defined menu accelerators.
+ Alt can be included in user.shortcuts.
+ </li>
+ <li>
+ SciTE Language menu can have items commented out.
+ </li>
+ <li>
+ SciTE on Windows Go to dialog allows choosing a column number as
+ well as a line number.
+ </li>
+ <li>
+ SciTE on GTK+ make file uses prefix setting more consistently.
+ </li>
+ <li>
+ Bug fixed that caused word wrapping to fail to display all text.
+ </li>
+ <li>
+ Crashing bug fixed in GTK+ version of Scintilla when using GDK fonts
+ and opening autocompletion.
+ </li>
+ <li>
+ Bug fixed in Scintilla SCI_GETSELTEXT where an extra NUL
+ was included at end of returned string
+ </li>
+ <li>
+ Crashing bug fixed in SciTE z-order switching implementation.
+ </li>
+ <li>
+ Hanging bug fixed in Perl lexer.
+ </li>
+ <li>
+ SciTE crashing bug fixed for using 'case' without argument in style definition.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite156.zip?download">Release 1.56</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 25 October 2003.
+ </li>
+ <li>
+ Rectangular selection can be performed using the keyboard.
+ Greater programmatic control over rectangular selection.
+ This has caused several changes to key bindings.
+ </li>
+ <li>
+ SciTE Replace In Selection works on rectangular selections.
+ </li>
+ <li>
+ Improved lexer for TeX, new lexer for Metapost and other support for these
+ languages.
+ </li>
+ <li>
+ Lexer for PowerBasic.
+ </li>
+ <li>
+ Lexer for Forth.
+ </li>
+ <li>
+ YAML lexer improved to include error styling.
+ </li>
+ <li>
+ Perl lexer improved to correctly handle more cases.
+ </li>
+ <li>
+ Assembler lexer updated to support single-quote strings and fix some
+ problems.
+ </li>
+ <li>
+ SciTE on Windows can switch between buffers in order of use (z-order) rather
+ than static order.
+ </li>
+ <li>
+ SciTE supports adding an extension for "Open Selected Filename".
+ The openpath setting works on GTK+.
+ </li>
+ <li>
+ SciTE can Export as XML.
+ </li>
+ <li>
+ SciTE $(SelHeight) variable gives a more natural result for empty and whole line
+ selections.
+ </li>
+ <li>
+ Fixes to wrapping problems, such as only first display line being visible in some
+ cases.
+ </li>
+ <li>
+ Fixes to hotspot to only highlight when over the hotspot, only use background
+ colour when set and option to limit hotspots to a single line.
+ </li>
+ <li>
+ Small fixes to FORTRAN lexing and folding.
+ </li>
+ <li>
+ SQL lexer treats single quote strings as a separate class to double quote strings..
+ </li>
+ <li>
+ Scintilla made compatible with expectations of container widget in GTK+ 2.3.
+ </li>
+ <li>
+ Fix to strip out pixmap ID when automatically choosing from an autocompletion
+ list with only one element.
+ </li>
+ <li>
+ SciTE bug fixed where UTF-8 files longer than 128K were gaining more than one
+ BOM.
+ </li>
+ <li>
+ Crashing bug fixed in SciTE on GTK+ where using "Stop Executing" twice leads
+ to all applications exiting.
+ </li>
+ <li>
+ Bug fixed in autocompletion scrolling on GTK+ 2 with a case sensitive list.
+ The ListBox::Sort method is no longer needed or available so platform
+ maintainers should remove it.
+ </li>
+ <li>
+ SciTE check.if.already.open setting removed from GTK+ version as unmaintained.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite155.zip?download">Release 1.55</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 25 September 2003.
+ </li>
+ <li>
+ Fix a crashing bug in indicator display in Scintilla.
+ </li>
+ <li>
+ GTK+ version now defaults to building for GTK+ 2 rather than 1.
+ </li>
+ <li>
+ Mingw make file detects compiler version and avoids options
+ that are cause problems for some versions.
+ </li>
+ <li>
+ Large performance improvement on GTK+ 2 for long lines.
+ </li>
+ <li>
+ Incremental line wrap on GTK+.
+ </li>
+ <li>
+ International text entry works much better on GTK+ with particular
+ improvements for Baltic languages and languages that use 'dead' accents.
+ NUL key events such as those generated by some function keys, ignored.
+ </li>
+ <li>
+ Unicode clipboard support on GTK+.
+ </li>
+ <li>
+ Indicator type INDIC_BOX draws a rectangle around the text.
+ </li>
+ <li>
+ Clarion language support.
+ </li>
+ <li>
+ YAML language support.
+ </li>
+ <li>
+ MPT LOG language support.
+ </li>
+ <li>
+ On Windows, SciTE can switch buffers based on activation order rather
+ than buffer number.
+ </li>
+ <li>
+ SciTE save.on.deactivate saves all buffers rather than just the current buffer.
+ </li>
+ <li>
+ Lua lexer handles non-ASCII characters correctly.
+ </li>
+ <li>
+ Error lexer understands Borland errors with pathnames that contain space.
+ </li>
+ <li>
+ On GTK+ 2, autocompletion uses TreeView rather than deprecated CList.
+ </li>
+ <li>
+ SciTE autocompletion removed when expand abbreviation command used.
+ </li>
+ <li>
+ SciTE calltips support overloaded functions.
+ </li>
+ <li>
+ When Save fails in SciTE, choice offered to Save As.
+ </li>
+ <li>
+ SciTE message boxes on Windows may be moved to front when needed.
+ </li>
+ <li>
+ Indicators drawn correctly on wrapped lines.
+ </li>
+ <li>
+ Regular expression search no longer matches characters with high bit
+ set to characters without high bit set.
+ </li>
+ <li>
+ Hang fixed in backwards search in multi byte character documents.
+ </li>
+ <li>
+ Hang fixed in SciTE Mark All command when wrap around turned off.
+ </li>
+ <li>
+ SciTE Incremental Search no longer uses hot keys on Windows.
+ </li>
+ <li>
+ Calltips draw non-ASCII characters correctly rather than as arrows.
+ </li>
+ <li>
+ SciTE crash fixed when going to an error message with empty file name.
+ </li>
+ <li>
+ Bugs fixed in XPM image handling code.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite154.zip?download">Release 1.54</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 12 August 2003.
+ </li>
+ <li>
+ SciTE on GTK+ 2.x can display a tab bar.
+ </li>
+ <li>
+ SciTE on Windows provides incremental search.
+ </li>
+ <li>
+ Lexer for PostScript.
+ </li>
+ <li>
+ Lexer for the NSIS scripting language.
+ </li>
+ <li>
+ New lexer for POV-Ray Scene Description Language
+ replaces previous implementation.
+ </li>
+ <li>
+ Lexer for the MMIX Assembler language.
+ </li>
+ <li>
+ Lexer for the Scriptol language.
+ </li>
+ <li>
+ Incompatibility: SQL keywords are specified in lower case rather than upper case.
+ SQL lexer allows double quoted strings.
+ </li>
+ <li>
+ Pascal lexer: character constants that start with '#' understood,
+ '@' only allowed within assembler blocks,
+ '$' can be the start of a number,
+ initial '.' in 0..constant not treated as part of a number,
+ and assembler blocks made more distinctive.
+ </li>
+ <li>
+ Lua lexer allows '.' in keywords.
+ Multi-line strings and comments can be folded.
+ </li>
+ <li>
+ CSS lexer handles multiple psuedoclasses.
+ </li>
+ <li>
+ Properties file folder works for INI file format.
+ </li>
+ <li>
+ Hidden indicator style allows the container to mark text within Scintilla
+ without there being any visual effect.
+ </li>
+ <li>
+ SciTE does not prompt to save changes when the buffer is empty and untitled.
+ </li>
+ <li>
+ Modification notifications caused by SCI_INSERTSTYLEDSTRING
+ now include the contents of the insertion.
+ </li>
+ <li>
+ SCI_MARKERDELETEALL deletes all the markers on a line
+ rather than just the first match.
+ </li>
+ <li>
+ Better handling of 'dead' accents on GTK+ 2 for languages
+ that use accented characters.
+ </li>
+ <li>
+ SciTE now uses value of output.vertical.size property.
+ </li>
+ <li>
+ Crash fixed in SciTE autocompletion on long lines.
+ </li>
+ <li>
+ Crash fixed in SciTE comment command on long lines.
+ </li>
+ <li>
+ Bug fixed with backwards regular expression search skipping
+ every second match.
+ </li>
+ <li>
+ Hang fixed with regular expression replace where both target and replacement were empty.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite153.zip?download">Release 1.53</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 16 May 2003.
+ </li>
+ <li>
+ On GTK+ 2, encodings other than ASCII, Latin1, and Unicode are
+ supported for both display and input using iconv.
+ </li>
+ <li>
+ External lexers supported on GTK+/Linux.
+ External lexers must now be explicitly loaded with SCI_LOADLEXERLIBRARY
+ rather than relying upon a naming convention and automatic loading.
+ </li>
+ <li>
+ Support of Lout typesetting language.
+ </li>
+ <li>
+ Support of E-Scripts language used in the POL Ultima Online Emulator.
+ </li>
+ <li>
+ Scrolling and drawing performance on GTK+ enhanced, particularly for GTK+ 2.x
+ with an extra window for the text area avoiding conflicts with the scroll bars.
+ </li>
+ <li>
+ CopyText and CopyRange methods in Scintilla allow container to
+ easily copy to the system clipboard.
+ </li>
+ <li>
+ Line Copy command implemented and bound to Ctrl+Shift+T.
+ </li>
+ <li>
+ Scintilla APIs PositionBefore and PositionAfter can be used to iterate through
+ a document taking into account the encoding and multi-byte characters.
+ </li>
+ <li>
+ C++ folder can fold on the "} else {" line of an if statement by setting
+ fold.at.else property to 1.
+ </li>
+ <li>
+ C++ lexer allows an extra set of keywords.
+ </li>
+ <li>
+ Property names and thus abbreviations may be non-ASCII.
+ </li>
+ <li>
+ Removed attempt to load a file when setting properties that was
+ part of an old scripting experiment.
+ </li>
+ <li>
+ SciTE no longer warns about a file not existing when opening
+ properties files from the Options menu as there is a good chance
+ the user wants to create one.
+ </li>
+ <li>
+ Bug fixed with brace recognition in multi-byte encoded files where a partial
+ character matched a brace byte.
+ </li>
+ <li>
+ More protection against infinite loops or recursion with recursive property definitions.
+ </li>
+ <li>
+ On Windows, cursor will no longer disappear over margins in custom builds when
+ cursor resource not present. The Windows default cursor is displayed instead.
+ </li>
+ <li>
+ load.on.activate fixed in SciTE as was broken in 1.52.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite152.zip?download">Release 1.52</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 17 April 2003.
+ </li>
+ <li>
+ Pango font support on GTK+ 2.
+ Unicode input improved on GTK+ 2.
+ </li>
+ <li>
+ Hotspot style implemented in Scintilla.
+ </li>
+ <li>
+ Small up and down arrows can be displayed in calltips and the container
+ is notified when the mouse is clicked on a calltip.
+ Normal and selected calltip text colours can be set.
+ </li>
+ <li>
+ POSIX compatibility flag in Scintilla regular expression search
+ interprets bare ( and ) as tagged sections.
+ </li>
+ <li>
+ Error message lexer tightened to yield fewer false matches.
+ Recognition of Lahey and Intel FORTRAN error formats.
+ </li>
+ <li>
+ Scintilla keyboard commands for moving to start and end of
+ screen lines rather than document lines, unless already there
+ where these keys move to the start or end of the document line.
+ </li>
+ <li>
+ Line joining command.
+ </li>
+ <li>
+ Lexer for POV-Ray.
+ </li>
+ <li>
+ Calltips on Windows are no longer clipped by the parent window.
+ </li>
+ <li>
+ Autocompletion lists are cancelled when focus leaves their parent window.
+ </li>
+ <li>
+ Move to next/previous empty line delimited paragraph key commands.
+ </li>
+ <li>
+ SciTE hang fixed with recursive property definitions by placing limit
+ on number of substitutions performed.
+ </li>
+ <li>
+ SciTE Export as PDF reenabled and works.
+ </li>
+ <li>
+ Added loadsession: command line command to SciTE.
+ </li>
+ <li>
+ SciTE option to quit application when last document closed.
+ </li>
+ <li>
+ SciTE option to ask user if it is OK to reload a file that has been
+ modified outside SciTE.
+ </li>
+ <li>
+ SciTE option to automatically save before running particular command tools
+ or to ask user or to not save.
+ </li>
+ <li>
+ SciTE on Windows 9x will write a Ctrl+Z to the process input pipe before
+ closing the pipe when running tool commands that take input.
+ </li>
+ <li>
+ Added a manifest resource to SciTE on Windows to enable Windows XP
+ themed UI.
+ </li>
+ <li>
+ SciTE calltips handle nested calls and other situations better.
+ </li>
+ <li>
+ CSS lexer improved.
+ </li>
+ <li>
+ Interface to platform layer changed - Surface initialisation now requires
+ a WindowID parameter.
+ </li>
+ <li>
+ Bug fixed with drawing or measuring long pieces of text on Windows 9x
+ by truncating the pieces.
+ </li>
+ <li>
+ Bug fixed with SciTE on GTK+ where a user shortcut for a visible character
+ inserted the character as well as executing the command.
+ </li>
+ <li>
+ Bug fixed where primary selection on GTK+ was reset by
+ Scintilla during creation.
+ </li>
+ <li>
+ Bug fixed where SciTE would close immediately on startup
+ when using save.session.
+ </li>
+ <li>
+ Crash fixed when entering '\' in LaTeX file.
+ </li>
+ <li>
+ Hang fixed when '#' last character in VB file.
+ </li>
+ <li>
+ Crash fixed in error message lexer.
+ </li>
+ <li>
+ Crash fixed when searching for long regular expressions.
+ </li>
+ <li>
+ Pressing return when nothing selected in user list sends notification with
+ empty text rather than random text.
+ </li>
+ <li>
+ Mouse debouncing disabled on Windows as it interfered with some
+ mouse utilities.
+ </li>
+ <li>
+ Bug fixed where overstrike mode inserted before rather than replaced last
+ character in document.
+ </li>
+ <li>
+ Bug fixed with syntax highlighting of Japanese text.
+ </li>
+ <li>
+ Bug fixed in split lines function.
+ </li>
+ <li>
+ Cosmetic fix to SciTE tab bar on Windows when window resized.
+ Focus sticks to either pane more consistently.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite151.zip?download">Release 1.51</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 16 February 2003.
+ </li>
+ <li>
+ Two phase drawing avoids cutting off text that overlaps runs by drawing
+ all the backgrounds of a line then drawing all the text transparently.
+ Single phase drawing is an option.
+ </li>
+ <li>
+ Scintilla method to split lines at a particular width by adding new line
+ characters.
+ </li>
+ <li>
+ The character used in autocompletion lists to separate the text from the image
+ number can be changed.
+ </li>
+ <li>
+ The scrollbar range will automatically expand when the caret is moved
+ beyond the current range.
+ The scroll bar is updated when SCI_SETXOFFSET is called.
+ </li>
+ <li>
+ Mouse cursors on GTK+ improved to be consistent with other applications
+ and the Windows version.
+ </li>
+ <li>
+ Horizontal scrollbar on GTK+ now disappears in wrapped mode.
+ </li>
+ <li>
+ Scintilla on GTK+ 2: mouse wheel scrolling, cursor over scrollbars, focus,
+ and syntax highlighting now work.
+ gtk_selection_notify avoided for compatibility with GTK+ 2.2.
+ </li>
+ <li>
+ Fold margin colours can now be set.
+ </li>
+ <li>
+ SciTE can be built for GTK+ 2.
+ </li>
+ <li>
+ SciTE can optionally preserve the undo history over an automatic file reload.
+ </li>
+ <li>
+ Tags can optionally be case insensitive in XML and HTML.
+ </li>
+ <li>
+ SciTE on Windows handles input to tool commands in a way that should avoid
+ deadlock. Output from tools can be used to replace the selection.
+ </li>
+ <li>
+ SciTE on GTK+ automatically substitutes '|' for '/' in menu items as '/'
+ is used to define the menu hierarchy.
+ </li>
+ <li>
+ Optional buffer number in SciTE title bar.
+ </li>
+ <li>
+ Crash fixed in SciTE brace matching.
+ </li>
+ <li>
+ Bug fixed where automatic scrolling past end of document
+ flipped back to the beginning.
+ </li>
+ <li>
+ Bug fixed where wrapping caused text to disappear.
+ </li>
+ <li>
+ Bug fixed on Windows where images in autocompletion lists were
+ shown on the wrong item.
+ </li>
+ <li>
+ Crash fixed due to memory bug in autocompletion lists on Windows.
+ </li>
+ <li>
+ Crash fixed when double clicking some error messages.
+ </li>
+ <li>
+ Bug fixed in word part movement where sometimes no movement would occur.
+ </li>
+ <li>
+ Bug fixed on Windows NT where long text runs were truncated by
+ treating NT differently to 9x where there is a limitation.
+ </li>
+ <li>
+ Text in not-changeable style works better but there remain some cases where
+ it is still possible to delete text protected this way.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite150.zip?download">Release 1.50</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 24 January 2003.
+ </li>
+ <li>
+ Autocompletion lists may have a per-item pixmap.
+ </li>
+ <li>
+ Autocompletion lists allow Unicode text on Windows.
+ </li>
+ <li>
+ Scintilla documentation rewritten.
+ </li>
+ <li>
+ Additional DBCS encoding support in Scintilla on GTK+ primarily aimed at
+ Japanese EUC encoding.
+ </li>
+ <li>
+ CSS (Cascading Style Sheets) lexer added.
+ </li>
+ <li>
+ diff lexer understands some more formats.
+ </li>
+ <li>
+ Fold box feature is an alternative way to show the structure of code.
+ </li>
+ <li>
+ Avenue lexer supports multiple keyword lists.
+ </li>
+ <li>
+ The caret may now be made invisible by setting the caret width to 0.
+ </li>
+ <li>
+ Python folder attaches comments before blocks to the next block rather
+ than the previous block.
+ </li>
+ <li>
+ SciTE openpath property on Windows searches a path for files that are
+ the subject of the Open Selected Filename command.
+ </li>
+ <li>
+ The localisation file name can be changed with the locale.properties property.
+ </li>
+ <li>
+ On Windows, SciTE can pipe the result of a string expression into a command line tool.
+ </li>
+ <li>
+ On Windows, SciTE's Find dialog has a Mark All button.
+ </li>
+ <li>
+ On Windows, there is an Insert Abbreviation command that allows a choice from
+ the defined abbreviations and inserts the selection into the abbreviation at the
+ position of a '|'.
+ </li>
+ <li>
+ Minor fixes to Fortran lexer.
+ </li>
+ <li>
+ fold.html.preprocessor decides whether to fold &lt;? and ?&gt;.
+ Minor improvements to PHP folding.
+ </li>
+ <li>
+ Maximum number of keyword lists allowed increased from 6 to 9.
+ </li>
+ <li>
+ Duplicate line command added with default assignment to Ctrl+D.
+ </li>
+ <li>
+ SciTE sets $(Replacements) to the number of replacements made by the
+ Replace All command. $(CurrentWord) is set to the word before the caret if the caret
+ is at the end of a word.
+ </li>
+ <li>
+ Opening a SciTE session now loads files in remembered order, sets the current file
+ as remembered, and moves the caret to the remembered line.
+ </li>
+ <li>
+ Bugs fixed with printing on Windows where line wrapping was causing some text
+ to not print.
+ </li>
+ <li>
+ Bug fixed with Korean Input Method Editor on Windows.
+ </li>
+ <li>
+ Bugs fixed with line wrap which would sometimes choose different break positions
+ after switching focus away and back.
+ </li>
+ <li>
+ Bug fixed where wheel scrolling had no effect on GTK+ after opening a fold.
+ </li>
+ <li>
+ Bug fixed with file paths containing non-ASCII characters on Windows.
+ </li>
+ <li>
+ Crash fixed with printing on Windows after defining pixmap marker.
+ </li>
+ <li>
+ Crash fixed in makefile lexer when first character on line was '='.
+ </li>
+ <li>
+ Bug fixed where local properties were not always being applied.
+ </li>
+ <li>
+ Ctrl+Keypad* fold command works on GTK+.
+ </li>
+ <li>
+ Hangs fixed in SciTE's Replace All command when replacing regular expressions '^'
+ or '$'.
+ </li>
+ <li>
+ SciTE monospace setting behaves more sensibly.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite149.zip?download">Release 1.49</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 November 2002.
+ </li>
+ <li>
+ Unicode supported on GTK+. To perform well, this added a font cache to GTK+
+ and to make that safe, a mutex is used. The mutex requires the application to link in
+ the threading library by evaluating `glib-config --libs gthread`. A Unicode locale
+ should also be set up by a call like setlocale(LC_CTYPE, "en_US.UTF-8").
+ scintilla_release_resources function added to release mutex.
+ </li>
+ <li>
+ FORTRAN and assembler lexers added along with other support for these
+ languages in SciTE.
+ </li>
+ <li>
+ Ada lexer improved handling of based numbers, identifier validity and attributes
+ distinguished from character literals.
+ </li>
+ <li>
+ Lua lexer handles block comments and a deep level of nesting for literal strings
+ and block comments.
+ </li>
+ <li>
+ Errorlist lexer recognises PHP error messages.
+ </li>
+ <li>
+ Variant of the C++ lexer with case insensitive keywords
+ called cppnocase. Whitespace in preprocessor text handled more correctly.
+ </li>
+ <li>
+ Folder added for Perl.
+ </li>
+ <li>
+ Compilation with GCC 3.2 supported.
+ </li>
+ <li>
+ Markers can be pixmaps.
+ </li>
+ <li>
+ Lines are wrapped when printing.
+ Bug fixed which printed line numbers in different styles.
+ </li>
+ <li>
+ Text can be appended to end with AppendText method.
+ </li>
+ <li>
+ ChooseCaretX method added.
+ </li>
+ <li>
+ Vertical scroll bar can be turned off with SetVScrollBar method.
+ </li>
+ <li>
+ SciTE Save All command saves all buffers.
+ </li>
+ <li>
+ SciTE localisation compares keys case insensitively to make translations more flexible.
+ </li>
+ <li>
+ SciTE detects a utf-8 coding cookie "coding: utf-8" in first two
+ lines and goes into Unicode mode.
+ </li>
+ <li>
+ SciTE key bindings are definable.
+ </li>
+ <li>
+ SciTE Find in Files dialog can display directory browser to
+ choose directory to search.
+ </li>
+ <li>
+ SciTE enabling of undo and redo toolbar buttons improved.
+ </li>
+ <li>
+ SciTE on Windows file type filters in open dialog sorted.
+ </li>
+ <li>
+ Fixed crashing bug when using automatic tag closing in XML or HTML.
+ </li>
+ <li>
+ Fixed bug on Windows causing very long (&gt;64K) lines to not display.
+ </li>
+ <li>
+ Fixed bug in backwards regular expression searching.
+ </li>
+ <li>
+ Fixed bug in calltips where wrong argument was highlighted.
+ </li>
+ <li>
+ Fixed bug in tab timmy feature when file has line feed line endings.
+ </li>
+ <li>
+ Fixed bug in compiling without INCLUDE_DEPRECATED_FEATURES
+ defined.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite148.zip?download">Release 1.48</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 9 September 2002.
+ </li>
+ <li>
+ Improved Pascal lexer with context sensitive keywords
+ and separate folder which handles //{ and //} folding comments and
+ {$region} and {$end} folding directives.
+ The "case" statement now folds correctly.
+ </li>
+ <li>
+ C++ lexer correctly handles comments on preprocessor lines.
+ </li>
+ <li>
+ New commands for moving to beginning and end of display lines when in line
+ wrap mode. Key bindings added for these commands.
+ </li>
+ <li>
+ New marker symbols that look like ">>>" and "..." which can be used for
+ interactive shell prompts for Python.
+ </li>
+ <li>
+ The foreground and background colours of visible whitespace can be chosen
+ independent of the colours chosen for the lexical class of that whitespace.
+ </li>
+ <li>
+ Per line data optimised by using an exponential allocation scheme.
+ </li>
+ <li>
+ SciTE API file loading optimised.
+ </li>
+ <li>
+ SciTE for GTK+ subsystem 2 documented. The exit status of commands
+ is decoded into more understandable fields.
+ </li>
+ <li>
+ SciTE find dialog remembers previous find string when there is no selection.
+ Find in Selection button disabled when selection is rectangular as command
+ did not work.
+ </li>
+ <li>
+ Shift+Enter made equivalent to Enter to avoid users having to let go of
+ the shift key when typing. Avoids the possibility of entering single carriage
+ returns in a file that contains CR+LF line ends.
+ </li>
+ <li>
+ Autocompletion does not immediately disappear when the length parameter
+ to SCI_AUTOCSHOW is 0.
+ </li>
+ <li>
+ SciTE focuses on the editor pane when File | New executed and when the
+ output pane is closed with F8. Double clicking on a non-highlighted output
+ pane line selects the word under the cursor rather than seeking the next
+ highlighted line.
+ </li>
+ <li>
+ SciTE director interface implements an "askproperty" command.
+ </li>
+ <li>
+ SciTE's Export as LaTeX output improved.
+ </li>
+ <li>
+ Better choice of autocompletion displaying above the caret rather then
+ below when that is more sensible.
+ </li>
+ <li>
+ Bug fixed where context menu would not be completely visible if invoked
+ when cursor near bottom or left of screen.
+ </li>
+ <li>
+ Crashing bug fixed when displaying long strings on GTK+ caused failure of X server
+ by displaying long text in segments.
+ </li>
+ <li>
+ Crashing bug fixed on GTK+ when a Scintilla window was removed from its parent
+ but was still the selection owner.
+ </li>
+ <li>
+ Bug fixed on Windows in Unicode mode where not all characters on a line
+ were displayed when that line contained some characters not in ASCII.
+ </li>
+ <li>
+ Crashing bug fixed in SciTE on Windows with clearing output while running command.
+ </li>
+ <li>
+ Bug fixed in SciTE for GTK+ with command completion not detected when
+ no output was produced by the command.
+ </li>
+ <li>
+ Bug fixed in SciTE for Windows where menus were not shown translated.
+ </li>
+ <li>
+ Bug fixed where words failed to display in line wrapping mode with visible
+ line ends.
+ </li>
+ <li>
+ Bug fixed in SciTE where files opened from a session file were not closed.
+ </li>
+ <li>
+ Cosmetic flicker fixed when using Ctrl+Up and Ctrl+Down with some caret policies.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite147.zip?download">Release 1.47</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 August 2002.
+ </li>
+ <li>
+ Support for GTK+ 2 in Scintilla. International input methods not supported
+ on GTK+2.
+ </li>
+ <li>
+ Line wrapping performance improved greatly.
+ </li>
+ <li>
+ New caret policy implementation that treats horizontal and vertical
+ positioning equivalently and independently. Old caret policy methods
+ deprecated and not all options work correctly with old methods.
+ </li>
+ <li>
+ Extra fold points for C, C++, Java, ... for fold comments //{ .. //} and
+ #if / #ifdef .. #endif and the #region .. #endregion feature of C#.
+ </li>
+ <li>
+ Scintilla method to find the height in pixels of a line. Currently returns the
+ same result for every line as all lines are same height.
+ </li>
+ <li>
+ Separate make file, scintilla_vc6.mak, for Scintilla to use Visual C++
+ version 6 since main makefile now assumes VS .NET.
+ VS .NET project files available for combined Scintilla and
+ SciTE in scite/boundscheck.
+ </li>
+ <li>
+ SciTE automatically recognises Unicode files based
+ on their Byte Order Marks and switches to Unicode mode.
+ On Windows, where SciTE supports Unicode display, this
+ allows display of non European characters.
+ The file is saved back into the same character encoding unless
+ the user decides to switch using the File | Encoding menu.
+ </li>
+ <li>
+ Handling of character input changed so that a fillup character, typically '('
+ displays a calltip when an autocompletion list was being displayed.
+ </li>
+ <li>
+ Multiline strings lexed better for C++ and Lua.
+ </li>
+ <li>
+ Regular expressions in JavaScript within hypertext files are lexed better.
+ </li>
+ <li>
+ On Windows, Scintilla exports a function called Scintilla_DirectFunction
+ that can be used the same as the function returned by GetDirectFunction.
+ </li>
+ <li>
+ Scintilla converts line endings of text obtained from the clipboard to
+ the current default line endings.
+ </li>
+ <li>
+ New SciTE property ensure.final.line.end can ensure that saved files
+ always end with a new line as this is required by some tools.
+ The ensure.consistent.line.ends property ensures all line ends are the
+ current default when saving files.
+ The strip.trailing.spaces property now works on the buffer so the
+ buffer in memory and the file on disk are the same after a save is performed.
+ </li>
+ <li>
+ The SciTE expand abbreviation command again allows '|' characters
+ in expansions to be quoted by using '||'.
+ </li>
+ <li>
+ SciTE on Windows can send data to the find tool through standard
+ input rather than using a command line argument to avoid problems
+ with quoting command line arguments.
+ </li>
+ <li>
+ The Stop Executing command in SciTE on Windows improved to send
+ a Ctrl+Z character to the tool. Better messages when stopping a tool.
+ </li>
+ <li>
+ Autocompletion can automatically "fill up" when one of a set of characters is
+ type with the autocomplete.&lt;lexer&gt;.fillups property.
+ </li>
+ <li>
+ New predefined properties in SciTE, SelectionStartColumn, SelectionStartLine,
+ SelectionEndColumn, SelectionEndLine can be used to integrate with other
+ applications.
+ </li>
+ <li>
+ Environment variables are available as properties in SciTE.
+ </li>
+ <li>
+ SciTE on Windows keeps status line more current.
+ </li>
+ <li>
+ Abbreviations work in SciTE on Linux when first opened.
+ </li>
+ <li>
+ File saving fixed in SciTE to ensure files are not closed when they can not be
+ saved because of file permissions. Also fixed a problem with buffers that
+ caused files to not be saved.
+ </li>
+ <li>
+ SciTE bug fixed where monospace mode not remembered when saving files.
+ Some searching options now remembered when switching files.
+ </li>
+ <li>
+ SciTE on Linux now waits on child termination when it shuts a child down
+ to avoid zombies.
+ </li>
+ <li>
+ SciTE on Linux has a Print menu command that defaults to invoking a2ps.
+ </li>
+ <li>
+ Fixed incorrect highlighting of indentation guides in SciTE for Python.
+ </li>
+ <li>
+ Crash fixed in Scintilla when calling GetText for 0 characters.
+ </li>
+ <li>
+ Exporting as LaTeX improved when processing backslashes and tabs
+ and setting up font.
+ </li>
+ <li>
+ Crash fixed in SciTE when exporting or copying as RTF.
+ </li>
+ <li>
+ SciTE session loading fixed to handle more than 10 files in session.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite146.zip?download">Release 1.46</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 10 May 2002.
+ </li>
+ <li>
+ Set of lexers compiled into Scintilla can now be changed by adding and
+ removing lexer source files from scintilla/src and running LexGen.py.
+ </li>
+ <li>
+ SCN_ZOOM notification provided by Scintilla when user changes zoom level.
+ Method to determine width of strings in pixels so that elements can be sized
+ relative to text size.
+ SciTE changed to keep line number column displaying a given
+ number of characters.
+ </li>
+ <li>
+ The logical width of the document used to determine scroll bar range can be set.
+ </li>
+ <li>
+ Setting to allow vertical scrolling to display last line at top rather than
+ bottom of window.
+ </li>
+ <li>
+ Read-only mode improved to avoid changing the selection in most cases
+ when a modification is attempted. Drag and drop cursors display correctly
+ for read-only in some cases.
+ </li>
+ <li>
+ Visual C++ options in make files changed to suit Visual Studio .NET.
+ </li>
+ <li>
+ Scintilla.iface includes feature types for enumerations and lexers.
+ </li>
+ <li>
+ Lua lexer improves handling of literal strings and copes with nested literal strings.
+ </li>
+ <li>
+ Diff lexer changed to treat lines starting with "***" similarly to "---".
+ Symbolic names defined for lexical classes.
+ </li>
+ <li>
+ nncrontab lexer improved.
+ </li>
+ <li>
+ Turkish fonts (iso8859-9) supported on GTK+.
+ </li>
+ <li>
+ Automatic close tag feature for XML and HTML in SciTE.
+ </li>
+ <li>
+ Automatic indentation in SciTE improved.
+ </li>
+ <li>
+ Maximum number of buffers available in SciTE increased. May be up to 100
+ although other restrictions on menu length limit the real maximum.
+ </li>
+ <li>
+ Save a Copy command added to SciTE.
+ </li>
+ <li>
+ Export as TeX command added to SciTE.
+ </li>
+ <li>
+ Export as HTML command in SciTE respects Use Monospaced Font and
+ background colour settings.
+ </li>
+ <li>
+ Compilation problem on Solaris fixed.
+ </li>
+ <li>
+ Order of files displayed for SciTE's previous and next menu and key commands
+ are now consistent.
+ </li>
+ <li>
+ Saving of MRU in recent file changed so files open when SciTE quit
+ are remembered.
+ </li>
+ <li>
+ More variants of ctags tags handled by Open Selected Filename in SciTE.
+ </li>
+ <li>
+ JavaScript embedded in XML highlighted again.
+ </li>
+ <li>
+ SciTE status bar updated after changing parameters in case they are being
+ displayed in status bar.
+ </li>
+ <li>
+ Crash fixed when handling some multi-byte languages.
+ </li>
+ <li>
+ Crash fixed when replacing end of line characters.
+ </li>
+ <li>
+ Bug in SciTE fixed in multiple buffer mode where automatic loading
+ turned on could lead to losing file contents.
+ </li>
+ <li>
+ Bug in SciTE on GTK+ fixed where dismissing dialogs with close box led to
+ those dialogs never being shown again.
+ </li>
+ <li>
+ Bug in SciTE on Windows fixed where position.tile with default positions
+ led to SciTE being positioned off-screen.
+ </li>
+ <li>
+ Bug fixed in read-only mode, clearing all deletes contraction state data
+ leading to it not being synchronized with text.
+ </li>
+ <li>
+ Crash fixed in SciTE on Windows when tab bar displayed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite145.zip?download">Release 1.45</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 15 March 2002.
+ </li>
+ <li>
+ Line layout cache implemented to improve performance by maintaining
+ the positioning of characters on lines. Can be set to cache nothing,
+ the line with the caret, the visible page or the whole document.
+ </li>
+ <li>
+ Support, including a new lexer, added for Matlab programs.
+ </li>
+ <li>
+ Lua folder supports folding {} ranges and compact mode.
+ Lua lexer styles floating point numbers in number style instead of
+ setting the '.' in operator style.
+ Up to 6 sets of keywords.
+ Better support for [[ although only works well
+ when all on one line.
+ </li>
+ <li>
+ Python lexer improved to handle floating point numbers that contain negative
+ exponents and that start with '.'.
+ </li>
+ <li>
+ When performing a rectangular paste, the caret now remains at the
+ insertion point.
+ </li>
+ <li>
+ On Windows with a wheel mouse, page-at-a-time mode is recognised.
+ </li>
+ <li>
+ Read-only mode added to SciTE with a property to initialise it and another property,
+ $(ReadOnly) available to show this mode in the status bar.
+ </li>
+ <li>
+ SciTE status bar can show the number of lines in the selection
+ with the $(SelHeight) property.
+ </li>
+ <li>
+ SciTE's "Export as HTML" command uses the current character set to produce
+ correct output for non-Western-European character sets, such as Russian.
+ </li>
+ <li>
+ SciTE's "Export as RTF" fixed to produce correct output when file contains '\'.
+ </li>
+ <li>
+ SciTE goto command accepts a column as well as a line.
+ If given a column, it selects the word at that column.
+ </li>
+ <li>
+ SciTE's Build, Compile and Go commands are now disabled if no
+ action has been assigned to them.
+ </li>
+ <li>
+ The Refresh button in the status bar has been removed from SciTE on Windows.
+ </li>
+ <li>
+ Bug fixed in line wrap mode where cursor up or down command did not work.
+ </li>
+ <li>
+ Some styling bugs fixed that were due to a compilation problem with
+ gcc and inline functions with same name but different code.
+ </li>
+ <li>
+ The way that lexers loop over text was changed to avoid accessing beyond the
+ end or setting beyond the end. May fix some bugs and make the code safer but
+ may also cause new bugs.
+ </li>
+ <li>
+ Bug fixed in HTML lexer's handling of SGML.
+ </li>
+ <li>
+ Bug fixed on GTK+/X where lines wider than 32767 pixels did not display.
+ </li>
+ <li>
+ SciTE bug fixed with file name generation for standard property files.
+ </li>
+ <li>
+ SciTE bug fixed with Open Selected Filename command when used with
+ file name and line number combination.
+ </li>
+ <li>
+ In SciTE, indentation and tab settings stored with buffers so maintained correctly
+ as buffers selected.
+ The properties used to initialise these settings can now be set separately for different
+ file patterns.
+ </li>
+ <li>
+ Thread safety improved on Windows with a critical section protecting the font
+ cache and initialisation of globals performed within Scintilla_RegisterClasses.
+ New Scintilla_ReleaseResources call provided to allow explicit freeing of resources
+ when statically bound into another application. Resources automatically freed
+ in DLL version. The window classes are now unregistered as part of resource
+ freeing which fixes bugs that occurred in some containers such as Internet Explorer.
+ </li>
+ <li>
+ 'make install' fixed on Solaris.
+ </li>
+ <li>
+ Bug fixed that could lead to a file being opened twice in SciTE.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite144.zip?download">Release 1.44</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 4 February 2002.
+ </li>
+ <li>
+ Crashing bug fixed in Editor::Paint.
+ </li>
+ <li>
+ Lua lexer no longer treats '.' as a word character and
+ handles 6 keyword sets.
+ </li>
+ <li>
+ WordStartPosition and WordEndPosition take an onlyWordCharacters
+ argument.
+ </li>
+ <li>
+ SciTE option for simplified automatic indentation which repeats
+ the indentation of the previous line.
+ </li>
+ <li>
+ Compilation fix on Alpha because of 64 bit.
+ </li>
+ <li>
+ Compilation fix for static linking.
+ </li>
+ <li>
+ Limited maximum line length handled to 8000 characters as previous
+ value of 16000 was causing stack exhaustion crashes for some.
+ </li>
+ <li>
+ When whole document line selected, only the last display line gets
+ the extra selected rectangle at the right hand side rather than
+ every display line.
+ </li>
+ <li>
+ Caret disappearing bug fixed for the case that the caret was not on the
+ first display line of a document line.
+ </li>
+ <li>
+ SciTE bug fixed where untitled buffer containing text was sometimes
+ deleted without chance to save.
+ </li>
+ <li>
+ SciTE bug fixed where use.monospaced not working with
+ multiple buffers.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite143.zip?download">Release 1.43</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 19 January 2002.
+ </li>
+ <li>
+ Line wrapping robustness and performance improved in Scintilla.
+ </li>
+ <li>
+ Line wrapping option added to SciTE for both edit and output panes.
+ </li>
+ <li>
+ Static linking on Windows handles cursor resource better.
+ Documentation of static linking improved.
+ </li>
+ <li>
+ Autocompletion has an option to delete any word characters after the caret
+ upon selecting an item.
+ </li>
+ <li>
+ FOX version identified by PLAT_FOX in Platform.h.
+ </li>
+ <li>
+ Calltips in SciTE use the calltip.&lt;lexer&gt;.word.characters setting to
+ correctly find calltips for functions that include characters like '$' which
+ is not normally considered a word character.
+ </li>
+ <li>
+ SciTE has a command to show help on itself which gets hooked up to displaying
+ SciTEDoc.html.
+ </li>
+ <li>
+ SciTE option calltip.&lt;lexer&gt;.end.definition to display help text on a
+ second line of calltip.
+ </li>
+ <li>
+ Fixed the handling of the Buffers menu on GTK+ to ensure current buffer
+ indicated and no warnings occur.
+ Changed some menu items on GTK+ version to be same as Windows version.
+ </li>
+ <li>
+ use.monospaced property for SciTE determines initial state of Use Monospaced Font
+ setting.
+ </li>
+ <li>
+ The SciTE Complete Symbol command now works when there are no word
+ characters before the caret, even though it is slow to display the whole set of
+ symbols.
+ </li>
+ <li>
+ Function names removed from SciTE's list of PHP keywords. The full list of
+ predefined functions is available from another web site mentioned on the
+ Extras page.
+ </li>
+ <li>
+ Crashing bug at startup on GTK+ for some configurations fixed.
+ </li>
+ <li>
+ Crashing bug on GTK+ on 64 bit platforms fixed.
+ </li>
+ <li>
+ Compilation problem with some compilers fixed in GTK+.
+ </li>
+ <li>
+ Japanese text entry improved on Windows 9x.
+ </li>
+ <li>
+ SciTE recent files directory problem on Windows when HOME and SciTE_HOME
+ environment variables not set is now the directory of the executable.
+ </li>
+ <li>
+ Session files no longer include untitled buffers.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite142.zip?download">Release 1.42</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 24 December 2001.
+ </li>
+ <li>
+ Better localisation support including context menus and most messages.
+ Translations of the SciTE user interface available for Bulgarian,
+ French, German, Italian, Russian, and Turkish.
+ </li>
+ <li>
+ Can specify a character to use to indicate control characters
+ rather than having them displayed as mnemonics.
+ </li>
+ <li>
+ Scintilla key command for backspace that will not delete line
+ end characters.
+ </li>
+ <li>
+ Scintilla method to find start and end of words.
+ </li>
+ <li>
+ SciTE on GTK+ now supports the load.on.activate and save.on.deactivate
+ properties in an equivalent way to the Windows version.
+ </li>
+ <li>
+ The output pane of SciTE on Windows is now interactive so command line
+ utilities that prompt for input or confirmation can be used.
+ </li>
+ <li>
+ SciTE on Windows can choose directory for a "Find in Files"
+ command like the GTK+ version could.
+ </li>
+ <li>
+ SciTE can now load a set of API files rather than just one file.
+ </li>
+ <li>
+ ElapsedTime class added to Platform for accurate measurement of durations.
+ Used for debugging and for showing the user how long commands take in SciTE.
+ </li>
+ <li>
+ Baan lexer added.
+ </li>
+ <li>
+ In C++ lexer, document comment keywords no longer have to be at the start
+ of the line.
+ </li>
+ <li>
+ PHP lexer changed to match keywords case insensitively.
+ </li>
+ <li>
+ More shell keywords added.
+ </li>
+ <li>
+ SciTE support for VoiceXML added to xml.properties.
+ </li>
+ <li>
+ In SciTE the selection is not copied to the find field of the Search and Replace
+ dialogs if it contains end of line characters.
+ </li>
+ <li>
+ SciTE on Windows has a menu item to decide whether to respond to other
+ instances which are performing their check.if.already.open check.
+ </li>
+ <li>
+ SciTE accelerator key for Box Comment command changed to avoid problems
+ in non-English locales.
+ </li>
+ <li>
+ SciTE context menu includes Close command for the editor pane and
+ Hide command for the output pane.
+ </li>
+ <li>
+ output: command added to SciTE director interface to add text to the
+ output pane. The director interface can execute commands (such as tool
+ commands with subsystem set to 3) by sending a macro:run message.
+ </li>
+ <li>
+ SciTE on GTK+ will defer to the Window Manager for position if position.left or
+ position.top not set and for size if position.width or position.height not set.
+ </li>
+ <li>
+ SciTE on Windows has a position.tile property to place a second instance
+ to the right of the first.
+ </li>
+ <li>
+ Scintilla on Windows again supports EM_GETSEL and EM_SETSEL.
+ </li>
+ <li>
+ Problem fixed in Scintilla on Windows where control ID is no longer cached
+ as it could be changed by external code.
+ </li>
+ <li>
+ Problems fixed in SciTE on Windows when finding any other open instances at
+ start up when check.if.already.open is true.
+ </li>
+ <li>
+ Bugs fixed in SciTE where command strings were not always having
+ variables evaluated.
+ </li>
+ <li>
+ Bugs fixed with displaying partial double-byte and Unicode characters
+ in rectangular selections and at the edge when edge mode is EDGE_BACKGROUND.
+ Column numbers reported by GetColumn treat multiple byte characters as one column
+ rather than counting bytes.
+ </li>
+ <li>
+ Bug fixed with caret movement over folded lines.
+ </li>
+ <li>
+ Another bug fixed with tracking selection in secondary views when performing
+ modifications.
+ </li>
+ <li>
+ Horizontal scrolling and display of long lines optimised.
+ </li>
+ <li>
+ Cursor setting in Scintilla on GTK+ optimised.
+ </li>
+ <li>
+ Experimental changeable style attribute.
+ Set to false to make text read-only.
+ Currently only stops caret from being within not-changeable
+ text and does not yet stop deleting a range that contains
+ not-changeable text.
+ Can be used from SciTE by adding notchangeable to style entries.
+ </li>
+ <li>
+ Experimental line wrapping.
+ Currently has performance and appearence problems.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite141.zip?download">Release 1.41</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 6 November 2001.
+ </li>
+ <li>
+ Changed Platform.h to not include platform headers. This lessens likelihood and impact of
+ name clashes from system headers and also speeds up compilation.
+ Renamed DrawText to DrawTextNoClip to avoid name clash.
+ </li>
+ <li>
+ Changed way word functions work to treat a sequence of punctuation as
+ a word. This is more sensible and also more compatible with other editors.
+ </li>
+ <li>
+ Cursor changes over the margins and selection on GTK+ platform.
+ </li>
+ <li>
+ SC_MARK_BACKGROUND is a marker that only changes the line's background colour.
+ </li>
+ <li>
+ Enhanced Visual Basic lexer handles character date and octal literals,
+ and bracketed keywords for VB.NET. There are two VB lexers, vb and vbscript
+ with type indication characters like ! and $ allowed at the end of identifiers
+ in vb but not vbscript. Lexer states now separate from those used for C++ and
+ names start with SCE_B.
+ </li>
+ <li>
+ Lexer added for Bullant language.
+ </li>
+ <li>
+ The horizontal scroll position, xOffset, is now exposed through the API.
+ </li>
+ <li>
+ The SCN_POSCHANGED notification is deprecated as it was causing confusion.
+ Use SCN_UPDATEUI instead.
+ </li>
+ <li>
+ Compilation problems fixed for some versions of gcc.
+ </li>
+ <li>
+ Support for WM_GETTEXT restored on Windows.
+ </li>
+ <li>
+ Double clicking on an autocompletion list entry works on GTK+.
+ </li>
+ <li>
+ Bug fixed with case insensitive sorts for autocompletion lists.
+ </li>
+ <li>
+ Bug fixed with tracking selection in secondary views when performing modifications.
+ </li>
+ <li>
+ SciTE's abbreviation expansion feature will now indent expansions to the current
+ indentation level if indent.automatic is on.
+ </li>
+ <li>
+ SciTE allows setting up of parameters to commands from a dialog and can also
+ show this dialog automatically to prompt for arguments when running a command.
+ </li>
+ <li>
+ SciTE's Language menu (formerly Options | Use Lexer) is now defined by the
+ menu.language property rather than being hardcoded.
+ </li>
+ <li>
+ The user interface of SciTE can be localised to a particular language by editing
+ a locale.properties file.
+ </li>
+ <li>
+ On Windows, SciTE will try to move to the front when opening a new file from
+ the shell and using check.if.already.open.
+ </li>
+ <li>
+ SciTE can display the file name and directory in the title bar in the form
+ "file @ directory" when title.full.path=2.
+ </li>
+ <li>
+ The SciTE time.commands property reports the time taken by a command as well
+ as its status when completed.
+ </li>
+ <li>
+ The SciTE find.files property is now a list separated by '|' characters and this list is
+ added into the Files pull down of the Find in Files dialog.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite140.zip?download">Release 1.40</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 23 September 2001.
+ </li>
+ <li>
+ Removal of emulation of Win32 RichEdit control in core of Scintilla.
+ <em>This change may be incompatible with existing client code.</em>
+ Some emulation still done in Windows platform layer.
+ </li>
+ <li>
+ SGML support in the HTML/XML lexer.
+ </li>
+ <li>
+ SciTE's "Stop Executing" command will terminate GUI programs on
+ Windows NT and Windows 2000.
+ </li>
+ <li>
+ StyleContext class helps construct lexers that are simple and accurate.
+ Used in the C++, Eiffel, and Python lexers.
+ </li>
+ <li>
+ Clipboard operations in GTK+ version convert between platform '\n' line endings and
+ currently chosen line endings.
+ </li>
+ <li>
+ Any character in range 0..255 can be used as a marker.
+ This can be used to support numbered bookmarks, for example.
+ </li>
+ <li>
+ The default scripting language for ASP can be set.
+ </li>
+ <li>
+ New lexer and other support for crontab files used with the nncron scheduler.
+ </li>
+ <li>
+ Folding of Python improved.
+ </li>
+ <li>
+ The ` character is treated as a Python operator.
+ </li>
+ <li>
+ Line continuations ("\" at end of line) handled inside Python strings.
+ </li>
+ <li>
+ More consistent handling of line continuation ('\' at end of line) in
+ C++ lexer.
+ This fixes macro definitions that span more than one line.
+ </li>
+ <li>
+ C++ lexer can understand Doxygen keywords in doc comments.
+ </li>
+ <li>
+ SciTE on Windows allows choosing to open the "open" dialog on the directory
+ of the current file rather than in the default directory.
+ </li>
+ <li>
+ SciTE on Windows handles command line arguments in "check.if.already.open"
+ correctly when the current directory of the new instance is different to the
+ already open instance of SciTE.
+ </li>
+ <li>
+ "cwd" command (change working directory) defined for SciTE director interface.
+ </li>
+ <li>
+ SciTE "Export As HTML" produces better, more compliant, and shorter files.
+ </li>
+ <li>
+ SciTE on Windows allows several options for determining default file name
+ for exported files.
+ </li>
+ <li>
+ Automatic indentation of Python in SciTE fixed.
+ </li>
+ <li>
+ Exported HTML can support folding.
+ </li>
+ <li>
+ Bug fixed in SCI_GETTEXT macro command of director interface.
+ </li>
+ <li>
+ Cursor leak fixed on GTK+.
+ </li>
+ <li>
+ During SciTE shutdown, "identity" messages are no longer sent over the director interface.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite139.zip?download">Release 1.39</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 22 August 2001.
+ </li>
+ <li>
+ Windows version requires msvcrt.dll to be available so will not work
+ on original Windows 95 version 1. The msvcrt.dll file is installed
+ by almost everything including Internet Explorer so should be available.
+ </li>
+ <li>
+ Flattened tree control style folding margin. The SciTE fold.plus option is
+ now fold.symbols and has more values for the new styles.
+ </li>
+ <li>
+ Mouse dwell events are generated when the user holds the mouse steady
+ over Scintilla.
+ </li>
+ <li>
+ PositionFromPointClose is like PositionFromPoint but returns
+ INVALID_POSITION when point outside window or after end of line.
+ </li>
+ <li>
+ Input of Hungarian and Russian characters in GTK+ version works by
+ truncating input to 8 bits if in the range of normal characters.
+ </li>
+ <li>
+ Better choices for font descriptors on GTK+ for most character sets.
+ </li>
+ <li>
+ GTK+ Scintilla is destroyed upon receiving destroy signal rather than
+ destroy_event signal.
+ </li>
+ <li>
+ Style setting that force upper or lower case text.
+ </li>
+ <li>
+ Case-insensitive autocompletion lists work correctly.
+ </li>
+ <li>
+ Keywords can be prefix based so ^GTK_ will treat all words that start
+ with GTK_ as keywords.
+ </li>
+ <li>
+ Horizontal scrolling can be jumpy rather than gradual.
+ </li>
+ <li>
+ GetSelText places a '\0' in the buffer if the selection is empty..
+ </li>
+ <li>
+ EnsureVisible split into two methods EnsureVisible which will not scroll to show
+ the line and EnsureVisibleEnforcePolicy which may scroll.
+ </li>
+ <li>
+ Python folder has options to fold multi-line comments and triple quoted strings.
+ </li>
+ <li>
+ C++ lexer handles keywords before '.' like "this.x" in Java as keywords.
+ Compact folding mode option chooses whether blank lines after a structure are
+ folded with that structure. Second set of keywords with separate style supported.
+ </li>
+ <li>
+ Ruby lexer handles multi-line comments.
+ </li>
+ <li>
+ VB has folder.
+ </li>
+ <li>
+ PHP lexer has an operator style, handles "&lt;?" and "?&gt;" inside strings
+ and some comments.
+ </li>
+ <li>
+ TCL lexer which is just an alias for the C++ lexer so does not really
+ understand TCL syntax.
+ </li>
+ <li>
+ Error lines lexer has styles for Lua error messages and .NET stack traces.
+ </li>
+ <li>
+ Makefile lexer has a target style.
+ </li>
+ <li>
+ Lua lexer handles some [[]] string literals.
+ </li>
+ <li>
+ HTML and XML lexer have a SCE_H_SGML state for tags that
+ start with "&lt;!".
+ </li>
+ <li>
+ Fixed Scintilla bugs with folding. When modifications were performed near
+ folded regions sometimes no unfolding occurred when it should have. Deleting a
+ fold causing character sometimes failed to update fold information correctly.
+ </li>
+ <li>
+ Better support for Scintilla on GTK+ for Win32 including separate
+ PLAT_GTK_WIN32 definition and correct handling of rectangular selection
+ with clipboard operations.
+ </li>
+ <li>
+ SciTE has a Tools | Switch Pane (Ctrl+F6) command to switch focus between
+ edit and output panes.
+ </li>
+ <li>
+ SciTE option output.scroll allows automatic scrolling of output pane to
+ be turned off.
+ </li>
+ <li>
+ Commands can be typed into the SciTE output pane similar to a shell window.
+ </li>
+ <li>
+ SciTE properties magnification and output magnification set initial zoom levels.
+ </li>
+ <li>
+ Option for SciTE comment block command to place comments at start of line.
+ </li>
+ <li>
+ SciTE for Win32 has an option to minimize to the tray rather than the task bar.
+ </li>
+ <li>
+ Close button on SciTE tool bar for Win32.
+ </li>
+ <li>
+ SciTE compiles with GCC 3.0.
+ </li>
+ <li>
+ SciTE's automatic indentation of C++ handles braces without preceding keyword
+ correctly.
+ </li>
+ <li>
+ Bug fixed with GetLine method writing past the end of where it should.
+ </li>
+ <li>
+ Bug fixed with mouse drag automatic scrolling when some lines were folded.
+ </li>
+ <li>
+ Bug fixed because caret XEven setting was inverted.
+ </li>
+ <li>
+ Bug fixed where caret was initially visible even though window was not focussed.
+ </li>
+ <li>
+ Bug fixed where some file names could end with "\\" which caused slow
+ downs on Windows 9x.
+ </li>
+ <li>
+ On Win32, SciTE Replace dialog starts with focus on replacement text.
+ </li>
+ <li>
+ SciTE Go to dialog displays correct current line.
+ </li>
+ <li>
+ Fixed bug with SciTE opening multiple files at once.
+ </li>
+ <li>
+ Fixed bug with Unicode key values reported to container truncated.
+ </li>
+ <li>
+ Fixed bug with unnecessary save point notifications.
+ </li>
+ <li>
+ Fixed bugs with indenting and unindenting at start of line.
+ </li>
+ <li>
+ Monospace Font setting behaves more consistently.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite138.zip?download">Release 1.38</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 23 May 2001.
+ </li>
+ <li>
+ Loadable lexer plugins on Windows.
+ </li>
+ <li>
+ Ruby lexer and support.
+ </li>
+ <li>
+ Lisp lexer and support.
+ </li>
+ <li>
+ Eiffel lexer and support.
+ </li>
+ <li>
+ Modes for better handling of Tab and BackSpace keys within
+ indentation. Mode to avoid autocompletion list cancelling when
+ there are no viable matches.
+ </li>
+ <li>
+ ReplaceTarget replaced with two calls ReplaceTarget
+ (which is incompatible with previous ReplaceTarget) and
+ ReplaceTargetRE. Both of these calls have a count first
+ parameter which allows using strings containing nulls.
+ SearchInTarget and SetSearchFlags functions allow
+ specifying a search in several simple steps which helps
+ some clients which can not create structs or pointers easily.
+ </li>
+ <li>
+ Asian language input through an Input Method Editor works
+ on Windows 2000.
+ </li>
+ <li>
+ On Windows, control characters can be entered through use of
+ the numeric keypad in conjunction with the Alt key.
+ </li>
+ <li>
+ Document memory allocation changed to grow exponentially
+ which reduced time to load a 30 Megabyte file from
+ 1000 seconds to 25. Change means more memory may be used.
+ </li>
+ <li>
+ Word part movement keys now handled in Scintilla rather than
+ SciTE.
+ </li>
+ <li>
+ Regular expression '^' and '$' work more often allowing insertion
+ of text at start or end of line with a replace command.
+ Backslash quoted control characters \a, \b, \f, \t, and \v
+ recognised within sets.
+ </li>
+ <li>
+ Session files for SciTE.
+ </li>
+ <li>
+ Export as PDF command hidden in SciTE as it often failed.
+ Code still present so can be turned on by those willing to cope.
+ </li>
+ <li>
+ Bug fixed in HTML lexer handling % before &gt; as end ASP
+ even when no start ASP encountered.
+ Bug fixed when scripts ended with a quoted string and
+ end tag was not seen.
+ </li>
+ <li>
+ Bug fixed on Windows where context menu key caused menu to
+ appear in corner of screen rather than within window.
+ </li>
+ <li>
+ Bug fixed in SciTE's Replace All command not processing
+ whole file when replace string longer than search string.
+ </li>
+ <li>
+ Bug fixed in SciTE's MRU list repeating entries if Ctrl+Tab
+ used when all entries filled.
+ </li>
+ <li>
+ ConvertEOLs call documentation fixed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite137.zip?download">Release 1.37</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 17 April 2001.
+ </li>
+ <li>
+ Bug fixed with scroll bars being invisible on GTK+ 1.2.9.
+ </li>
+ <li>
+ Scintilla and SciTE support find and replace using simple regular
+ expressions with tagged expressions. SciTE supports C '\' escapes
+ in the Find and Replace dialogs.
+ Replace in Selection available in SciTE.
+ </li>
+ <li>
+ Scintilla has a 'target' feature for replacing code rapidly without
+ causing display updates.
+ </li>
+ <li>
+ Scintilla and SciTE on GTK+ support file dropping from file managers
+ such as Nautilus and gmc. Files or other URIs dropped on Scintilla
+ result in a URIDropped notification.
+ </li>
+ <li>
+ Lexers may have separate Lex and Fold functions.
+ </li>
+ <li>
+ Lexer infrastructure improved to allow for plug in lexers and for referring
+ to lexers by name rather than by ID.
+ </li>
+ <li>
+ Ada lexer and support added.
+ </li>
+ <li>
+ Option in both Scintilla and SciTE to treat both left and right margin
+ as equally important when repositioning visible area in response to
+ caret movement. Default is to prefer visible area positioning which
+ minimises the horizontal scroll position thus favouring the left margin.
+ </li>
+ <li>
+ Caret line highlighting.
+ </li>
+ <li>
+ Commands to delete from the caret to the end of line and
+ from the caret to the beginning of line.
+ </li>
+ <li>
+ SciTE has commands for inserting and removing block comments and
+ for inserting stream comments.
+ </li>
+ <li>
+ SciTE Director interface uses C++ '\' escapes to send control characters.
+ </li>
+ <li>
+ SciTE Director interface adds more commands including support for macros.
+ </li>
+ <li>
+ SciTE has menu options for recording and playing macros which are visible
+ when used with a companion program that supports these features.
+ </li>
+ <li>
+ SciTE has an Expand Abbreviation command.
+ Abbreviations are stored in a global abbrev.properties file.
+ </li>
+ <li>
+ SciTE has a Full Screen command to switch between a normal window
+ size and using the full screen. On Windows, the menu bar can be turned
+ off when in full screen mode.
+ </li>
+ <li>
+ SciTE has a Use monospaced font command to switch between the normal
+ set of fonts and one size of a particular fixed width font.
+ </li>
+ <li>
+ SciTE's use of tabs can be controlled for particular file names
+ as well as globally.
+ </li>
+ <li>
+ The contents of SciTE's status bar can be defined by a property and
+ include variables. On Windows, several status bar definitions can be active
+ with a click on the status bar cycling through them.
+ </li>
+ <li>
+ Copy as RTF command in SciTE on Windows to allow pasting
+ styled text into word processors.
+ </li>
+ <li>
+ SciTE can allow the use of non-alphabetic characters in
+ Complete Symbol lists and can automatically display this autocompletion
+ list when a trigger character such as '.' is typed.
+ Complete word can be set to pop up when the user is typing a word and
+ there is only one matching word in the document.
+ </li>
+ <li>
+ SciTE lists the imported properties files on a menu to allow rapid
+ access to them.
+ </li>
+ <li>
+ SciTE on GTK+ improvements to handling accelerator keys and focus
+ in dialogs. Message boxes respond to key presses without the Alt key as
+ they have no text entries to accept normal keystrokes.
+ </li>
+ <li>
+ SciTE on GTK+ sets the application icon.
+ </li>
+ <li>
+ SciTE allows setting the colours used to indicate the current
+ error line.
+ </li>
+ <li>
+ Variables within PHP strings have own style. Keyword list updated.
+ </li>
+ <li>
+ Keyword list for Lua updated for Lua 4.0.
+ </li>
+ <li>
+ Bug fixed in rectangular selection where rectangle still appeared
+ selected after using cursor keys to move caret.
+ </li>
+ <li>
+ Bug fixed in C++ lexer when deleting a '{' controlling a folded range
+ led to that range becoming permanently invisible.
+ </li>
+ <li>
+ Bug fixed in Batch lexer where comments were not recognised.
+ </li>
+ <li>
+ Bug fixed with undo actions coalescing into steps incorrectly.
+ </li>
+ <li>
+ Bug fixed with Scintilla on GTK+ positioning scroll bars 1 pixel
+ over the Scintilla window leading to their sides being chopped off.
+ </li>
+ <li>
+ Bugs fixed in SciTE when doing some actions led to the start
+ or end of the file being displayed rather than the current location.
+ </li>
+ <li>
+ Appearance of calltips fixed to look like document text including
+ any zoom factor. Positioned to be outside current line even when
+ multiple fonts and sizes used.
+ </li>
+ <li>
+ Bug fixed in Scintilla macro support where typing Enter caused both a newline
+ command and newline character insertion to be recorded.
+ </li>
+ <li>
+ Bug fixed in SciTE on GTK+ where focus was moving
+ between widgets incorrectly.
+ </li>
+ <li>
+ Bug fixed with fold symbols sometimes not updating when
+ the text changed.
+ </li>
+ <li>
+ Bugs fixed in SciTE's handling of folding commands.
+ </li>
+ <li>
+ Deprecated undo collection enumeration removed from API.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite136.zip?download">Release 1.36</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 March 2001.
+ </li>
+ <li>
+ Scintilla supports GTK+ on Win32.
+ </li>
+ <li>
+ Some untested work on making Scintilla and SciTE 64 bit compatible.
+ For users on GTK+ this requires including Scintilla.h before
+ ScintillaWidget.h.
+ </li>
+ <li>
+ HTML lexer allows folding HTML.
+ </li>
+ <li>
+ New lexer for Avenue files which are used in the ESRI ArcView GIS.
+ </li>
+ <li>
+ DOS Batch file lexer has states for '@', external commands, variables and
+ operators.
+ </li>
+ <li>
+ C++ lexer can fold comments of /* .. */ form.
+ </li>
+ <li>
+ Better disabling of popup menu items in Scintilla when in read-only mode.
+ </li>
+ <li>
+ Starting to move to Doxygen compatible commenting.
+ </li>
+ <li>
+ Director interface on Windows enables another application to control SciTE.
+ </li>
+ <li>
+ Opening SciTE on Windows 9x sped up greatly for some cases.
+ </li>
+ <li>
+ The command.build.directory property allows SciTE to run the build
+ command in a different directory to the source files.
+ </li>
+ <li>
+ SciTE on Windows allows setting foreground and background colours
+ for printed headers and footers.
+ </li>
+ <li>
+ Bug fixed in finding calltips in SciTE which led to no calltips for some identifiers.
+ </li>
+ <li>
+ Documentation added for lexers and for the extension and director interfaces.
+ </li>
+ <li>
+ SciTE menus rearranged with new View menu taking over some of the items that
+ were under the Options menu. Clear All Bookmarks command added.
+ </li>
+ <li>
+ Clear Output command in SciTE.
+ </li>
+ <li>
+ SciTE on Windows gains an Always On Top command.
+ </li>
+ <li>
+ Bug fixed in SciTE with attempts to define properties recursively.
+ </li>
+ <li>
+ Bug fixed in SciTE properties where only one level of substitution was done.
+ </li>
+ <li>
+ Bug fixed in SciTE properties where extensions were not being
+ matched in a case insensitive manner.
+ </li>
+ <li>
+ Bug fixed in SciTE on Windows where the Go to dialog displays the correct
+ line number.
+ </li>
+ <li>
+ In SciTE, if fold.on.open set then switching buffers also performs fold.
+ </li>
+ <li>
+ Bug fixed in Scintilla where ensuring a line was visible in the presence of folding
+ operated on the document line instead of the visible line.
+ </li>
+ <li>
+ SciTE command line processing modified to operate on arguments in order and in
+ two phases. First any arguments before the first file name are processed, then the
+ UI is opened, then the remaining arguments are processed. Actions defined for the
+ Director interface (currently only "open") may also be used on the command line.
+ For example, "SciTE -open:x.txt" will start SciTE and open x.txt.
+ </li>
+ <li>
+ Numbered menu items SciTE's Buffers menu and the Most Recently Used portion
+ of the File menu go from 1..0 rather than 0..9.
+ </li>
+ <li>
+ The tab bar in SciTE for Windows has numbers.
+ The tab.hide.one option hides the tab bar until there is more than one buffer open.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite135.zip?download">Release 1.35</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 29 January 2001.
+ </li>
+ <li>
+ Rewritten and simplified widget code for the GTK+ version to enhance
+ solidity and make more fully compliant with platform norms. This includes more
+ normal handling of keystrokes so they are forwarded to containers correctly.
+ </li>
+ <li>
+ User defined lists can be shown.
+ </li>
+ <li>
+ Many fixes to the Perl lexer.
+ </li>
+ <li>
+ Pascal lexer handles comments more correctly.
+ </li>
+ <li>
+ C/C++/Java/JavaScipt lexer has a state for line doc comments.
+ </li>
+ <li>
+ Error output lexer understands Sun CC messages.
+ </li>
+ <li>
+ Make file lexer has variable, preprocessor, and operator states.
+ </li>
+ <li>
+ Wider area given to an italics character that is at the end of a line to prevent it
+ being cut off.
+ </li>
+ <li>
+ Call to move the caret inside the currently visible area.
+ </li>
+ <li>
+ Paste Rectangular will space fill on the left hand side of the pasted text as
+ needed to ensure it is kept rectangular.
+ </li>
+ <li>
+ Cut and Paste Rectangular does nothing in read-only mode.
+ </li>
+ <li>
+ Undo batching changed so that a paste followed by typing creates two undo actions..
+ </li>
+ <li>
+ A "visibility policy" setting for Scintilla determines which range of lines are displayed
+ when a particular line is moved to. Also exposed as a property in SciTE.
+ </li>
+ <li>
+ SciTE command line allows property settings.
+ </li>
+ <li>
+ SciTE has a View Output command to hide or show the output pane.
+ </li>
+ <li>
+ SciTE's Edit menu has been split in two with searching commands moved to a
+ new Search menu. Find Previous and Previous Bookmark are in the Search menu.
+ </li>
+ <li>
+ SciTE on Windows has options for setting print margins, headers and footers.
+ </li>
+ <li>
+ SciTE on Windows has tooltips for toolbar.
+ </li>
+ <li>
+ SciTE on GTK+ has properties for setting size of file selector.
+ </li>
+ <li>
+ Visual and audio cues in SciTE on Windows enhanced.
+ </li>
+ <li>
+ Fixed performance problem in SciTE for GTK+ by dropping the extra 3D
+ effect on the content windows.
+ </li>
+ <li>
+ Fixed problem in SciTE where choosing a specific lexer then meant
+ that no lexer was chosen when files opened.
+ </li>
+ <li>
+ Default selection colour changed to be visible on low colour displays.
+ </li>
+ <li>
+ Fixed problems with automatically reloading changed documents in SciTE on
+ Windows.
+ </li>
+ <li>
+ Fixed problem with uppercase file extensions in SciTE.
+ </li>
+ <li>
+ Fixed some problems when using characters >= 128, some of which were being
+ incorrectly treated as spaces.
+ </li>
+ <li>
+ Fixed handling multiple line tags, non-inline scripts, and XML end tags /&gt; in HTML/XML lexer.
+ </li>
+ <li>
+ Bookmarks in SciTE no longer disappear when switching between buffers.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite134.zip?download">Release 1.34</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 28 November 2000.
+ </li>
+ <li>
+ Pascal lexer.
+ </li>
+ <li>
+ Export as PDF in SciTE.
+ </li>
+ <li>
+ Support for the OpenVMS operating system in SciTE.
+ </li>
+ <li>
+ SciTE for GTK+ can check for another instance of SciTE
+ editing a file and switch to it rather than open a second instance
+ on one file.
+ </li>
+ <li>
+ Fixes to quoting and here documents in the Perl lexer.
+ </li>
+ <li>
+ SciTE on Windows can give extra visual and audio cues when a
+ warning is shown or find restarts from beginning of file.
+ </li>
+ <li>
+ Open Selected Filename command in SciTE. Also understands some
+ warning message formats.
+ </li>
+ <li>
+ Wider area for line numbers when printing.
+ </li>
+ <li>
+ Better scrolling performance on GTK+.
+ </li>
+ <li>
+ Fixed problem where rectangles with negative coordinates were
+ invalidated leading to trouble with platforms that use
+ unsigned coordinates.
+ </li>
+ <li>
+ GTK+ Scintilla uses more compliant signalling code so that keyboard
+ events should propagate to containers.
+ </li>
+ <li>
+ Bug fixed with opening full or partial paths.
+ </li>
+ <li>
+ Improved handling of paths in error messages in SciTE.
+ </li>
+ <li>
+ Better handling of F6 in SciTE.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite133.zip?download">Release 1.33</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 6 November 2000.
+ </li>
+ <li>
+ XIM support for the GTK+ version of Scintilla ensures that more non-English
+ characters can be typed.
+ </li>
+ <li>
+ Caret may be 1, 2, or 3 pixels wide.
+ </li>
+ <li>
+ Cursor may be switched to wait image during lengthy processing.
+ </li>
+ <li>
+ Scintilla's internal focus flag is exposed for clients where focus is handled in
+ complex ways.
+ </li>
+ <li>
+ Error status defined for Scintilla to hold indication that an operation failed and the reason
+ for that failure. No detection yet implemented but clients may start using the interface
+ so as to be ready for when it does.
+ </li>
+ <li>
+ Context sensitive help in SciTE.
+ </li>
+ <li>
+ CurrentWord property available in SciTE holding the value of the word the
+ caret is within or near.
+ </li>
+ <li>
+ Apache CONF file lexer.
+ </li>
+ <li>
+ Changes to Python lexer to allow 'as' as a context sensitive keyword and the
+ string forms starting with u, r, and ur to be recognised.
+ </li>
+ <li>
+ SCN_POSCHANGED notification now working and SCN_PAINTED notification added.
+ </li>
+ <li>
+ Word part movement commands for cursoring between the parts of reallyLongCamelIdentifiers and
+ other_ways_of_making_words.
+ </li>
+ <li>
+ When text on only one line is selected, Shift+Tab moves to the previous tab stop.
+ </li>
+ <li>
+ Tab control available for Windows version of SciTE listing all the buffers
+ and making it easy to switch between them.
+ </li>
+ <li>
+ SciTE can be set to automatically determine the line ending type from the contents of a
+ file when it is opened.
+ </li>
+ <li>
+ Dialogs in GTK+ version of SciTE made more modal and have accelerator keys.
+ </li>
+ <li>
+ Find in Files command in GTK+ version of SciTE allows choice of directory.
+ </li>
+ <li>
+ On Windows, multiple files can be opened at once.
+ </li>
+ <li>
+ SciTE source broken up into more files.
+ </li>
+ <li>
+ Scintilla headers made safe for C language, not just C++.
+ </li>
+ <li>
+ New printing modes - force background to white and force default background to white.
+ </li>
+ <li>
+ Automatic unfolding not occurring when Enter pressed at end of line bug fixed.
+ </li>
+ <li>
+ Bugs fixed in line selection.
+ </li>
+ <li>
+ Bug fixed with escapes in PHP strings in the HTML lexer.
+ </li>
+ <li>
+ Bug fixed in SciTE for GTK+ opening files when given full paths.
+ </li>
+ <li>
+ Bug fixed in autocompletion where user backspaces into existing text.
+ </li>
+ <li>
+ Bugs fixed in opening files and ensuring they are saved before running.
+ A case bug also fixed here.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite132.zip?download">Release 1.32</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 8 September 2000.
+ </li>
+ <li>
+ Fixes bugs in complete word and related code. Protection against a bug when
+ receiving a bad argument.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite131.zip?download">Release 1.31</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 6 September 2000.
+ </li>
+ <li>
+ Scintilla is available as a COM control from the scintillactrl module in CVS.
+ </li>
+ <li>
+ Style setting to underline text. Exposed in SciTE as "underlined".
+ </li>
+ <li>
+ Style setting to make text invisible.
+ </li>
+ <li>
+ SciTE has an extensibility interface that can be used to implement features such as
+ a scripting language or remote control. An example use of this is the extlua module
+ available from CVS which allows SciTE to be scripted in Lua.
+ </li>
+ <li>
+ Many minor fixes to all of the lexers.
+ </li>
+ <li>
+ New lexer for diff and patch files.
+ </li>
+ <li>
+ Error message lexer understands Perl error messages.
+ </li>
+ <li>
+ C/C++/Java lexer now supports C#, specifically verbatim strings and
+ @ quoting of identifiers that are the same as keywords. SciTE has
+ a set of keywords for C# and a build command set up for C#.
+ </li>
+ <li>
+ Scintilla property to see whether in overtype or insert state.
+ </li>
+ <li>
+ PosChanged notification fired when caret moved.
+ </li>
+ <li>
+ Comboboxes in dialogs in SciTE on Windows can be horizontally scrolled.
+ </li>
+ <li>
+ Autocompletion and calltips can treat the document as case sensitive or
+ case insensitive.
+ </li>
+ <li>
+ Autocompletion can be set to automatically choose the only
+ element in a single element list.
+ </li>
+ <li>
+ Set of characters that automatically complete an autocompletion list
+ can be set.
+ </li>
+ <li>
+ SciTE command to display calltip - useful when dropped because of
+ editing.
+ </li>
+ <li>
+ SciTE has a Revert command to go back to the last saved version.
+ </li>
+ <li>
+ SciTE has an Export as RTF command. Save as HTML is renamed
+ to Export as HTML and is located on the Export sub menu.
+ </li>
+ <li>
+ SciTE command "Complete Word" searches document for any
+ words starting with characters before caret.
+ </li>
+ <li>
+ SciTE options for changing aspects of the formatting of files exported
+ as HTML or RTF.
+ </li>
+ <li>
+ SciTE "character.set" option for choosing the character
+ set for all fonts.
+ </li>
+ <li>
+ SciTE has a "Toggle all folds" command.
+ </li>
+ <li>
+ The makefiles have changed. The makefile_vc and
+ makefile_bor files in scintilla/win32 and scite/win32 have been
+ merged into scintilla/win32/scintilla.mak and scite/win32/scite.mak.
+ DEBUG may be defined for all make files and this will turn on
+ assertions and for some make files will choose other debugging
+ options.
+ </li>
+ <li>
+ To make debugging easier and allow good use of BoundsChecker
+ there is a Visual C++ project file in scite/boundscheck that builds
+ all of Scintilla and SciTE into one executable.
+ </li>
+ <li>
+ The size of the SciTE output window can be set with the
+ output.horizontal.size and output.vertical.size settings.
+ </li>
+ <li>
+ SciTE status bar indicator for insert or overwrite mode.
+ </li>
+ <li>
+ Performance improvements to autocompletion and calltips.
+ </li>
+ <li>
+ A caret redraw problem when undoing is fixed.
+ </li>
+ <li>
+ Crash with long lines fixed.
+ </li>
+ <li>
+ Bug fixed with merging markers when lines merged.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite130.zip?download">Release 1.30</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 26 July 2000.
+ </li>
+ <li>
+ Much better support for PHP which is now an integral part of the HTML support.
+ </li>
+ <li>
+ Start replacement of Windows-specific APIs with cross platform APIs.
+ In 1.30, the new APIs are introduced but the old APIs are still available.
+ For the GTK+ version, may have to include "WinDefs.h" explicitly to
+ use the old APIs.
+ </li>
+ <li>
+ "if" and "import" statements in SciTE properties files allows modularisation into
+ language-specific properties files and choices based upon platform.
+ This means that SciTE is delivered with 9 language-specific properties files
+ as well as the standard SciTEGlobal.properties file.
+ </li>
+ <li>
+ Much lower resource usage on Windows 9x.
+ </li>
+ <li>
+ "/p" option in SciTE on Windows for printing a file and then exiting.
+ </li>
+ <li>
+ Options for printing with inverted brightness (when the screen is set to use
+ a dark background) and to force black on white printing.
+ </li>
+ <li>
+ Option for printing magnified or miniaturised from screen settings.
+ </li>
+ <li>
+ In SciTE, Ctrl+F3 and Ctrl+Shift+F3 find the selection in the forwards and backwards
+ directions respectively.
+ </li>
+ <li>
+ Auto-completion lists may be set to cancel when the cursor goes before
+ its start position or before the start of string being completed.
+ </li>
+ <li>
+ Auto-completion lists automatically size more sensibly.
+ </li>
+ <li>
+ SCI_CLEARDOCUMENTSTYLE zeroes all style bytes, ensures all
+ lines are shown and deletes all folding information.
+ </li>
+ <li>
+ On Windows, auto-completion lists are visually outdented rather than indented.
+ </li>
+ <li>
+ Close all command in SciTE.
+ </li>
+ <li>
+ On Windows multiple files can be dragged into SciTE.
+ </li>
+ <li>
+ When saving a file, the SciTE option save.deletes.first deletes it before doing the save.
+ This allows saving with a different capitalisation on Windows.
+ </li>
+ <li>
+ When use tabs option is off pressing the tab key inserts spaces.
+ </li>
+ <li>
+ Bug in indicators leading to extra line drawn fixed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite128.zip?download">Release 1.28</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 27 June 2000.
+ </li>
+ <li>
+ Fixes crash in indentation guides when indent size set to 0.
+ </li>
+ <li>
+ Fixes to installation on GTK+/Linux. User properties file on GTK+ has a dot at front of name:
+ .SciTEUser.properties. Global properties file location configurable at compile time
+ defaulting to $prefix/share/scite. $prefix determined from Gnome if present else its
+ /usr/local and can be overridden by installer. Gnome menu integration performed in
+ make install if Gnome present.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite127.zip?download">Release 1.27</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 23 June 2000.
+ </li>
+ <li>
+ Indentation guides. View whitespace mode may be set to not display whitespace
+ in indentation.
+ </li>
+ <li>
+ Set methods have corresponding gets for UndoCollection, BufferedDraw,
+ CodePage, UsePalette, ReadOnly, CaretFore, and ModEventMask.
+ </li>
+ <li>
+ Caret is continuously on rather than blinking while typing or holding down
+ delete or backspace. And is now always shown if non blinking when focused on GTK+.
+ </li>
+ <li>
+ Bug fixed in SciTE with file extension comparison now done in case insensitive way.
+ </li>
+ <li>
+ Bugs fixed in SciTE's file path handling on Windows.
+ </li>
+ <li>
+ Bug fixed with preprocessor '#' last visible character causing hang.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite126.zip?download">Release 1.26</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 13 June 2000.
+ </li>
+ <li>
+ Support for the Lua language in both Scintilla and SciTE.
+ </li>
+ <li>
+ Multiple buffers may be open in SciTE.
+ </li>
+ <li>
+ Each style may have a character set configured. This may determine
+ the characters that are displayed by the style.
+ </li>
+ <li>
+ In the C++ lexer, lexing of preprocessor source may either treat it all as being in
+ the preprocessor class or only the initial # and preprocessor command word as
+ being in the preprocessor class.
+ </li>
+ <li>
+ Scintilla provides SCI_CREATEDOCUMENT, SCI_ADDREFDOCUMENT, and
+ SCI_RELEASEDOCUMENT to make it easier for a container to deal with multiple
+ documents.
+ </li>
+ <li>
+ GTK+ specific definitions in Scintilla.h were removed to ScintillaWidget.h. All GTK+ clients will need to
+ #include "ScintillaWidget.h".
+ </li>
+ <li>
+ For GTK+, tools can be executed in the background by setting subsystem to 2.
+ </li>
+ <li>
+ Keys in the properties files are now case sensitive. This leads to a performance increase.
+ </li>
+ <li>
+ Menu to choose which lexer to use on a file.
+ </li>
+ <li>
+ Tab size dialog on Windows.
+ </li>
+ <li>
+ File dialogs enlarged on GTK+.
+ </li>
+ <li>
+ Match Brace command bound to Ctrl+E on both platforms with Ctrl+] a synonym on Windows.
+ Ctrl+Shift+E is select to matching brace. Brace matching tries to match to either the inside or the
+ outside, depending on whether the cursor is inside or outside the braces initially.
+ View End of Line bound to Ctrl+Shift+O.
+ </li>
+ <li>
+ The Home key may be bound to move the caret to either the start of the line or the start of the
+ text on the line.
+ </li>
+ <li>
+ Visual C++ project file for SciTE.
+ </li>
+ <li>
+ Bug fixed with current x location after Tab key.
+ </li>
+ <li>
+ Bug fixed with hiding fold margin by setting fold.margin.width to 0.
+ </li>
+ <li>
+ Bugs fixed with file name confusion on Windows when long and short names used, or different capitalisations,
+ or relative paths.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite125.zip?download">Release 1.25</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 9 May 2000.
+ </li>
+ <li>
+ Some Unicode support on Windows. Treats buffer and API as UTF-8 and displays
+ through UCS-2 of Windows.
+ </li>
+ <li>
+ Automatic indentation. Indentation size can be different to tab size.
+ </li>
+ <li>
+ Tool bar.
+ </li>
+ <li>
+ Status bar now on Windows as well as GTK+.
+ </li>
+ <li>
+ Input fields in Find and Replace dialogs now have history on both Windows and
+ GTK+.
+ </li>
+ <li>
+ Auto completion list items may be separated by a chosen character to allow spaces
+ in items. The selected item may be changed through the API.
+ </li>
+ <li>
+ Horizontal scrollbar can be turned off.
+ </li>
+ <li>
+ Property to remove trailing spaces when saving file.
+ </li>
+ <li>
+ On Windows, changed font size calculation to be more compatible with
+ other applications.
+ </li>
+ <li>
+ On GTK+, SciTE's global properties files are looked for in the directory specified in the
+ SCITE_HOME environment variable if it is set. This allows hiding in a dot directory.
+ </li>
+ <li>
+ Keyword lists in SciTE updated for JavaScript to include those destined to be used in
+ the future. IDL includes XPIDL keywords as well as MSIDL keywords.
+ </li>
+ <li>
+ Zoom level can be set and queried through API.
+ </li>
+ <li>
+ New notification sent before insertions and deletions.
+ </li>
+ <li>
+ LaTeX lexer.
+ </li>
+ <li>
+ Fixes to folding including when deletions and additions are performed.
+ </li>
+ <li>
+ Fix for crash with very long lines.
+ </li>
+ <li>
+ Fix to affect all of rectangular selections with deletion and case changing.
+ </li>
+ <li>
+ Removed non-working messages that had been included only for Richedit compatibility.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/scite124.zip">Release 1.24</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 29 March 2000.
+ </li>
+ <li>
+ Added lexing of IDL based on C++ lexer with extra UUID lexical class.
+ </li>
+ <li>
+ Functions and associated keys for Line Delete, Line Cut, Line Transpose,
+ Selection Lower Case and Selection Upper Case.
+ </li>
+ <li>
+ Property setting for SciTE, eol.mode, chooses initial state of line end characters.
+ </li>
+ <li>
+ Fixed bugs in undo history with small almost-contiguous changes being incorrectly coalesced.
+ </li>
+ <li>
+ Fixed bugs with incorrect expansion of ContractionState data structures causing crash.
+ </li>
+ <li>
+ Fixed bugs relating to null fonts.
+ </li>
+ <li>
+ Fixed bugs where recolourisation was not done sometimes when required.
+ </li>
+ <li>
+ Fixed compilation problems with SVector.h.
+ </li>
+ <li>
+ Fixed bad setting of fold points in Python.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite123.zip?download">Release 1.23</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 21 March 2000.
+ </li>
+ <li>
+ Directory structure to separate on basis of product (Scintilla, SciTE, DMApp)
+ and environment (Cross-platform, Win32, GTK+).
+ </li>
+ <li>
+ Download packaging to allow download of the source or platform dependent executables.
+ </li>
+ <li>
+ Source code now available from CVS at SourceForge.
+ </li>
+ <li>
+ Very simple Windows-only demonstration application DMApp is available from cvs as dmapp.
+ </li>
+ <li>
+ Lexing functionality may optionally be included in Scintilla rather than be provided by
+ the container.
+ </li>
+ <li>
+ Set of lexers included is determined at link time by defining which of the Lex* object files
+ are linked in.
+ </li>
+ <li>
+ On Windows, the SciLexer.DLL extends Scintilla.DLL with the standard lexers.
+ </li>
+ <li>
+ Enhanced HTML lexer styles embedded VBScript and Python.
+ ASP segments are styled and ASP scripts in JavaScript, VBScript and Python are styled.
+ </li>
+ <li>
+ PLSQL and PHP supported.
+ </li>
+ <li>
+ Maximum number of lexical states extended to 128.
+ </li>
+ <li>
+ Lexers may store per line parse state for multiple line features such as ASP script language choice.
+ </li>
+ <li>
+ Lexing API simplified.
+ </li>
+ <li>
+ Project file for Visual C++.
+ </li>
+ <li>
+ Can now cycle through all recent files with Ctrl+Tab in SciTE.
+ </li>
+ <li>
+ Bookmarks in SciTE.
+ </li>
+ <li>
+ Drag and drop copy works when dragging to the edge of the selection.
+ </li>
+ <li>
+ Fixed bug with value sizes in properties file.
+ </li>
+ <li>
+ Fixed bug with last line in properties file not being used.
+ </li>
+ <li>
+ Bug with multiple views of one document fixed.
+ </li>
+ <li>
+ Keypad now works on GTK+.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/SciTE122.zip?download">Release 1.22</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 27 February 2000.
+ </li>
+ <li>
+ wxWindows platform defined.
+ Implementation for wxWindows will be available separately
+ from main Scintilla distribution.
+ </li>
+ <li>
+ Line folding in Scintilla.
+ </li>
+ <li>
+ SciTE performs syntax directed folding for C/C++/Java/JavaScript and for Python.
+ </li>
+ <li>
+ Optional macro recording support.
+ </li>
+ <li>
+ User properties file (SciTEUser.properties) allows for customisation by the user
+ that is not overwritten with each installation of SciTE.
+ </li>
+ <li>
+ Python lexer detects and highlights inconsistent indentation.
+ </li>
+ <li>
+ Margin API made more orthogonal. SCI_SETMARGINWIDTH and SCI_SETLINENUMBERWIDTH
+ are deprecated in favour of this new API.
+ </li>
+ <li>
+ Margins may be made sensitive to forward mouse click events to container.
+ </li>
+ <li>
+ SQL lexer and styles included.
+ </li>
+ <li>
+ Perl lexer handles regular expressions better.
+ </li>
+ <li>
+ Caret policy determines how closely caret is tracked by visible area.
+ </li>
+ <li>
+ New marker shapes: arrow pointing down, plus and minus.
+ </li>
+ <li>
+ Optionally display full path in title rather than just file name.
+ </li>
+ <li>
+ Container is notified when Scintilla gains or loses focus.
+ </li>
+ <li>
+ SciTE handles focus in a more standard way and applies the main
+ edit commands to the focused pane.
+ </li>
+ <li>
+ Container is notified when Scintilla determines that a line needs to be made visible.
+ </li>
+ <li>
+ Document watchers receive notification when document about to be deleted.
+ </li>
+ <li>
+ Document interface allows access to list of watchers.
+ </li>
+ <li>
+ Line end determined correctly for lines ending with only a '\n'.
+ </li>
+ <li>
+ Search variant that searches form current selection and sets selection.
+ </li>
+ <li>
+ SciTE understands format of diagnostic messages from WScript.
+ </li>
+ <li>
+ SciTE remembers top line of window for each file in MRU list so switching to a recent file
+ is more likely to show the same text as when the file was previously visible.
+ </li>
+ <li>
+ Document reference count now initialised correctly.
+ </li>
+ <li>
+ Setting a null document pointer creates an empty document.
+ </li>
+ <li>
+ WM_GETTEXT can no longer overrun buffer.
+ </li>
+ <li>
+ Polygon drawing bug fixed on GTK+.
+ </li>
+ <li>
+ Java and JavaScript lexers merged into C++ lexer.
+ </li>
+ <li>
+ C++ lexer indicates unterminated strings by colouring the end of the line
+ rather than changing the rest of the file to string style. This is less
+ obtrusive and helps the folding.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/SciTE121.zip?download">Release 1.21</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 2 February 2000.
+ </li>
+ <li>
+ Blank margins on left and right side of text.
+ </li>
+ <li>
+ SCN_CHECKBRACE renamed SCN_UPDATEUI and made more efficient.
+ </li>
+ <li>
+ SciTE source code refactored into platform independent and platform specific classes.
+ </li>
+ <li>
+ XML and Perl subset lexers in SciTE.
+ </li>
+ <li>
+ Large improvement to lexing speed.
+ </li>
+ <li>
+ A new subsystem, 2, allows use of ShellExec on Windows.
+ </li>
+ <li>
+ Borland compatible makefile.
+ </li>
+ <li>
+ Status bar showing caret position in GTK+ version of SciTE.
+ </li>
+ <li>
+ Bug fixes to selection drawing when part of selection outside window, mouse release over
+ scroll bars, and scroll positioning after deletion.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE120.zip">Release 1.2</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 21 January 2000.
+ </li>
+ <li>
+ Multiple views of one document.
+ </li>
+ <li>
+ Rectangular selection, cut, copy, paste, drag and drop.
+ </li>
+ <li>
+ Long line indication.
+ </li>
+ <li>
+ Reverse searching
+ </li>
+ <li>
+ Line end conversion.
+ </li>
+ <li>
+ Generic autocompletion and calltips in SciTE.
+ </li>
+ <li>
+ Call tip background colour can be set.
+ </li>
+ <li>
+ SCI_MARKERPREV for moving to a previous marker.
+ </li>
+ <li>
+ Caret kept more within window where possible.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE115.zip">Release 1.15</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 15 December 1999.
+ </li>
+ <li>
+ Brace highlighting and badlighting (for mismatched braces).
+ </li>
+ <li>
+ Visible line ends.
+ </li>
+ <li>
+ Multiple line call tips.
+ </li>
+ <li>
+ Printing now works from SciTE on Windows.
+ </li>
+ <li>
+ SciTE has a global "*" lexer style that is used as the basis for all the lexers' styles.
+ </li>
+ <li>
+ Fixes some warnings on GTK+ 1.2.6.
+ </li>
+ <li>
+ Better handling of modal dialogs on GTK+.
+ </li>
+ <li>
+ Resize handle drawn on pane splitter in SciTE on GTK+ so it looks more like a regular GTK+
+ *paned widget.
+ </li>
+ <li>
+ SciTE does not place window origin offscreen if no properties file found on GTK+.
+ </li>
+ <li>
+ File open filter remembered in SciTE on Windows.
+ </li>
+ <li>
+ New mechanism using style numbers 32 to 36 standardises the setting of styles for brace
+ highlighting, brace badlighting, line numbers, control characters and the default style.
+ </li>
+ <li>
+ Old messages SCI_SETFORE .. SCI_SETFONT have been replaced by the default style 32. The old
+ messages are deprecated and will disappear in a future version.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE114.zip">Release 1.14</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 20 November 1999.
+ </li>
+ <li>
+ Fixes a scrolling bug reported on GTK+.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE113.zip">Release 1.13</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 18 November 1999.
+ </li>
+ <li>
+ Fixes compilation problems with the mingw32 GCC 2.95.2 on Windows.
+ </li>
+ <li>
+ Control characters are now visible.
+ </li>
+ <li>
+ Performance has improved, particularly for scrolling.
+ </li>
+ <li>
+ Windows RichEdit emulation is more accurate. This may break client code that uses these
+ messages: EM_GETLINE, EM_GETLINECOUNT, EM_EXGETSEL, EM_EXSETSEL, EM_EXLINEFROMCHAR,
+ EM_LINELENGTH, EM_LINEINDEX, EM_CHARFROMPOS, EM_POSFROMCHAR, and EM_GETTEXTRANGE.
+ </li>
+ <li>
+ Menus rearranged and accelerator keys set for all static items.
+ </li>
+ <li>
+ Placement of space indicators in view whitespace mode is more accurate with some fonts.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE112.zip">Release 1.12</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 9 November 1999.
+ </li>
+ <li>
+ Packaging error in 1.11 meant that the compilation error was not fixed in that release.
+ Linux/GTK+ should compile with GCC 2.95 this time.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE111.zip">Release 1.11</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 7 November 1999.
+ </li>
+ <li>
+ Fixed a compilation bug in ScintillaGTK.cxx.
+ </li>
+ <li>
+ Added a README file to explain how to build.
+ </li>
+ <li>
+ GTK+/Linux downloads now include documentation.
+ </li>
+ <li>
+ Binary only Sc1.EXE one file download for Windows.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE110.zip">Release 1.1</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 6 November 1999.
+ </li>
+ <li>
+ Major restructuring for better modularity and platform independence.
+ </li>
+ <li>
+ Inter-application drag and drop.
+ </li>
+ <li>
+ Printing support in Scintilla on Windows.
+ </li>
+ <li>
+ Styles can select colouring to end of line. This can be used when a file contains more than
+ one language to differentiate between the areas in each language. An example is the HTML +
+ JavaScript styling in SciTE.
+ </li>
+ <li>
+ Actions can be grouped in the undo stack, so they will be undone together. This grouping is
+ hierarchical so higher level actions such as replace all can be undone in one go. Call to
+ discover whether there are any actions to redo.
+ </li>
+ <li>
+ The set of characters that define words can be changed.
+ </li>
+ <li>
+ Markers now have identifiers and can be found and deleted by their identifier. The empty
+ marker type can be used to make a marker that is invisible and which is only used to trace
+ where a particular line moves to.
+ </li>
+ <li>
+ Double click notification.
+ </li>
+ <li>
+ HTML styling in SciTE also styles embedded JavaScript.
+ </li>
+ <li>
+ Additional tool commands can be added to SciTE.
+ </li>
+ <li>
+ SciTE option to allow reloading if changed upon application activation and saving on
+ application deactivation. Not yet working on GTK+ version.
+ </li>
+ <li>
+ Entry fields in search dialogs remember last 10 user entries. Not working in all cases in
+ Windows version.
+ </li>
+ <li>
+ SciTE can save a styled copy of the current file in HTML format. As SciTE does not yet
+ support printing, this can be used to print a file by then using a browser to print the
+ HTML file.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE102.zip">Release 1.02</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 October 1999.
+ </li>
+ <li>
+ GTK+ version compiles with GCC 2.95.
+ </li>
+ <li>
+ Properly deleting objects when window destroyed under GTK+.
+ </li>
+ <li>
+ If the selection is not empty backspace deletes the selection.
+ </li>
+ <li>
+ Some X style middle mouse button handling for copying the primary selection to and from
+ Scintilla. Does not work in all cases.
+ </li>
+ <li>
+ HTML styling in SciTE.
+ </li>
+ <li>
+ Stopped dirty flag being set in SciTE when results pane modified.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE101.zip">Release 1.01</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 28 September 1999.
+ </li>
+ <li>
+ Better DBCS support on Windows including IME.
+ </li>
+ <li>
+ Wheel mouse support for scrolling and zooming on Windows. Zooming with Ctrl+KeypadPlus and
+ Ctrl+KeypadMinus.
+ </li>
+ <li>
+ Performance improvements especially on GTK+.
+ </li>
+ <li>
+ Caret blinking and settable colour on both GTK+ and Windows.
+ </li>
+ <li>
+ Drag and drop within a Scintilla window. On Windows, files can be dragged into SciTE.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/SciTE100.zip">Release 1.0</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 17 May 1999.
+ </li>
+ <li>
+ Changed name of "Tide" to "SciTE" to avoid clash with a TCL based IDE. "SciTE" is a
+ SCIntilla based Text Editor and is Latin meaning something like "understanding in a neat
+ way" and is also an Old English version of the word "shit".
+ </li>
+ <li>
+ There is a SCI_AUTOCSTOPS message for defining a string of characters that will stop
+ autocompletion mode. Autocompletion mode is cancelled when any cursor movement occurs apart
+ from backspace.
+ </li>
+ <li>
+ GTK+ version now splits horizontally as well as vertically and all dialogs cancel when the
+ escape key is pressed.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide92.zip">Beta release 0.93</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 12 May 1999.
+ </li>
+ <li>
+ A bit more robust than 0.92 and supports SCI_MARKERNEXT message.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide92.zip">Beta release 0.92</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 11 May 1999.
+ </li>
+ <li>
+ GTK+ version now contains all features of Windows version with some very small differences.
+ Executing programs works much better now.
+ </li>
+ <li>
+ New palette code to allow more colours to be displayed in 256 colour screen modes. A line
+ number column can be displayed to the left of the selection margin.
+ </li>
+ <li>
+ The code that maps from line numbers to text positions and back has been completely
+ rewritten to be faster, and to allow markers to move with the text.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide91.zip">Beta release 0.91</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 30 April 1999, containing fixes to text measuring to make Scintilla work better
+ with bitmap fonts. Also some small fixes to make compiling work with Visual C++.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide90.zip">Beta release 0.90</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 29 April 1999, containing working GTK+/Linux version.
+ </li>
+ <li>
+ The Java, C++ and Python lexers recognise operators as distinct from default allowing them
+ to be highlighted.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide82.zip">Beta release 0.82</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 1 April 1999, to fix a problem with handling the Enter key in PythonWin. Also
+ fixes some problems with cmd key mapping.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://www.scintilla.org/Tide81.zip">Beta release 0.81</a>
+ </h3>
+ <ul>
+ <li>
+ Released on 30th March 1999, containing bug fixes and a few more features.
+ </li>
+ <li>
+ Static linking supported and Tidy.EXE, a statically linked version of Tide.EXE. Changes to
+ compiler flags in the makefiles to optimise for size.
+ </li>
+ <li>
+ Scintilla supports a 'savepoint' in the undo stack which can be set by the container when
+ the document is saved. Notifications are sent to the container when the savepoint is
+ entered or left, allowing the container to to display a dirty indicator and change its
+ menus.
+ </li>
+ <li>
+ When Scintilla is set to read-only mode, a notification is sent to the container should the
+ user try to edit the document. This can be used to check the document out of a version
+ control system.
+ </li>
+ <li>
+ There is an API for setting the appearance of indicators.
+ </li>
+ <li>
+ The keyboard mapping can be redefined or removed so it can be implemented completely by the
+ container. All of the keyboard commands are now commands which can be sent by the
+ container.
+ </li>
+ <li>
+ A home command like Visual C++ with one hit going to the start of the text on the line and
+ the next going to the left margin is available. I do not personally like this but my
+ fingers have become trained to it by much repetition.
+ </li>
+ <li>
+ SCI_MARKERDELETEALL has an argument in wParam which is the number of the type marker to
+ delete with -1 performing the old action of removing all marker types.
+ </li>
+ <li>
+ Tide now understands both the file name and line numbers in error messages in most cases.
+ </li>
+ <li>
+ Tide remembers the current lines of files in the recently used list.
+ </li>
+ <li>
+ Tide has a Find in Files command.
+ </li>
+ </ul>
+ <h3>
+ Beta release 0.80
+ </h3>
+ <ul>
+ <li>
+ This was the first public release on 14th March 1999, containing a mostly working Win32
+ Scintilla DLL and Tide EXE.
+ </li>
+ </ul>
+ <h3>
+ Beta releases of SciTE were called Tide
+ </h3>
+ </body>
+</html>
+
diff --git a/scintilla/doc/ScintillaRelated.html b/scintilla/doc/ScintillaRelated.html
new file mode 100644
index 0000000..10d114d
--- /dev/null
+++ b/scintilla/doc/ScintillaRelated.html
@@ -0,0 +1,495 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla and SciTE Related Sites
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ and SciTE</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Related Sites
+ </h2>
+ <h3>
+ Ports and Bindings of Scintilla
+ </h3>
+ <p>
+ <a href="http://mewsoft.com/cgi-bin/forum/forum.cgi?action=ViewTopic&Topic=1494&Forum=1&Page=1&Period=0a&Lang=English">Editawy</a>
+ is an ActiveX Control wrapper that support all Scintilla functions and additional high level functions.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/jintilla/">Jintilla</a>
+ is a JNI wrapper that allows Scintilla to be used in Java with
+ both SWT and AWT.
+ </p>
+ <p>
+ <a href="http://delphisci.sourceforge.net/">Delphi Scintilla Interface Components</a>
+ is a FREE collection of components that makes it easy to use the
+ Scintilla source code editing control from within Delphi and C++ Builder.
+ </p>
+ <p>
+ <a href="http://wxcode.sourceforge.net/showcomp.php?name=wxStEdit">wxStEdit</a>
+ is a library and sample program that provides extra features over wxStyledTextControl.
+ </p>
+ <p>
+ <a href="http://www.naughter.com/scintilla.html">CScintillaCtrl, CScintillaView &amp; CScintillaDoc</a>
+ are freeware MFC classes to encapsulate Scintilla.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/scide/">ScintillaNet
+ </a> is an encapsulation of Scintilla for use within the .NET framework.
+ </p>
+ <p>
+ <a href="http://www.riverbankcomputing.co.uk/software/qscintilla/intro">QScintilla
+ </a> is a port of Scintilla to the Qt platform. It has a similar license to Qt: GPL for use in
+ free software and commercial for use in close-source applications.
+ </p>
+ <p>
+ <a href="http://www.adapower.com/gwindows/">
+ GWindows</a> is a Win32 RAD GUI Framework for Ada 95 that
+ includes a binding of Scintilla.
+ </p>
+ <p>
+ <a href="http://scintilla.cvs.sourceforge.net/viewvc/scintilla/ScintillaVB/">ScintillaVB</a>
+ is an ActiveX control written in VB that encapsulates Scintilla.
+ </p>
+ <p>
+ <a href="http://savannah.nongnu.org/projects/fxscintilla/">FXScintilla
+ </a> is a port of Scintilla to the FOX platform. FXRuby includes Ruby
+ bindings for FXScintilla.
+ </p>
+ <p>
+ <a href="http://www.pnotepad.org/scintilla/">Delphi wrapper</a> for
+ Scintilla which is also usable from Borland C++ Builder.
+ </p>
+ <p>
+ The wxStyledTextCtrl editor component in the
+ <a href="http://www.wxwidgets.org/">wxWidgets</a> cross platform toolkit is based on Scintilla.<br />
+ A Python binding for wxStyledTextCtrl is part of <a href="http://wxpython.org/">wxPython</a>.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/moleskine/">gtkscintilla</a>
+ is an alternative GTK class implementation for scintilla.
+ This implementation acts more like a Gtk+ object, with many methods rather
+ than just scintilla_send_message() and is available as a shared library.
+ This implementation works with GTK 1.x.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/moleskine/">gtkscintilla2</a>
+ is an alternative GTK class implementation for scintilla
+ similar to the above, but for GTK 2.x.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/moleskine/">pygtkscintilla</a>
+ is a Python binding for gtk1.x scintilla that uses
+ gtkscintilla instead of the default GTK class.
+ </p>
+ <p>
+ <a href="http://sra.itc.it/people/cavada/PyScintilla2.html">pyscintilla2</a>
+ is a Python binding for GTK 2.x scintilla that uses
+ gtkscintilla2.
+ </p>
+ <p>
+ <a href="http://scintilla.cvs.sourceforge.net/viewvc/scintilla/scintillactrl/">ScintillaCtrl</a>
+ is an unmaintained ActiveX control wrapper for Scintilla.
+ </p>
+ <h3>
+ Projects using Scintilla
+ </h3>
+ <p>
+ <a href="http://www.sparxsystems.com/products/ea/index.html">Enterprise Architect</a>
+ is a UML 2.1 analysis and design tool.
+ </p>
+ <p>
+ <a href="https://launchpad.net/codeassistor">The CodeAssistor Editor</a>
+ is a small and simple MacOSX source code editor.
+ </p>
+ <p>
+ <a href="http://www.topwizprogramming.com/freecode_pbeditor.html">PBEditor</a>
+ is a text editor for PowerBuilder.
+ </p>
+ <p>
+ <a href="http://www.cryptool.org/">CrypTool</a>
+ is an application for applying and analyzing cryptographic algorithms.
+ </p>
+ <p>
+ <a href="http://code.google.com/p/fxite/">FXiTe</a>
+ is an advanced cross-platform text editor built with the Fox GUI toolkit
+ and the FXScintilla text widget.
+ </p>
+ <p>
+ <a href="http://www.jabaco.org/">Jabaco</a>
+ is a simple programming language with a Visual Basic like syntax.
+ </p>
+ <p>
+ <a href="http://www.daansystems.com/lispide">LispIDE</a>
+ is a basic Lisp editor for Windows 2000, XP and Vista.
+ </p>
+ <p>
+ <a href="http://www.flexedit.org/">FlexEdit</a>
+ is Free Text/Hex Editor for Windows.
+ </p>
+ <p>
+ <a href="http://www.assembla.com/wiki/show/FileWorkbench">File Workbench:</a>
+ a file manager / text editor environment with Squirrel scripting.
+ </p>
+ <p>
+ <a href="http://kephra.sf.net">Kephra</a>
+ is a free, easy and comfortable cross-platform editor written in Perl.
+ </p>
+ <p>
+ <a href="http://top.gresham-computing.com">TOP</a>
+ is an interface to HP's NonStop servers which run a proprietary OS.
+ </p>
+ <p>
+ <a href="http://universalindent.sourceforge.net/">UniversalIndentGUI</a>
+ is a cross platform GUI for several code formatters, beautifiers and indenters
+ like GreatCode, AStyle (Artistic Styler), GNU Indent, BCPP and so on.
+ </p>
+ <p>
+ <a href="http://scitools.com/products/trackback/product.php">TrackBack</a>
+ watches and backs up every change made in your source code.
+ </p>
+ <p>
+ <a href="http://elementaryreports.com/">Elementary Reports</a>
+ is designed to reduce the time to compose detailed and professional primary school reports.
+ </p>
+ <p>
+ <a href="http://stepaheadsoftware.com/products/vcw/vcw.htm">Visual Classworks</a>
+ Visual class modeling and coding in C++ via 'live'
+ UML style class diagrams.
+ </p>
+ <p>
+ <a href="http://stepaheadsoftware.com/products/javelin/javelin.htm">Javelin</a>
+ Visual Class modeling and coding in Java via 'live' UML style
+ class diagrams.
+ </p>
+ <p>
+ The <a href="http://www.adobe.com/devnet/bridge/">ExtendScript Toolkit</a>
+ is a development and debugging tool for JavaScript
+ scripts included with Adobe CS3 Suites.
+ </p>
+ <p>
+ <a href="http://tortoisesvn.net/">TortoiseSVN</a>
+ is a Windows GUI client for the Subversion source control software.
+ </p>
+ <p>
+ <a href="http://www.geany.org/">Geany</a>
+ is a small and fast GTK2 based IDE, which has only a few dependencies from other packages.
+ </p>
+ <p>
+ <a href="http://www.elliecomputing.com/products/merge_overview.asp">ECMerge</a>
+ is a commercial graphical and batch diff / merge tool for Windows, Linux and Solaris
+ (aiming to target all major platforms).
+ </p>
+ <p>
+ <a href="http://pype.sourceforge.net/">PyPE</a>
+ is an editor written in Python with the wxPython GUI toolkit.
+ </p>
+ <p>
+ <a href="http://home.mweb.co.za/sd/sdonovan/sciboo.html">Sciboo</a>
+ is an editor based on ScintillaNET.
+ </p>
+ <p>
+ <a href="https://sourceforge.net/projects/tsct/">The Scite Config Tool</a>
+ is a graphical user interface for changing SciTE properties files.
+ </p>
+ <p>
+ <a href="http://www.totalcmd.net/plugring/SciLister.html">Scintilla Lister</a>
+ is a plugin for Total Commander allowing viewing all documents with syntax highlighting
+ inside Total Commander.
+ </p>
+ <p>
+ <a href="http://chscite.sourceforge.net">ChSciTE</a>
+ is a free IDE for C/C++ interpreter Ch. It runs cross platform.
+ Ch is for cross-platform scripting, shell
+ programming, 2D/3D plotting, numerical computing, and embedded
+ scripting.
+ </p>
+ <p>
+ <a href="http://codeblocks.org/">
+ Code::Blocks</a> is an open source, cross platform free C++ IDE.
+ </p>
+ <p>
+ <a href="http://notepad-plus.sourceforge.net/uk/site.htm">
+ Notepad++</a> is a free source code editor under Windows.
+ </p>
+ <p>
+ <a href="http://gubed.mccabe.nu/">
+ Gubed</a> is a cross platform program to debug PHP scripts.
+ </p>
+ <p>
+ <a href="http://www.lesser-software.com/lswdnl.htm">
+ LSW DotNet-Lab</a> is a development environment for the .NET platform.
+ </p>
+ <p>
+ <a href="http://glintercept.nutty.org/">
+ GLIntercept</a> is an OpenGL function call interceptor that uses SciTE as a
+ run-time shader editor.
+ </p>
+ <p>
+ <a href="http://wxguide.sourceforge.net/indexedit.html">
+ wyoEditor</a> is "A nice editor with a well designed and consistent look and feel".
+ </p>
+ <p>
+ <a href="http://www.flos-freeware.ch/notepad2.html">
+ Notepad2</a> is "Yet another Notepad replacement".
+ </p>
+ <p>
+ <a href="http://pycrash.sourceforge.net/index.php?type=3">
+ PyCrash Viewer</a> can examine crash dumps of Python programs.
+ </p>
+ <p>
+ <a href="http://www.cabletest.com/mpt-wa-software-discovery.shtml">
+ MPT series Wire Analyzers</a> use Scintilla and SciTE.
+ </p>
+ <p>
+ <a href="http://www.mygenerationsoftware.com">MyGeneration</a>
+ is a .NET based code generator.
+ </p>
+ <p>
+ <a href="http://cssed.sourceforge.net">CSSED</a>
+ is a tiny GTK2 CSS editor.
+ </p>
+ <p>
+ <a href="http://wxghostscript.sourceforge.net/">
+ IdePS</a>
+ is a free Integrated Development Environment for PostScript
+ </p>
+ <p>
+ <a href="http://cute.sourceforge.net/">
+ CUTE</a>
+ is a user-friendly source code editor easily extended using Python.
+ </p>
+ <p>
+ <a href="http://www.spaceblue.com/venis/">
+ Venis IX</a>,
+ the Visual Environment for NSIS (Nullsoft Scriptable Install System).
+ </p>
+ <p>
+ <a href="http://www.die-offenbachs.de/detlev/eric.html">Eric3</a>
+ is a Python IDE written using PyQt and QScintilla.
+ </p>
+ <p>
+ <a href="http://www.bomberstudios.com/sciteflash/">SciTE|Flash</a>
+ is a free Scintilla-based ActionScript editor for Windows.
+ </p>
+ <p>
+ <a href="http://www.computersciencelab.com/CppIde.htm">CPPIDE</a>
+ is part of some commercial high-school oriented programming course software.
+ </p>
+ <p>
+ <a href="http://www.blazingtools.com/is.html">Instant Source</a>
+ is a commercial tool for looking at the HTML on web sites.
+ </p>
+ <p>
+ <a href="http://www.codejoin.com/radon/">RAD.On++</a>
+ is a free C++ Rapid Application Developer for Win32.
+ </p>
+ <p>
+ <a href="http://wxbasic.sourceforge.net/">wxBasic</a> is an open source
+ Basic interpreter that uses the wxWidgets toolkit. A small IDE is under construction.
+ </p>
+ <p>
+ <a href="http://freeride.rubyforge.org/wiki/wiki.pl">FreeRIDE</a> will be a
+ cross-platform IDE for the Ruby programming language.
+ </p>
+ <p>
+ <a href="http://visual-mingw.sourceforge.net/">Visual MinGW</a> is an
+ IDE for the MinGW compiler system.This runs on Windows with gcc.
+ </p>
+ <p>
+ The <a href="http://archaeopteryx.com/wingide">Wing IDE</a> is a
+ complete integrated development environment for the Python programming
+ language.
+ Available on Intel based Linux and Windows and on MacOS X through XDarwin.
+ </p>
+ <p>
+ <a href="http://www.gorlice.net.pl/~rybak/luaide/">LuaIDE</a>
+ is an IDE for Lua on Windows.
+ </p>
+ <p>
+ <a href="http://www.aegisknight.org/sphere/">Sphere</a>
+ is 2D RPG engine with a development environment.
+ </p>
+ <p>
+ <a href="http://gaiacrtn.free.fr/practical-ruby/index.html">Practical Ruby</a>
+ is an IDE for Ruby on Windows.
+ </p>
+ <p>
+ <a href="http://www.gnuenterprise.org/">GNUe</a>
+ is a suite of tools and applications for solving the needs of the enterprise.
+ </p>
+ <p>
+ <a href="http://silvercity.sourceforge.net/">SilverCity</a>
+ is a lexing package that can provide lexical analysis for over 20 programming
+ and markup languages.
+ </p>
+ <p>
+ <a href="http://hapdebugger.sourceforge.net/">HAP Python Remote Debugger</a>
+ is a Python debugger that can run on one Windows machine debugging a Python program running
+ on either the same or another machine.
+ </p>
+ <p>
+ <a href="http://www.rexx.com/~dkuhlman/">pyeditor and wxEditor</a>
+ are scriptable editors implemented in Python. pyeditor is based on GTK+ and
+ the pyscintilla wrapper. wxEditor is based on wxWidgets, wxPython and
+ wxStyledTextControl.
+ </p>
+ <p>
+ <a href="http://sourceforge.net/projects/pycrust/">PyCrust</a> is an interactive
+ Python shell based on wxPython.
+ </p>
+ <p>
+ <a href="http://www.thekompany.com/products/blackadder/">Black Adder</a> is a
+ Qt based development environment for Python and Ruby.
+ </p>
+ <p>
+ <a href="http://www.activestate.com/Products/Komodo/">Komodo</a>
+ is a cross-platform multi-language development environment built
+ as an application of Mozilla.
+ </p>
+ <p>
+ <a href="http://llt.chez-alice.fr/">Filerx</a>
+ is a project manager for SciTE on Windows.
+ Open source and includes an implementation of SciTE's Director interface so
+ will be of interest to others wanting to control SciTE.
+ </p>
+ <p>
+ <a href="http://anjuta.sourceforge.net/">Anjuta</a>
+ is an open source C/C++ IDE for Linux/GNOME.
+ </p>
+ <p>
+ A <a href="http://www.burgaud.com">version of SciTE for Win32</a> enhanced
+ with a tab control to allow easy movement between buffers.
+ Go to the "Goodies" area on this site.
+ </p>
+ <p>
+ <a href="http://www.suneido.com">
+ Suneido</a> is an integrated application platform currently available for Win32 that includes an
+ object-oriented language, client-server database, and user interface and reporting frameworks.
+ </p>
+ <p>
+ <a href="http://www.allitis.com/agast/home.html">
+ Agast</a> is an authoring system for adventure games which includes
+ a customised version of SciTE.
+ </p>
+ <p>
+ <a href="http://boa-constructor.sourceforge.net/">Boa Constructor</a> is a RAD GUI
+ Building IDE for the wxWidgets cross platform platform. Written using wxPython with the
+ wxStyledTextCtrl used as its editor.
+ </p>
+ <p>
+ <a href="http://www.python.org/download/windows/">PythonWin</a>, a Win32 IDE for Python, uses
+ Scintilla for both its editing and interactive windows.
+ </p>
+ <h3>
+ Editing Components
+ </h3>
+ <p>
+ <a href="http://projects.gnome.org/gtksourceview/">GtkSourceView</a>
+ is a text widget that extends the standard GTK+ 2.x text widget and improves it
+ by implementing syntax highlighting and other features typical of a source editor.
+ </p>
+ <p>
+ <a href="http://aeditor.rubyforge.org/">AEditor</a>
+ is a free source code editing component implemented in Ruby.
+ </p>
+ <p>
+ <a href="http://www.actiprosoftware.com/Products/DotNet/SyntaxEditor/Default.aspx">SyntaxEditor</a>
+ is a commercial native .Net source code editing component.
+ </p>
+ <p>
+ <a href="http://jedit.sourceforge.net/">jEdit</a> is a good Open Source syntax colouring
+ editor written in and for Java.
+ </p>
+ <p>
+ <a href="http://www.gtk.org/">GTK+</a>, the GIMP Toolkit, contains a rich text editing
+ widget.<br />
+ <a href="http://gedit.sourceforge.net/">Gedit</a> is an editor for GTK+/GNOME.<br />
+ <!--
+ <a href="http://www.daimi.au.dk/~mailund/gtk.html">GtkEditor</a> is a source code editing
+ widget based on the GTK+ text widget.<br />
+ <a href="http://gide.gdev.net/">gIDE</a> is an IDE based on GTK+.<br />
+ <a href="http://www.bahnhof.se/~mikeh/linux_software.html">GtkExText</a> is a source code
+ oriented text widget for GTK+.
+ -->
+ </p>
+ <p>
+ <a href="http://www.codeguru.com/">CodeGuru</a> has source code for several Win32 MFC based
+ editors.
+ </p>
+ <a href="http://synedit.sourceforge.net/">SynEdit</a> is a Win32 edit control written
+ in Delphi.
+ <p>
+ <a href="http://www.tetradyne.com/srcvwax.htm">SourceView</a> is a commercial editing
+ component for Win32.
+ </p>
+ <p>
+ <a href="http://www.winmain.com/">CodeMax</a> is another commercial component for Win32.
+ </p>
+ <h3>
+ Documents
+ </h3>
+ <p>
+ <a href="http://www.finseth.com/craft/">The Craft of Text Editing</a>
+ describes how EMACS works, <i>Craig A. Finseth</i>
+ </p>
+ <p>
+ <a href="http://www.cs.cmu.edu/~wjh/papers/byte.html">Data Structures in a Bit-Mapped Text
+ Editor</a>, <i>Wilfred J. Hanson</i>, Byte January 1987
+ </p>
+ <p>
+ Text Editors: Algorithms and Architectures, <i>Ray Vald&eacute;s</i>, Dr. Dobbs Journal
+ April 1993
+ </p>
+ <p>
+ Macintosh User Interface Guidelines and TextEdit chapters of Inside Macintosh
+ </p>
+ <h3>
+ Development Tools
+ </h3>
+ <p>
+ Scintilla and SciTE were developed using the
+ <a href="http://www.mingw.org/">Mingw version of GCC</a>.
+ </p>
+ <p>
+ <a href="http://astyle.sourceforge.net/">AStyle</a> is a source code formatter for C++ and
+ Java code. SciTE has an Indent command defined for .cxx files that uses AStyle.
+ </p>
+ <p>
+ <a href="http://winmerge.org/">WinMerge</a> is an interactive diff / merge
+ for Windows. I prefer code submissions in the form of source files rather than diffs and then run
+ WinMerge over the files to work out how to merge.
+ </p>
+ <p>
+ <a href="http://www.python.org">Python</a> is my favourite programming language. Scintilla
+ was started after I tried to improve the editor built into <a
+ href="http://www.python.org/download/windows/">PythonWin</a>, but was frustrated by the limitations of
+ the Windows Richedit control which PythonWin used.
+ </p>
+ <p>
+ <a href="http://www.cse.yorku.ca/~oz/">regex</a> is a public domain
+ implementation of regular expression pattern matching used in Scintilla.
+ </p>
+ <p>
+ Inspirational coding soundscapes by <a href="http://www.davidbridie.com.au">David Bridie</a>.
+ </p>
+ </body>
+</html>
+
diff --git a/scintilla/doc/ScintillaToDo.html b/scintilla/doc/ScintillaToDo.html
new file mode 100644
index 0000000..13c5ee9
--- /dev/null
+++ b/scintilla/doc/ScintillaToDo.html
@@ -0,0 +1,157 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla and SciTE To Do
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ and SciTE</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Bugs and To Do List
+ </h2>
+ <h3>
+ Feedback
+ </h3>
+ <p>
+ Issues can be reported on the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=102439">Bug Tracker</a>
+ and features requested on the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=352439">Feature Request Tracker</a>.
+ </p>
+ <h3>
+ Scintilla Bugs
+ </h3>
+ <p>
+ At the end of italics style runs characters can be chopped off. An example
+ is using Verdana 12 point italics for strings makes an ending double quote
+ half visible and an ending single quote invisible. This is hard to solve
+ completely, may be better to avoid these situations by, for example,
+ choosing a font like Times New Roman for strings. There is a specific kluge
+ for the end of line which adds some room for italics but this does not
+ work elsewhere.
+ </p>
+ <p>
+ Dragging over bold text in some fonts will ripple because of the difference in
+ size between drawing all of a string at once and drawing it in parts.
+ </p>
+ <p>
+ Automatic scrolling when text dragged near edge of window.
+ </p>
+ <h3>
+ GTK+ Version Bugs
+ </h3>
+ <h3>
+ Scintilla To Do
+ </h3>
+ <p>
+ Folding for languages that don't have it yet and good folding for languages
+ that inherited poor folding from another languages folding code.
+ </p>
+ <p>
+ Simple pattern based styling.
+ </p>
+ <p>
+ Different height lines based upon tallest text on the line rather than on the tallest style
+ possible.
+ </p>
+ <p>
+ Composition of lexing for mixed languages (such as ASP+ over COBOL) by
+ combining lexers.
+ </p>
+ <p>
+ Printing support on GTK+. Maybe Postscript output or use Gnome?
+ </p>
+ <p>
+ Stream folding which could be used to fold up the contents of HTML elements.
+ </p>
+ <p>
+ Persisting view state such as current folding into a stream or blob so it is easy
+ to restore.
+ </p>
+ <p>
+ Printing of highlight lines and folding margin.
+ </p>
+ <p>
+ Flow diagrams inside editor similar to
+ <a href="http://www.eng.auburn.edu/grasp/grasp_main.shtml">
+ GRASP</a>.
+ </p>
+ <p>
+ A VCL component wrapper around Scintilla so it can be used with Delphi or
+ Borland C++ Builder.
+ There is <a href="http://www.pnotepad.org/scintilla/">some work</a>
+ on this available.
+ </p>
+ <p>
+ More lexers for other languages.
+ </p>
+ <h3>
+ SciTE To Do
+ </h3>
+ <p>
+ Good regular expression support through a plugin.
+ </p>
+ <p>
+ Allow file name based selection on all properties rather than just a chosen few.
+ </p>
+ <p>
+ Opening from and saving to FTP servers.
+ </p>
+ <p>
+ Setting to fold away comments upon opening.
+ </p>
+ <p>
+ User defined fold ranges.
+ </p>
+ <p>
+ Silent mode that does not display any message boxes.
+ </p>
+ <h3>
+ Features I am unlikely to do
+ </h3>
+ <p>
+ These are features I don't like or don't think are important enough to work on.
+ Implementations are welcome from others though.
+ </p>
+ <p>
+ Mouse wheel panning (press the mouse wheel and then move the mouse) on
+ Windows.
+ </p>
+ <p>
+ Adding options to the save dialog to save in a particular encoding or with a
+ chosen line ending.
+ </p>
+ <h3>
+ Directions
+ </h3>
+ <p>
+ The main point of this development is Scintilla, and this is where most effort will
+ go. SciTE will get new features, but only when they make my life easier - I am
+ not intending to make it grow up to be a huge full-function IDE like Visual
+ Cafe. The lines I've currently decided not to step over in SciTE are any sort of
+ project facility and any configuration dialogs. SciTE for Windows now has a
+ Director interface for communicating with a separate project manager
+ application.
+ </p>
+ <p>
+ If you are interested in contributing code, do not feel any need to make it cross
+ platform.
+ Just code it for your platform and I'll either reimplement for the other platform or
+ ensure that there is no effect on the other platform.
+ </p>
+ </body>
+</html>
diff --git a/scintilla/doc/ScintillaUsage.html b/scintilla/doc/ScintillaUsage.html
new file mode 100644
index 0000000..c19cbc5
--- /dev/null
+++ b/scintilla/doc/ScintillaUsage.html
@@ -0,0 +1,375 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>
+ Scintilla Usage Notes
+ </title>
+<style type="text/css">
+SPAN {
+ font-family: Verdana, Arial, Helvetica;
+ font-size: 9pt;
+}
+.S0 {
+ color: #808080;
+ font-family: Verdana, Arial, Helvetica;
+}
+.S1 {
+ font-family: Comic Sans MS, Times New Roman, Times;
+ color: #007F00;
+ font-size: 8pt;
+}
+.S2 {
+ font-family: Comic Sans MS, Times New Roman, Times;
+ color: #007F00;
+ font-size: 8pt;
+}
+.S3 {
+ font-family: Verdana, Arial, Helvetica;
+ color: #7F7F7F;
+}
+.S4 {
+ font-family: Verdana, Arial, Helvetica;
+ color: #007F7F;
+}
+.S5 {
+ color: #00007F;
+ font-weight: bold;
+ font-family: Verdana, Arial, Helvetica;
+}
+.S6 {
+ color: #7F007F;
+ font-family: Courier New, Courier;
+}
+.S7 {
+ color: #7F007F;
+ font-family: Courier New, Courier;
+}
+.S8 {
+ color: #007F7F;
+}
+.S9 {
+ color: #7F7F00;
+}
+.S10 {
+ font-weight: bold;
+}
+</style>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
+ </td>
+ <td>
+ <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
+ Usage Notes</font></a>
+ </td>
+ </tr>
+ </table>
+ <h2>
+ Implementing Auto-Indent
+ </h2>
+ <p>
+ The key idea is to use the SCN_CHARADDED notification to add indentation after a newline.
+ </p>
+ <p>
+ The lParam on the notification is a pointer to a SCNotification structure whose ch member
+ specifies the character added. If a newline was added, the previous line can be retrieved and
+ the same indentation can be added to the new line.
+ </p>
+ <p>
+ Here is the relevant portion of code from SciTE: (SciTE.cxx SciTEWindow::CharAdded)
+ </p>
+ <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
+ class='S11'>ch</span><span class='S0'>&nbsp;</span> <span class='S10'>==</span><span
+ class='S0'>&nbsp;</span> <span class='S7'>'\r'</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>||</span><span class='S0'>&nbsp;</span> <span class='S11'>ch</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>==</span><span class='S0'>&nbsp;</span> <span
+ class='S7'>'\n'</span><span class='S10'>)</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>char</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
+ class='S10'>];</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>GetCurrentLineNumber</span><span
+ class='S10'>();</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>lineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
+ =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
+ class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span class='S10'>);</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S2'>
+ //Platform::DebugPrintf("[CR]&nbsp;%d&nbsp;len&nbsp;=&nbsp;%d\n",&nbsp;curLine,&nbsp;lineLength);</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>(</span><span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>&gt;</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>lineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
+ &lt;=</span><span class='S0'>&nbsp;</span> <span class='S4'>2</span><span
+ class='S10'>)</span><span class='S0'>&nbsp;</span> <span class='S10'>{</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>prevLineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
+ =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
+ class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
+ class='S10'>);</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>(</span><span class='S11'>prevLineLength</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>&lt;</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
+ class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>))</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>WORD</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>buflen</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
+ class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>);</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>memcpy</span><span
+ class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>&amp;</span><span class='S11'>buflen</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
+ class='S10'>(</span><span class='S11'>buflen</span><span class='S10'>));</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
+ SendEditor</span><span class='S10'>(</span><span class='S11'>EM_GETLINE</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>-</span><span class='S0'>&nbsp;</span> <span
+ class='S4'>1</span><span class='S10'>,</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S5'>reinterpret_cast</span><span class='S10'>&lt;</span><span
+ class='S11'>LPARAM</span><span class='S10'>&gt;(</span><span class='S5'>static_cast</span><span
+ class='S10'>&lt;</span><span class='S5'>char</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>*&gt;(</span><span class='S11'>linebuf</span><span class='S10'>)));</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>linebuf</span><span
+ class='S10'>[</span><span class='S11'>prevLineLength</span><span class='S10'>]</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>=</span><span class='S0'>&nbsp;</span> <span
+ class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>for</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>(</span><span class='S5'>int</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>pos</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S10'>;</span><span class='S0'>&nbsp;</span> <span class='S11'>linebuf</span><span
+ class='S10'>[</span><span class='S11'>pos</span><span class='S10'>];</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>pos</span><span class='S10'>++)</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span
+ class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
+ class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
+ class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>!=</span><span
+ class='S0'>&nbsp;</span> <span class='S7'>'&nbsp;'</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span> <span class='S11'>
+ linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
+ class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>!=</span><span
+ class='S0'>&nbsp;</span> <span class='S7'>'\t'</span><span class='S10'>)</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
+ class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S7'>'\0'</span><span class='S10'>;</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S10'>}</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
+ SendEditor</span><span class='S10'>(</span><span class='S11'>EM_REPLACESEL</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S5'>
+ reinterpret_cast</span><span class='S10'>&lt;</span><span class='S11'>LPARAM</span><span
+ class='S10'>&gt;(</span><span class='S5'>static_cast</span><span class='S10'>&lt;</span><span
+ class='S5'>char</span><span class='S0'>&nbsp;</span> <span class='S10'>*&gt;(</span><span
+ class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S10'>}</span><span class='S0'><br />
+ </span> <span class='S10'>}</span><br />
+
+ <p style="margin-bottom: 0in">
+ Of course, fancier handling could be implemented. For example, if the previous line was the
+ start of a control construct, the next line could be automatically indented one tab further.
+ (Assuming that is your indenting style.)
+ </p>
+ <h2>
+ Implementing Syntax Styling
+ </h2>
+ <p>
+ Syntax styling is handled by the SCN_STYLENEEDED notification. Scintilla keeps track of the
+ end of the styled text - this is retrieved with SCI_GETENDSTYLED. In response to the
+ SCN_STYLENEEDED notification, you should apply styles to the text from ENDSTYLED to the
+ position specified by the notification.
+ </p>
+ <p>
+ Here is the relevant portion of code from SciTE: (SciTE.cxx)
+ </p>
+ <span class='S5'>void</span><span class='S0'>&nbsp;</span> <span class='S11'>
+ SciTEWindow</span><span class='S10'>::</span><span class='S11'>Notify</span><span
+ class='S10'>(</span><span class='S11'>SCNotification</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>*</span><span class='S11'>notification</span><span class='S10'>)</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>switch</span><span class='S0'>&nbsp;</span>
+ <span class='S10'>(</span><span class='S11'>notification</span><span
+ class='S10'>-&gt;</span><span class='S11'>nmhdr.code</span><span class='S10'>)</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>case</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>SCN_STYLENEEDED</span><span class='S10'>:</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span
+ class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
+ class='S11'>notification</span><span class='S10'>-&gt;</span><span
+ class='S11'>nmhdr.idFrom</span><span class='S0'>&nbsp;</span> <span class='S10'>==</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>IDM_SRCWIN</span><span class='S10'>)</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S5'>int</span><span class='S0'>&nbsp;</span> <span class='S11'>
+ endStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
+ class='S11'>SCI_GETENDSTYLED</span><span class='S10'>);</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S5'>int</span><span class='S0'>&nbsp;</span> <span class='S11'>
+ lineEndStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
+ class='S11'>EM_LINEFROMCHAR</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>endStyled</span><span class='S10'>);</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S11'>endStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>
+ =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
+ class='S10'>(</span><span class='S11'>EM_LINEINDEX</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>lineEndStyled</span><span class='S10'>);</span><span
+ class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span class='S11'>Colourise</span><span class='S10'>(</span><span
+ class='S11'>endStyled</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>notification</span><span class='S10'>-&gt;</span><span
+ class='S11'>position</span><span class='S10'>);</span><br />
+
+ <p>
+ Colourize(start, end) retrieves the specified range of text and then calls ColourizeDoc in
+ keywords.cxx. It starts the process by calling:
+ </p>
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessage</span><span class='S10'>(</span><span
+ class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>SCI_STARTSTYLING</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>startPos</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S4'>31</span><span class='S10'>);</span><br />
+
+ <p>
+ and then for each token of the text, calling:
+ </p>
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessage</span><span class='S10'>(</span><span
+ class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>SCI_SETSTYLING</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>length</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>style</span><span class='S10'>);</span><br />
+
+ <p>
+ where style is a number from 0 to 31 whose appearance has been defined using the
+ SCI_STYLESET... messages.
+ </p>
+ <h2>
+ Implementing Calltips
+ </h2>
+ <p>
+ Again, the SCN_CHARADDED notification is used to catch when an opening parenthesis is added.
+ The preceding word can then be retrieved from the current line:
+ </p>
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>char</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
+ class='S10'>];</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>current</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
+ class='S11'>SCI_GETCURLINE</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S5'>sizeof</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
+ class='S10'>),</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>
+ reinterpret_cast</span><span class='S10'>&lt;</span><span class='S11'>LPARAM</span><span
+ class='S10'>&gt;(</span><span class='S5'>static_cast</span><span class='S10'>&lt;</span><span
+ class='S5'>char</span><span class='S0'>&nbsp;</span> <span class='S10'>*&gt;(</span><span
+ class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>pos</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
+ class='S11'>SCI_GETCURRENTPOS</span><span class='S10'>);</span><span class='S0'><br />
+ <br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>startword</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>current</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
+ class='S10'>;</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>while</span><span class='S0'>&nbsp;</span>
+ <span class='S10'>(</span><span class='S11'>startword</span><span class='S0'>&nbsp;</span>
+ <span class='S10'>&gt;</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span>
+ <span class='S11'>isalpha</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
+ class='S10'>[</span><span class='S11'>startword</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
+ class='S10'>]))</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
+ startword</span><span class='S10'>--;</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>linebuf</span><span class='S10'>[</span><span
+ class='S11'>current</span><span class='S0'>&nbsp;</span> <span class='S10'>-</span><span
+ class='S0'>&nbsp;</span> <span class='S4'>1</span><span class='S10'>]</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>=</span><span class='S0'>&nbsp;</span> <span
+ class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>char</span><span class='S10'>*</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>word</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S11'>linebuf</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>+</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>startword</span><span class='S10'>;</span><br />
+
+ <p>
+ Then if a calltip is available it can be displayed. The calltip appears immediately below
+ the position specified. The calltip can be multiple lines separated by newlines (\n).
+ </p>
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>pos</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S11'>SendMessage</span><span
+ class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SCI_GETCURRENTPOS</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
+ class='S10'>);</span><span class='S0'><br />
+ </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessageText</span><span
+ class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>SCI_CALLTIPSHOW</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>pos</span><span
+ class='S0'>&nbsp;</span> <span class='S10'>-</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>wordLen</span><span class='S0'>&nbsp;</span> <span class='S10'>-</span><span
+ class='S0'>&nbsp;</span> <span class='S4'>1</span><span class='S10'>,</span><span
+ class='S0'>&nbsp;</span> <span class='S11'>calltip</span><span class='S10'>);</span><br />
+
+ <p>
+ The calltip can be removed when a closing parenthesis is entered:
+ </p>
+ &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
+ class='S10'>(</span><span class='S11'>SendMessage</span><span class='S10'>(</span><span
+ class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S11'>SCI_CALLTIPACTIVE</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
+ <span class='S4'>0</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S4'>0</span><span class='S10'>))</span><span class='S0'><br />
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
+ SendMessage</span><span class='S10'>(</span><span class='S11'>hwnd</span><span
+ class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>
+ SCI_CALLTIPCANCEL</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
+ class='S4'>0</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>
+ 0</span><span class='S10'>);</span><br />
+
+ <p>
+ Obviously, it is up the application to look after supplying the appropriate calltip text.
+ </p>
+ <p>
+ SciTE goes one step further, counting the commas between arguments and highlighting the
+ corresponding part of the calltip. This code is in ContinueCallTip.
+ </p>
+ <p>
+ <i>Page contributed by Andrew McKinlay.</i>
+ </p>
+ </body>
+</html>
+
diff --git a/scintilla/doc/Steps.html b/scintilla/doc/Steps.html
new file mode 100644
index 0000000..765268d
--- /dev/null
+++ b/scintilla/doc/Steps.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"><title>How to use the Scintilla Edit Control in windows?</title></head><body bgcolor="#ffffff">
+ <p><h2>How to use the Scintilla Edit Control in windows?</h2>
+ <p>
+ This should be a little step by step explanation how to use Scintilla in the windows environment.
+ </p>
+ </p>
+ <p><h2>How to create Scintilla Edit Control?</h2>
+ <p>
+ First of all, load the Scintilla DLL with something like:
+ </p>
+ <pre>
+
+ hmod = LoadLibrary(&quot;SciLexer.DLL&quot;);
+ if (hmod==NULL)
+ {
+ MessageBox(hwndParent,
+ &quot;The Scintilla DLL could not be loaded.&quot;,
+ &quot;Error loading Scintilla&quot;,
+ MB_OK | MB_ICONERROR);
+ }
+ </pre>
+ <p>
+ If the DLL was loaded successfully, then the DLL has registered (yes, by itself) a new
+ window class. The new class called &quot;Scintilla&quot; is the new scintilla edit control.
+ </p>
+ <p>
+ Now you can use this new control just like any other windows control.
+ </p>
+ <pre>
+
+ hwndScintilla = CreateWindowEx(0,
+ &quot;Scintilla&quot;,&quot;&quot;, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPCHILDREN,
+ 10,10,500,400,hwndParent,(HMENU)GuiID, hInstance,NULL);
+ </pre>
+ <p>
+ Note the new window class name: &quot;Scintilla&quot;. By reaching this point you actually included
+ a Scintilla Edit Control to your windows program.
+ </p>
+ </p>
+ <p><h2>How to control the Scintilla Edit Control?</h2>
+ <p>
+ You can control Scintilla by sending commands to the Edit Control.
+ There a 2 ways of doing this. A simple and fast way.
+ </p>
+ <p><h3>The simple way to control Scintilla</h3>
+ <p>
+ The simple way is just like with any other windows control. You can send messages to the
+ Scintilla Edit Control and receive notifications from the control. (Note that the notifications
+ are sent to the parent window of the Scintilla Edit Control.)
+ </p>
+ <p>
+ The Scintilla Edit Control knows a special message for each command.
+ To send commands to the Scintilla Edit Control you can use the SendMessage function.
+ </p>
+ <pre>
+
+ SendMessage(hwndScintilla,sci_command,wparam,lparam);
+ </pre>
+ <p>
+ like:
+ </p>
+ <pre>
+
+ SendMessage(hwndScintilla,SCI_CREATEDOCUMENT, 0, 0);
+ </pre>
+ <p>
+ Some of the commands will return a value and unused parameters should be set to NULL.
+ </p>
+ </p>
+ <p><h3>The fast way to control Scintilla</h3>
+ <p>
+ The fast way of controlling the Scintilla Edit Control is to call message handling function by yourself.
+ You can retrieve a pointer to the message handling function of the Scintilla Edit Control and
+ call it directly to execute a command. This way is much more faster than the SendMessage() way.
+ </p>
+ <p>
+ 1st you have to use the SCI_GETDIRECTFUNCTION and SCI_GETDIRECTPOINTER commands to
+ retrieve the pointer to the function and a pointer which must be the first parameter when calling the retrieved
+ function pointer.
+ You have to do this with the SendMessage way :)
+ </p>
+ <p>
+ The whole thing has to look like this:
+ </p>
+ <pre>
+
+ int (*fn)(void*,int,int,int);
+ void * ptr;
+ int canundo;
+
+ fn = (int (__cdecl *)(void *,int,int,int))SendMessage(
+ hwndScintilla,SCI_GETDIRECTFUNCTION,0,0);
+ ptr = (void *)SendMessage(hwndScintilla,SCI_GETDIRECTPOINTER,0,0);
+
+ canundo = fn(ptr,SCI_CANUNDO,0,0);
+ </pre>
+ <p>
+ with &quot;fn&quot; as the function pointer to the message handling function of the Scintilla Control
+ and &quot;ptr&quot; as the pointer that must be used as 1st parameter.
+ The next parameters are the Scintilla Command with its two (optional) parameters.
+ </p>
+
+ </p>
+ <p><h3>How will I receive notifications?</h3>
+ <p>
+ Whenever an event occurs where Scintilla wants to inform you about something, the Scintilla Edit Control
+ will send notification to the parent window. This is done by a WM_NOTITY message.
+ When receiving that message, you have to look in the xxx struct for the actual message.
+ </p>
+ <p>
+ So in Scintillas parent window message handling function you have to include some code like this:
+ </p>
+ <pre>
+ NMHDR *lpnmhdr;
+
+ [...]
+
+ case WM_NOTIFY:
+ lpnmhdr = (LPNMHDR) lParam;
+
+ if(lpnmhdr-&gt;hwndFrom==hwndScintilla)
+ {
+ switch(lpnmhdr-&gt;code)
+ {
+ case SCN_CHARADDED:
+ /* Hey, Scintilla just told me that a new */
+ /* character was added to the Edit Control.*/
+ /* Now i do something cool with that char. */
+ break;
+ }
+ }
+ break;
+ </pre>
+ </p>
+ </p>
+
+ <p>
+ <i>Page contributed by Holger Schmidt.</i>
+ </p>
+</body></html>
+
diff --git a/scintilla/doc/annotations.png b/scintilla/doc/annotations.png
new file mode 100644
index 0000000..9d9b247
--- /dev/null
+++ b/scintilla/doc/annotations.png
Binary files differ
diff --git a/scintilla/doc/index.html b/scintilla/doc/index.html
new file mode 100644
index 0000000..106f607
--- /dev/null
+++ b/scintilla/doc/index.html
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+ <meta name="generator" content="SciTE" />
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
+ <meta name="Description"
+ content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
+ <meta name="Date.Modified" content="20100601" />
+ <style type="text/css">
+ #versionlist {
+ margin: 0;
+ padding: .5em;
+ list-style-type: none;
+ color: #FFCC99;
+ background: #000000;
+ }
+ #versionlist li {
+ margin-bottom: .5em;
+ }
+ #menu {
+ margin: 0;
+ padding: .5em 0;
+ list-style-type: none;
+ font-size: larger;
+ background: #CCCCCC;
+ }
+ #menu li {
+ margin: 0;
+ padding: 0 .5em;
+ display: inline;
+ }
+ </style>
+ <script type="text/javascript">
+ function IsRemote() {
+ var loc = '' + window.location;
+ return loc.indexOf('http:') != -1;
+ }
+ </script>
+ <title>
+ Scintilla and SciTE
+ </title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td width="256">
+ <img src="SciWord.jpg" height="78" width="256" alt="Scintilla" />
+ </td>
+ <td width="40%" align="left">
+ <font color="#FFCC99" size="4"> A free source code editing component for Win32 and
+ GTK+</font>
+ </td>
+ <td width="40%" align="right">
+ <font color="#FFCC99" size="3"> Release version 2.12<br />
+ Site last modified June 1 2010</font>
+ </td>
+ <td width="20%">
+ &nbsp;
+ </td>
+ </tr>
+ </table>
+ <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
+ <tr>
+ <td width="100%" alt="Sci Break" style="background: url(http://www.scintilla.org/SciBreak.jpg) no-repeat;height:150px;">
+ &nbsp;
+ </td>
+ </tr>
+ </table>
+ <ul id="versionlist">
+ <li>Version 2.12 improves drawing speed and fixes bugs.</li>
+ <li>Version 2.11 fixes compatibility with the C language.</li>
+ <li>Version 2.10 performs case insensitive search and upper and lower casing for non-ASCII characters.
+ Support for version 1.x of GTK+ removed.</li>
+ <li>Version 2.03 fixes some problems with rectangular selection.</li>
+ <li>Version 2.02 fixes some problems with rectangular selection.</li>
+ <li>Version 2.01 fixes some problems with multiple selection.</li>
+ <li>Version 2.0 supports multiple selection and virtual space.</li>
+ </ul>
+ <ul id="menu">
+ <li id="remote1"><a href="http://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
+ <li id="remote2"><a href="http://www.scintilla.org/ScintillaDownload.html">Download</a></li>
+ <li><a href="http://www.scintilla.org/ScintillaDoc.html">Documentation</a></li>
+ <li><a href="http://www.scintilla.org/ScintillaToDo.html">Bugs</a></li>
+ <li id="remote3"><a href="http://www.scintilla.org/SciTE.html">SciTE</a></li>
+ <li><a href="http://www.scintilla.org/ScintillaHistory.html">History</a></li>
+ <li><a href="http://www.scintilla.org/ScintillaRelated.html">Related</a></li>
+ </ul>
+<script type="text/javascript" language="JavaScript"><!--
+if (!IsRemote()) { //if NOT remote...
+ document.getElementById('remote1').style.display='none';
+ document.getElementById('remote2').style.display='none';
+ document.getElementById('remote3').style.display='none';
+}
+//--></script>
+ <p>
+ <a href="http://www.scintilla.org/ScintillaDoc.html">Scintilla</a> is a free source code editing component.
+ It comes with complete source code and a <a href="http://www.scintilla.org/License.txt">license</a> that
+ permits use in any free project or commercial product.
+ </p>
+ <p>
+ As well as features found in standard text editing components, Scintilla includes features
+ especially useful when editing and debugging source code.
+ These include support for syntax styling, error indicators, code completion and call tips.
+ The selection margin can contain markers like those used in debuggers to indicate
+ breakpoints and the current line. Styling choices are more open than with many editors,
+ allowing the use of proportional fonts, bold and italics, multiple foreground and background
+ colours and multiple fonts.
+ </p>
+ <p>
+ The <a href="http://www.scintilla.org/SinkWorld.html">SinkWorld project</a>
+ investigates possible future directions for Scintilla to make it more flexible, robust, perform
+ better and run on the .NET and Java virtual machines.
+ </p>
+ <p>
+ <a href="http://www.scintilla.org/SciTE.html">SciTE</a> is a SCIntilla based Text Editor. Originally built to
+ demonstrate Scintilla, it has grown to be a generally useful editor with facilities for
+ building and running programs. It is best used for jobs with simple configurations - I use it
+ for building test and demonstration programs as well as SciTE and Scintilla, themselves.
+ </p>
+ <p>
+ Development of Scintilla started as an effort to improve the text editor in PythonWin. After
+ being frustrated by problems in the Richedit control used by PythonWin, it looked like the
+ best way forward was to write a new edit control. The biggest problem with Richedit and other
+ similar controls is that they treat styling changes as important persistent changes to the
+ document so they are saved into the undo stack and set the document's dirty flag. For source
+ code, styling should not be persisted as it can be mechanically recreated.
+ </p>
+ <p>
+ Scintilla and SciTE are currently available for Intel Win32 and Linux compatible operating
+ systems with GTK+. They have been run on Windows XP, Windows 7, and on Ubuntu 9.10
+ with GTK+ 2.18. <a href="http://www.scintilla.org/SciTEImage.html">Here is a screenshot of
+ SciTE.</a><br />
+ </p>
+ <p>
+ You can <a href="http://www.scintilla.org/ScintillaDownload.html">download Scintilla.</a>
+ </p>
+ <p>
+ The source code can be downloaded via CVS at the Source Forge
+ <a href="https://sourceforge.net/project/?group_id=2439">Scintilla project page</a>.
+ </p>
+ <p>
+ <a href="http://www.scintilla.org/ScintillaRelated.html">Related sites.</a>
+ </p>
+ <p>
+ <a href="http://www.scintilla.org/ScintillaToDo.html">Bugs and To Do list.</a>
+ </p>
+ <p>
+ <a href="http://www.scintilla.org/ScintillaHistory.html">History and contribution credits.</a>
+ </p>
+ <p>
+ <a href="http://www.scintilla.org/Icons.html">Icons that can be used with Scintilla.</a>
+ </p>
+ <p>
+ The scintilla-interest mailing list has moved from lyra.org to Google Groups.
+ Questions and comments about Scintilla should be directed to the
+ <a href="http://groups.google.com/group/scintilla-interest">scintilla-interest</a>
+ mailing list,
+ which is for discussion of Scintilla and related projects, their bugs and future features.
+ This is a low traffic list, averaging less than 50 messages per week.
+ To avoid spam, only list members can write to the list.
+ New versions of Scintilla are announced on scintilla-interest and may also be received by SourceForge
+ members by clicking on the Monitor column icon for "scintilla" on
+ <a href="https://sourceforge.net/project/showfiles.php?group_id=2439">the downloads page</a>.
+ Messages sent to my personal email address that could have been sent to the list
+ may receive no response.
+ <br />
+ </p>
+There is a <a href="https://sourceforge.net/project/?group_id=2439">Scintilla project page</a>
+hosted on
+<script type="text/javascript" language="JavaScript">
+<!--
+if (IsRemote()) {
+ document.write('<a href="http://sourceforge.net/projects/scintilla">');
+ document.write('<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a> ');
+} else {
+ document.write('<a href="http://sourceforge.net/projects/scintilla">SourceForge<\/a>');
+}
+//-->
+</script>
+<noscript>
+<a href="http://sourceforge.net/projects/scintilla">
+<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
+</noscript>
+ </body>
+</html>
+
diff --git a/scintilla/doc/styledmargin.png b/scintilla/doc/styledmargin.png
new file mode 100644
index 0000000..3aaf35b
--- /dev/null
+++ b/scintilla/doc/styledmargin.png
Binary files differ
diff --git a/scintilla/gtk/Converter.h b/scintilla/gtk/Converter.h
new file mode 100644
index 0000000..9c5123b
--- /dev/null
+++ b/scintilla/gtk/Converter.h
@@ -0,0 +1,70 @@
+// Scintilla source code edit control
+// Converter.h - Encapsulation of iconv
+// Copyright 2004 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+typedef GIConv ConverterHandle;
+const ConverterHandle iconvhBad = (ConverterHandle)(-1);
+// Since various versions of iconv can not agree on whether the src argument
+// is char ** or const char ** provide a templatised adaptor.
+template<typename T>
+size_t iconv_adaptor(size_t(*f_iconv)(ConverterHandle, T, size_t *, char **, size_t *),
+ ConverterHandle cd, char** src, size_t *srcleft,
+ char **dst, size_t *dstleft) {
+ return f_iconv(cd, (T)src, srcleft, dst, dstleft);
+}
+/**
+ * Encapsulate iconv safely and avoid iconv_adaptor complexity in client code.
+ */
+class Converter {
+ ConverterHandle iconvh;
+ void OpenHandle(const char *fullDestination, const char *charSetSource) {
+ iconvh = g_iconv_open(fullDestination, charSetSource);
+ }
+ bool Succeeded() const {
+ return iconvh != iconvhBad;
+ }
+public:
+ Converter() {
+ iconvh = iconvhBad;
+ }
+ Converter(const char *charSetDestination, const char *charSetSource, bool transliterations) {
+ iconvh = iconvhBad;
+ Open(charSetDestination, charSetSource, transliterations);
+ }
+ ~Converter() {
+ Close();
+ }
+ operator bool() const {
+ return Succeeded();
+ }
+ void Open(const char *charSetDestination, const char *charSetSource, bool transliterations=true) {
+ Close();
+ if (*charSetSource) {
+ // Try allowing approximate transliterations
+ if (transliterations) {
+ char fullDest[200];
+ strcpy(fullDest, charSetDestination);
+ strcat(fullDest, "//TRANSLIT");
+ OpenHandle(fullDest, charSetSource);
+ }
+ if (!Succeeded()) {
+ // Transliterations failed so try basic name
+ OpenHandle(charSetDestination, charSetSource);
+ }
+ }
+ }
+ void Close() {
+ if (Succeeded()) {
+ g_iconv_close(iconvh);
+ iconvh = iconvhBad;
+ }
+ }
+ size_t Convert(char** src, size_t *srcleft, char **dst, size_t *dstleft) const {
+ if (!Succeeded()) {
+ return (size_t)(-1);
+ } else {
+ return iconv_adaptor(g_iconv, iconvh, src, srcleft, dst, dstleft);
+ }
+ }
+};
diff --git a/scintilla/gtk/PlatGTK.cxx b/scintilla/gtk/PlatGTK.cxx
new file mode 100644
index 0000000..b6e7f7e
--- /dev/null
+++ b/scintilla/gtk/PlatGTK.cxx
@@ -0,0 +1,2577 @@
+// Scintilla source code edit control
+// PlatGTK.cxx - implementation of platform facilities on GTK+/Linux
+// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include <glib.h>
+#include <gmodule.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "ScintillaWidget.h"
+#include "UniConversion.h"
+#include "XPM.h"
+
+/* GLIB must be compiled with thread support, otherwise we
+ will bail on trying to use locks, and that could lead to
+ problems for someone. `glib-config --libs gthread` needs
+ to be used to get the glib libraries for linking, otherwise
+ g_thread_init will fail */
+#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)
+/* Use fast way of getting char data on win32 to work around problems
+ with gdk_string_extents. */
+#define FAST_WAY
+
+#include "Converter.h"
+
+#ifdef _MSC_VER
+// Ignore unreferenced local functions in GTK+ headers
+#pragma warning(disable: 4505)
+#endif
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+enum encodingType { singleByte, UTF8, dbcs};
+
+struct LOGFONT {
+ int size;
+ bool bold;
+ bool italic;
+ int characterSet;
+ char faceName[300];
+};
+
+#if USE_LOCK
+static GMutex *fontMutex = NULL;
+
+static void InitializeGLIBThreads() {
+ if (!g_thread_supported()) {
+ g_thread_init(NULL);
+ }
+}
+#endif
+
+static void FontMutexAllocate() {
+#if USE_LOCK
+ if (!fontMutex) {
+ InitializeGLIBThreads();
+ fontMutex = g_mutex_new();
+ }
+#endif
+}
+
+static void FontMutexFree() {
+#if USE_LOCK
+ if (fontMutex) {
+ g_mutex_free(fontMutex);
+ fontMutex = NULL;
+ }
+#endif
+}
+
+static void FontMutexLock() {
+#if USE_LOCK
+ g_mutex_lock(fontMutex);
+#endif
+}
+
+static void FontMutexUnlock() {
+#if USE_LOCK
+ if (fontMutex) {
+ g_mutex_unlock(fontMutex);
+ }
+#endif
+}
+
+// On GTK+ 1.x holds a GdkFont* but on GTK+ 2.x can hold a GdkFont* or a
+// PangoFontDescription*.
+class FontHandle {
+ int width[128];
+ encodingType et;
+public:
+ int ascent;
+ GdkFont *pfont;
+ PangoFontDescription *pfd;
+ int characterSet;
+ FontHandle(GdkFont *pfont_) {
+ et = singleByte;
+ ascent = 0;
+ pfont = pfont_;
+ pfd = 0;
+ characterSet = -1;
+ ResetWidths(et);
+ }
+ FontHandle(PangoFontDescription *pfd_, int characterSet_) {
+ et = singleByte;
+ ascent = 0;
+ pfont = 0;
+ pfd = pfd_;
+ characterSet = characterSet_;
+ ResetWidths(et);
+ }
+ ~FontHandle() {
+ if (pfont)
+ gdk_font_unref(pfont);
+ pfont = 0;
+ if (pfd)
+ pango_font_description_free(pfd);
+ pfd = 0;
+ }
+ void ResetWidths(encodingType et_) {
+ et = et_;
+ for (int i=0; i<=127; i++) {
+ width[i] = 0;
+ }
+ }
+ int CharWidth(unsigned char ch, encodingType et_) {
+ int w = 0;
+ FontMutexLock();
+ if ((ch <= 127) && (et == et_)) {
+ w = width[ch];
+ }
+ FontMutexUnlock();
+ return w;
+ }
+ void SetCharWidth(unsigned char ch, int w, encodingType et_) {
+ if (ch <= 127) {
+ FontMutexLock();
+ if (et != et_) {
+ ResetWidths(et_);
+ }
+ width[ch] = w;
+ FontMutexUnlock();
+ }
+ }
+};
+
+// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
+static const int maxCoordinate = 32000;
+
+static FontHandle *PFont(Font &f) {
+ return reinterpret_cast<FontHandle *>(f.GetID());
+}
+
+static GtkWidget *PWidget(WindowID wid) {
+ return reinterpret_cast<GtkWidget *>(wid);
+}
+
+static GtkWidget *PWidget(Window &w) {
+ return PWidget(w.GetID());
+}
+
+Point Point::FromLong(long lpoint) {
+ return Point(
+ Platform::LowShortFromLong(lpoint),
+ Platform::HighShortFromLong(lpoint));
+}
+
+Palette::Palette() {
+ used = 0;
+ allowRealization = false;
+ allocatedPalette = 0;
+ allocatedLen = 0;
+ size = 100;
+ entries = new ColourPair[size];
+}
+
+Palette::~Palette() {
+ Release();
+ delete []entries;
+ entries = 0;
+}
+
+void Palette::Release() {
+ used = 0;
+ delete [](reinterpret_cast<GdkColor *>(allocatedPalette));
+ allocatedPalette = 0;
+ allocatedLen = 0;
+ delete []entries;
+ size = 100;
+ entries = new ColourPair[size];
+}
+
+// This method either adds a colour to the list of wanted colours (want==true)
+// or retrieves the allocated colour back to the ColourPair.
+// This is one method to make it easier to keep the code for wanting and retrieving in sync.
+void Palette::WantFind(ColourPair &cp, bool want) {
+ if (want) {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired)
+ return;
+ }
+
+ if (used >= size) {
+ int sizeNew = size * 2;
+ ColourPair *entriesNew = new ColourPair[sizeNew];
+ for (int j=0; j<size; j++) {
+ entriesNew[j] = entries[j];
+ }
+ delete []entries;
+ entries = entriesNew;
+ size = sizeNew;
+ }
+
+ entries[used].desired = cp.desired;
+ entries[used].allocated.Set(cp.desired.AsLong());
+ used++;
+ } else {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired) {
+ cp.allocated = entries[i].allocated;
+ return;
+ }
+ }
+ cp.allocated.Set(cp.desired.AsLong());
+ }
+}
+
+void Palette::Allocate(Window &w) {
+ if (allocatedPalette) {
+ gdk_colormap_free_colors(gtk_widget_get_colormap(PWidget(w)),
+ reinterpret_cast<GdkColor *>(allocatedPalette),
+ allocatedLen);
+ delete [](reinterpret_cast<GdkColor *>(allocatedPalette));
+ allocatedPalette = 0;
+ allocatedLen = 0;
+ }
+ GdkColor *paletteNew = new GdkColor[used];
+ allocatedPalette = paletteNew;
+ gboolean *successPalette = new gboolean[used];
+ if (paletteNew) {
+ allocatedLen = used;
+ int iPal = 0;
+ for (iPal = 0; iPal < used; iPal++) {
+ paletteNew[iPal].red = entries[iPal].desired.GetRed() * (65535 / 255);
+ paletteNew[iPal].green = entries[iPal].desired.GetGreen() * (65535 / 255);
+ paletteNew[iPal].blue = entries[iPal].desired.GetBlue() * (65535 / 255);
+ paletteNew[iPal].pixel = entries[iPal].desired.AsLong();
+ }
+ gdk_colormap_alloc_colors(gtk_widget_get_colormap(PWidget(w)),
+ paletteNew, allocatedLen, FALSE, TRUE,
+ successPalette);
+ for (iPal = 0; iPal < used; iPal++) {
+ entries[iPal].allocated.Set(paletteNew[iPal].pixel);
+ }
+ }
+ delete []successPalette;
+}
+
+static const char *CharacterSetName(int characterSet) {
+ switch (characterSet) {
+ case SC_CHARSET_ANSI:
+ return "iso8859-*";
+ case SC_CHARSET_DEFAULT:
+ return "iso8859-*";
+ case SC_CHARSET_BALTIC:
+ return "iso8859-13";
+ case SC_CHARSET_CHINESEBIG5:
+ return "*-*";
+ case SC_CHARSET_EASTEUROPE:
+ return "*-2";
+ case SC_CHARSET_GB2312:
+ return "gb2312.1980-*";
+ case SC_CHARSET_GREEK:
+ return "*-7";
+ case SC_CHARSET_HANGUL:
+ return "ksc5601.1987-*";
+ case SC_CHARSET_MAC:
+ return "*-*";
+ case SC_CHARSET_OEM:
+ return "*-*";
+ case SC_CHARSET_RUSSIAN:
+ return "*-r";
+ case SC_CHARSET_CYRILLIC:
+ return "*-cp1251";
+ case SC_CHARSET_SHIFTJIS:
+ return "jisx0208.1983-*";
+ case SC_CHARSET_SYMBOL:
+ return "*-*";
+ case SC_CHARSET_TURKISH:
+ return "*-9";
+ case SC_CHARSET_JOHAB:
+ return "*-*";
+ case SC_CHARSET_HEBREW:
+ return "*-8";
+ case SC_CHARSET_ARABIC:
+ return "*-6";
+ case SC_CHARSET_VIETNAMESE:
+ return "*-*";
+ case SC_CHARSET_THAI:
+ return "iso8859-11";
+ case SC_CHARSET_8859_15:
+ return "iso8859-15";
+ default:
+ return "*-*";
+ }
+}
+
+static bool IsDBCSCharacterSet(int characterSet) {
+ switch (characterSet) {
+ case SC_CHARSET_GB2312:
+ case SC_CHARSET_HANGUL:
+ case SC_CHARSET_SHIFTJIS:
+ case SC_CHARSET_CHINESEBIG5:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void GenerateFontSpecStrings(const char *fontName, int characterSet,
+ char *foundary, int foundary_len,
+ char *faceName, int faceName_len,
+ char *charset, int charset_len) {
+ // supported font strings include:
+ // foundary-fontface-isoxxx-x
+ // fontface-isoxxx-x
+ // foundary-fontface
+ // fontface
+ if (strchr(fontName, '-')) {
+ char tmp[300];
+ char *d1 = NULL, *d2 = NULL, *d3 = NULL;
+ strncpy(tmp, fontName, sizeof(tmp) - 1);
+ tmp[sizeof(tmp) - 1] = '\0';
+ d1 = strchr(tmp, '-');
+ // we know the first dash exists
+ d2 = strchr(d1 + 1, '-');
+ if (d2)
+ d3 = strchr(d2 + 1, '-');
+ if (d3 && d2) {
+ // foundary-fontface-isoxxx-x
+ *d2 = '\0';
+ foundary[0] = '-';
+ foundary[1] = '\0';
+ strncpy(faceName, tmp, foundary_len - 1);
+ strncpy(charset, d2 + 1, charset_len - 1);
+ } else if (d2) {
+ // fontface-isoxxx-x
+ *d1 = '\0';
+ strcpy(foundary, "-*-");
+ strncpy(faceName, tmp, faceName_len - 1);
+ strncpy(charset, d1 + 1, charset_len - 1);
+ } else {
+ // foundary-fontface
+ foundary[0] = '-';
+ foundary[1] = '\0';
+ strncpy(faceName, tmp, faceName_len - 1);
+ strncpy(charset, CharacterSetName(characterSet), charset_len - 1);
+ }
+ } else {
+ strncpy(foundary, "-*-", foundary_len);
+ strncpy(faceName, fontName, faceName_len - 1);
+ strncpy(charset, CharacterSetName(characterSet), charset_len - 1);
+ }
+}
+
+static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, int size, bool bold, bool italic) {
+ memset(&lf, 0, sizeof(lf));
+ lf.size = size;
+ lf.bold = bold;
+ lf.italic = italic;
+ lf.characterSet = characterSet;
+ strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1);
+}
+
+/**
+ * Create a hash from the parameters for a font to allow easy checking for identity.
+ * If one font is the same as another, its hash will be the same, but if the hash is the
+ * same then they may still be different.
+ */
+static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic) {
+ return
+ size ^
+ (characterSet << 10) ^
+ (bold ? 0x10000000 : 0) ^
+ (italic ? 0x20000000 : 0) ^
+ faceName[0];
+}
+
+class FontCached : Font {
+ FontCached *next;
+ int usage;
+ LOGFONT lf;
+ int hash;
+ FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ ~FontCached() {}
+ bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ virtual void Release();
+ static FontID CreateNewFont(const char *fontName, int characterSet,
+ int size, bool bold, bool italic);
+ static FontCached *first;
+public:
+ static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_);
+ static void ReleaseId(FontID fid_);
+};
+
+FontCached *FontCached::first = 0;
+
+FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) :
+next(0), usage(0), hash(0) {
+ ::SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_);
+ hash = HashFont(faceName_, characterSet_, size_, bold_, italic_);
+ fid = CreateNewFont(faceName_, characterSet_, size_, bold_, italic_);
+ usage = 1;
+}
+
+bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
+ return
+ lf.size == size_ &&
+ lf.bold == bold_ &&
+ lf.italic == italic_ &&
+ lf.characterSet == characterSet_ &&
+ 0 == strcmp(lf.faceName, faceName_);
+}
+
+void FontCached::Release() {
+ if (fid)
+ delete PFont(*this);
+ fid = 0;
+}
+
+FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_) {
+ FontID ret = 0;
+ FontMutexLock();
+ int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_);
+ for (FontCached *cur = first; cur; cur = cur->next) {
+ if ((cur->hash == hashFind) &&
+ cur->SameAs(faceName_, characterSet_, size_, bold_, italic_)) {
+ cur->usage++;
+ ret = cur->fid;
+ }
+ }
+ if (ret == 0) {
+ FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_);
+ if (fc) {
+ fc->next = first;
+ first = fc;
+ ret = fc->fid;
+ }
+ }
+ FontMutexUnlock();
+ return ret;
+}
+
+void FontCached::ReleaseId(FontID fid_) {
+ FontMutexLock();
+ FontCached **pcur = &first;
+ for (FontCached *cur = first; cur; cur = cur->next) {
+ if (cur->fid == fid_) {
+ cur->usage--;
+ if (cur->usage == 0) {
+ *pcur = cur->next;
+ cur->Release();
+ cur->next = 0;
+ delete cur;
+ }
+ break;
+ }
+ pcur = &cur->next;
+ }
+ FontMutexUnlock();
+}
+
+static GdkFont *LoadFontOrSet(const char *fontspec, int characterSet) {
+ if (IsDBCSCharacterSet(characterSet)) {
+ return gdk_fontset_load(fontspec);
+ } else {
+ return gdk_font_load(fontspec);
+ }
+}
+
+FontID FontCached::CreateNewFont(const char *fontName, int characterSet,
+ int size, bool bold, bool italic) {
+ char fontset[1024];
+ char fontspec[300];
+ char foundary[50];
+ char faceName[100];
+ char charset[50];
+ fontset[0] = '\0';
+ fontspec[0] = '\0';
+ foundary[0] = '\0';
+ faceName[0] = '\0';
+ charset[0] = '\0';
+
+ if (fontName[0] == '!') {
+ PangoFontDescription *pfd = pango_font_description_new();
+ if (pfd) {
+ pango_font_description_set_family(pfd, fontName+1);
+ pango_font_description_set_size(pfd, size * PANGO_SCALE);
+ pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ return new FontHandle(pfd, characterSet);
+ }
+ }
+
+ GdkFont *newid = 0;
+ // If name of the font begins with a '-', assume, that it is
+ // a full fontspec.
+ if (fontName[0] == '-') {
+ if (strchr(fontName, ',') || IsDBCSCharacterSet(characterSet)) {
+ newid = gdk_fontset_load(fontName);
+ } else {
+ newid = gdk_font_load(fontName);
+ }
+ if (!newid) {
+ // Font not available so substitute a reasonable code font
+ // iso8859 appears to only allow western characters.
+ newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
+ characterSet);
+ }
+ return new FontHandle(newid);
+ }
+
+ // it's not a full fontspec, build one.
+
+ // This supports creating a FONT_SET
+ // in a method that allows us to also set size, slant and
+ // weight for the fontset. The expected input is multiple
+ // partial fontspecs seperated by comma
+ // eg. adobe-courier-iso10646-1,*-courier-iso10646-1,*-*-*-*
+ if (strchr(fontName, ',')) {
+ // build a fontspec and use gdk_fontset_load
+ int remaining = sizeof(fontset);
+ char fontNameCopy[1024];
+ strncpy(fontNameCopy, fontName, sizeof(fontNameCopy) - 1);
+ char *fn = fontNameCopy;
+ char *fp = strchr(fn, ',');
+ for (;;) {
+ const char *spec = "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s";
+ if (fontset[0] != '\0') {
+ // if this is not the first font in the list,
+ // append a comma seperator
+ spec = ",%s%s%s%s-*-*-*-%0d-*-*-*-*-%s";
+ }
+
+ if (fp)
+ *fp = '\0'; // nullify the comma
+ GenerateFontSpecStrings(fn, characterSet,
+ foundary, sizeof(foundary),
+ faceName, sizeof(faceName),
+ charset, sizeof(charset));
+
+ g_snprintf(fontspec,
+ sizeof(fontspec) - 1,
+ spec,
+ foundary, faceName,
+ bold ? "-bold" : "-medium",
+ italic ? "-i" : "-r",
+ size * 10,
+ charset);
+
+ // if this is the first font in the list, and
+ // we are doing italic, add an oblique font
+ // to the list
+ if (italic && fontset[0] == '\0') {
+ strncat(fontset, fontspec, remaining - 1);
+ remaining -= strlen(fontset);
+
+ g_snprintf(fontspec,
+ sizeof(fontspec) - 1,
+ ",%s%s%s-o-*-*-*-%0d-*-*-*-*-%s",
+ foundary, faceName,
+ bold ? "-bold" : "-medium",
+ size * 10,
+ charset);
+ }
+
+ strncat(fontset, fontspec, remaining - 1);
+ remaining -= strlen(fontset);
+
+ if (!fp)
+ break;
+
+ fn = fp + 1;
+ fp = strchr(fn, ',');
+ }
+
+ newid = gdk_fontset_load(fontset);
+ if (newid)
+ return new FontHandle(newid);
+
+ // if fontset load failed, fall through, we'll use
+ // the last font entry and continue to try and
+ // get something that matches
+ }
+
+ // single fontspec support
+
+ GenerateFontSpecStrings(fontName, characterSet,
+ foundary, sizeof(foundary),
+ faceName, sizeof(faceName),
+ charset, sizeof(charset));
+
+ g_snprintf(fontspec,
+ sizeof(fontspec) - 1,
+ "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
+ foundary, faceName,
+ bold ? "-bold" : "-medium",
+ italic ? "-i" : "-r",
+ size * 10,
+ charset);
+ newid = LoadFontOrSet(fontspec, characterSet);
+ if (!newid) {
+ // some fonts have oblique, not italic
+ g_snprintf(fontspec,
+ sizeof(fontspec) - 1,
+ "%s%s%s%s-*-*-*-%0d-*-*-*-*-%s",
+ foundary, faceName,
+ bold ? "-bold" : "-medium",
+ italic ? "-o" : "-r",
+ size * 10,
+ charset);
+ newid = LoadFontOrSet(fontspec, characterSet);
+ }
+ if (!newid) {
+ g_snprintf(fontspec,
+ sizeof(fontspec) - 1,
+ "-*-*-*-*-*-*-*-%0d-*-*-*-*-%s",
+ size * 10,
+ charset);
+ newid = gdk_font_load(fontspec);
+ }
+ if (!newid) {
+ // Font not available so substitute a reasonable code font
+ // iso8859 appears to only allow western characters.
+ newid = LoadFontOrSet("-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-*",
+ characterSet);
+ }
+ return new FontHandle(newid);
+}
+
+Font::Font() : fid(0) {}
+
+Font::~Font() {}
+
+void Font::Create(const char *faceName, int characterSet, int size,
+ bool bold, bool italic, int) {
+ Release();
+ fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
+}
+
+void Font::Release() {
+ if (fid)
+ FontCached::ReleaseId(fid);
+ fid = 0;
+}
+
+// Required on OS X
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+class SurfaceImpl : public Surface {
+ encodingType et;
+ GdkDrawable *drawable;
+ GdkGC *gc;
+ GdkPixmap *ppixmap;
+ int x;
+ int y;
+ bool inited;
+ bool createdGC;
+ PangoContext *pcontext;
+ PangoLayout *layout;
+ Converter conv;
+ int characterSet;
+ void SetConverter(int characterSet_);
+public:
+ SurfaceImpl();
+ virtual ~SurfaceImpl();
+
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+
+ void Release();
+ bool Initialised();
+ void PenColour(ColourAllocated fore);
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+ void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
+ void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, int *positions);
+ int WidthText(Font &font_, const char *s, int len);
+ int WidthChar(Font &font_, char ch);
+ int Ascent(Font &font_);
+ int Descent(Font &font_);
+ int InternalLeading(Font &font_);
+ int ExternalLeading(Font &font_);
+ int Height(Font &font_);
+ int AverageCharWidth(Font &font_);
+
+ int SetPalette(Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage);
+};
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+const char *CharacterSetID(int characterSet) {
+ switch (characterSet) {
+ case SC_CHARSET_ANSI:
+ return "";
+ case SC_CHARSET_DEFAULT:
+ return "ISO-8859-1";
+ case SC_CHARSET_BALTIC:
+ return "ISO-8859-13";
+ case SC_CHARSET_CHINESEBIG5:
+ return "BIG-5";
+ case SC_CHARSET_EASTEUROPE:
+ return "ISO-8859-2";
+ case SC_CHARSET_GB2312:
+ return "GB2312";
+ case SC_CHARSET_GREEK:
+ return "ISO-8859-7";
+ case SC_CHARSET_HANGUL:
+ return "";
+ case SC_CHARSET_MAC:
+ return "MACINTOSH";
+ case SC_CHARSET_OEM:
+ return "ASCII";
+ case SC_CHARSET_RUSSIAN:
+ return "KOI8-R";
+ case SC_CHARSET_CYRILLIC:
+ return "CP1251";
+ case SC_CHARSET_SHIFTJIS:
+ return "SHIFT-JIS";
+ case SC_CHARSET_SYMBOL:
+ return "";
+ case SC_CHARSET_TURKISH:
+ return "ISO-8859-9";
+ case SC_CHARSET_JOHAB:
+ return "JOHAB";
+ case SC_CHARSET_HEBREW:
+ return "ISO-8859-8";
+ case SC_CHARSET_ARABIC:
+ return "ISO-8859-6";
+ case SC_CHARSET_VIETNAMESE:
+ return "";
+ case SC_CHARSET_THAI:
+ return "ISO-8859-11";
+ case SC_CHARSET_8859_15:
+ return "ISO-8859-15";
+ default:
+ return "";
+ }
+}
+
+void SurfaceImpl::SetConverter(int characterSet_) {
+ if (characterSet != characterSet_) {
+ characterSet = characterSet_;
+ conv.Open("UTF-8", CharacterSetID(characterSet), false);
+ }
+}
+
+SurfaceImpl::SurfaceImpl() : et(singleByte), drawable(0), gc(0), ppixmap(0),
+x(0), y(0), inited(false), createdGC(false)
+, pcontext(0), layout(0), characterSet(-1) {
+}
+
+SurfaceImpl::~SurfaceImpl() {
+ Release();
+}
+
+void SurfaceImpl::Release() {
+ et = singleByte;
+ drawable = 0;
+ if (createdGC) {
+ createdGC = false;
+ gdk_gc_unref(gc);
+ }
+ gc = 0;
+ if (ppixmap)
+ gdk_pixmap_unref(ppixmap);
+ ppixmap = 0;
+ if (layout)
+ g_object_unref(layout);
+ layout = 0;
+ if (pcontext)
+ g_object_unref(pcontext);
+ pcontext = 0;
+ conv.Close();
+ characterSet = -1;
+ x = 0;
+ y = 0;
+ inited = false;
+ createdGC = false;
+}
+
+bool SurfaceImpl::Initialised() {
+ return inited;
+}
+
+void SurfaceImpl::Init(WindowID wid) {
+ Release();
+ PLATFORM_ASSERT(wid);
+ pcontext = gtk_widget_create_pango_context(PWidget(wid));
+ PLATFORM_ASSERT(pcontext);
+ layout = pango_layout_new(pcontext);
+ PLATFORM_ASSERT(layout);
+ inited = true;
+}
+
+void SurfaceImpl::Init(SurfaceID sid, WindowID wid) {
+ PLATFORM_ASSERT(sid);
+ GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);
+ Release();
+ PLATFORM_ASSERT(wid);
+ pcontext = gtk_widget_create_pango_context(PWidget(wid));
+ layout = pango_layout_new(pcontext);
+ drawable = drawable_;
+ gc = gdk_gc_new(drawable_);
+ // Ask for lines that do not paint the last pixel so is like Win32
+ gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
+ createdGC = true;
+ inited = true;
+}
+
+void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID wid) {
+ PLATFORM_ASSERT(surface_);
+ Release();
+ SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
+ PLATFORM_ASSERT(surfImpl->drawable);
+ PLATFORM_ASSERT(wid);
+ pcontext = gtk_widget_create_pango_context(PWidget(wid));
+ PLATFORM_ASSERT(pcontext);
+ layout = pango_layout_new(pcontext);
+ PLATFORM_ASSERT(layout);
+ if (height > 0 && width > 0)
+ ppixmap = gdk_pixmap_new(surfImpl->drawable, width, height, -1);
+ drawable = ppixmap;
+ gc = gdk_gc_new(surfImpl->drawable);
+ // Ask for lines that do not paint the last pixel so is like Win32
+ gdk_gc_set_line_attributes(gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
+ createdGC = true;
+ inited = true;
+}
+
+void SurfaceImpl::PenColour(ColourAllocated fore) {
+ if (gc) {
+ GdkColor co;
+ co.pixel = fore.AsLong();
+ gdk_gc_set_foreground(gc, &co);
+ }
+}
+
+int SurfaceImpl::LogPixelsY() {
+ return 72;
+}
+
+int SurfaceImpl::DeviceHeightFont(int points) {
+ int logPix = LogPixelsY();
+ return (points * logPix + logPix / 2) / 72;
+}
+
+void SurfaceImpl::MoveTo(int x_, int y_) {
+ x = x_;
+ y = y_;
+}
+
+void SurfaceImpl::LineTo(int x_, int y_) {
+ if (drawable && gc) {
+ gdk_draw_line(drawable, gc,
+ x, y,
+ x_, y_);
+ }
+ x = x_;
+ y = y_;
+}
+
+void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore,
+ ColourAllocated back) {
+ GdkPoint gpts[20];
+ if (npts < static_cast<int>((sizeof(gpts) / sizeof(gpts[0])))) {
+ for (int i = 0;i < npts;i++) {
+ gpts[i].x = pts[i].x;
+ gpts[i].y = pts[i].y;
+ }
+ PenColour(back);
+ gdk_draw_polygon(drawable, gc, 1, gpts, npts);
+ PenColour(fore);
+ gdk_draw_polygon(drawable, gc, 0, gpts, npts);
+ }
+}
+
+void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (gc && drawable) {
+ PenColour(back);
+ gdk_draw_rectangle(drawable, gc, 1,
+ rc.left + 1, rc.top + 1,
+ rc.right - rc.left - 2, rc.bottom - rc.top - 2);
+
+ PenColour(fore);
+ // The subtraction of 1 off the width and height here shouldn't be needed but
+ // otherwise a different rectangle is drawn than would be done if the fill parameter == 1
+ gdk_draw_rectangle(drawable, gc, 0,
+ rc.left, rc.top,
+ rc.right - rc.left - 1, rc.bottom - rc.top - 1);
+ }
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
+ PenColour(back);
+ if (drawable && (rc.left < maxCoordinate)) { // Protect against out of range
+ gdk_draw_rectangle(drawable, gc, 1,
+ rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top);
+ }
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ if (static_cast<SurfaceImpl &>(surfacePattern).drawable) {
+ // Tile pattern over rectangle
+ // Currently assumes 8x8 pattern
+ int widthPat = 8;
+ int heightPat = 8;
+ for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
+ int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
+ for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
+ int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
+ gdk_draw_pixmap(drawable,
+ gc,
+ static_cast<SurfaceImpl &>(surfacePattern).drawable,
+ 0, 0,
+ xTile, yTile,
+ widthx, heighty);
+ }
+ }
+ } else {
+ // Something is wrong so try to show anyway
+ // Shows up black because colour not allocated
+ FillRectangle(rc, ColourAllocated(0));
+ }
+}
+
+void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) {
+ // Approximate a round rect with some cut off corners
+ Point pts[] = {
+ Point(rc.left + 2, rc.top),
+ Point(rc.right - 2, rc.top),
+ Point(rc.right, rc.top + 2),
+ Point(rc.right, rc.bottom - 2),
+ Point(rc.right - 2, rc.bottom),
+ Point(rc.left + 2, rc.bottom),
+ Point(rc.left, rc.bottom - 2),
+ Point(rc.left, rc.top + 2),
+ };
+ Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back);
+ } else {
+ RectangleDraw(rc, fore, back);
+ }
+}
+
+// Plot a point into a guint32 buffer symetrically to all 4 qudrants
+static void AllFour(guint32 *pixels, int stride, int width, int height, int x, int y, guint32 val) {
+ pixels[y*stride+x] = val;
+ pixels[y*stride+width-1-x] = val;
+ pixels[(height-1-y)*stride+x] = val;
+ pixels[(height-1-y)*stride+width-1-x] = val;
+}
+
+static unsigned int GetRValue(unsigned int co) {
+ return (co >> 16) & 0xff;
+}
+
+static unsigned int GetGValue(unsigned int co) {
+ return (co >> 8) & 0xff;
+}
+
+static unsigned int GetBValue(unsigned int co) {
+ return co & 0xff;
+}
+
+static guint32 u32FromRGBA(guint8 r, guint8 g, guint8 b, guint8 a) {
+ union {
+ guint8 pixVal[4];
+ guint32 val;
+ } converter;
+ converter.pixVal[0] = r;
+ converter.pixVal[1] = g;
+ converter.pixVal[2] = b;
+ converter.pixVal[3] = a;
+ return converter.val;
+}
+
+void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags) {
+ if (gc && drawable && rc.Width() > 0) {
+ int width = rc.Width();
+ int height = rc.Height();
+ // Ensure not distorted too much by corners when small
+ cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
+ // Make a 32 bit deep pixbuf with alpha
+ GdkPixbuf *pixalpha = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+
+ guint32 valEmpty = u32FromRGBA(0,0,0,0);
+ guint32 valFill = u32FromRGBA(GetRValue(fill.AsLong()),
+ GetGValue(fill.AsLong()), GetBValue(fill.AsLong()), alphaFill);
+ guint32 valOutline = u32FromRGBA(GetRValue(outline.AsLong()),
+ GetGValue(outline.AsLong()), GetBValue(outline.AsLong()), alphaOutline);
+ guint32 *pixels = reinterpret_cast<guint32 *>(gdk_pixbuf_get_pixels(pixalpha));
+ int stride = gdk_pixbuf_get_rowstride(pixalpha) / 4;
+ for (int yr=0; yr<height; yr++) {
+ for (int xr=0; xr<width; xr++) {
+ if ((xr==0) || (xr==width-1) || (yr == 0) || (yr == height-1)) {
+ pixels[yr*stride+xr] = valOutline;
+ } else {
+ pixels[yr*stride+xr] = valFill;
+ }
+ }
+ }
+ for (int c=0;c<cornerSize; c++) {
+ for (int xr=0;xr<c+1; xr++) {
+ AllFour(pixels, stride, width, height, xr, c-xr, valEmpty);
+ }
+ }
+ for (int xr=1;xr<cornerSize; xr++) {
+ AllFour(pixels, stride, width, height, xr, cornerSize-xr, valOutline);
+ }
+
+ // Draw with alpha
+ gdk_draw_pixbuf(drawable, gc, pixalpha,
+ 0,0, rc.left,rc.top, width,height, GDK_RGB_DITHER_NORMAL, 0, 0);
+
+ g_object_unref(pixalpha);
+ }
+}
+
+void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ PenColour(back);
+ gdk_draw_arc(drawable, gc, 1,
+ rc.left + 1, rc.top + 1,
+ rc.right - rc.left - 2, rc.bottom - rc.top - 2,
+ 0, 32767);
+
+ // The subtraction of 1 here is similar to the case for RectangleDraw
+ PenColour(fore);
+ gdk_draw_arc(drawable, gc, 0,
+ rc.left, rc.top,
+ rc.right - rc.left - 1, rc.bottom - rc.top - 1,
+ 0, 32767);
+}
+
+void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+ if (static_cast<SurfaceImpl &>(surfaceSource).drawable) {
+ gdk_draw_pixmap(drawable,
+ gc,
+ static_cast<SurfaceImpl &>(surfaceSource).drawable,
+ from.x, from.y,
+ rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top);
+ }
+}
+
+static size_t UTF8Len(char ch) {
+ unsigned char uch = static_cast<unsigned char>(ch);
+ if (uch < 0x80)
+ return 1;
+ else if (uch < (0x80 + 0x40 + 0x20))
+ return 2;
+ else
+ return 3;
+}
+
+char *UTF8FromLatin1(const char *s, int &len) {
+ char *utfForm = new char[len*2+1];
+ size_t lenU = 0;
+ for (int i=0;i<len;i++) {
+ unsigned int uch = static_cast<unsigned char>(s[i]);
+ if (uch < 0x80) {
+ utfForm[lenU++] = uch;
+ } else {
+ utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ }
+ utfForm[lenU] = '\0';
+ len = lenU;
+ return utfForm;
+}
+
+static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) {
+ if (conv) {
+ char *utfForm = new char[len*3+1];
+ char *pin = const_cast<char *>(s);
+ size_t inLeft = len;
+ char *pout = utfForm;
+ size_t outLeft = len*3+1;
+ size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
+ if (conversions != ((size_t)(-1))) {
+ *pout = '\0';
+ len = pout - utfForm;
+ return utfForm;
+ }
+ delete []utfForm;
+ }
+ return 0;
+}
+
+// Work out how many bytes are in a character by trying to convert using iconv,
+// returning the first length that succeeds.
+static size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t len) {
+ for (size_t lenMB=1; (lenMB<4) && (lenMB <= len); lenMB++) {
+ char wcForm[2];
+ char *pin = const_cast<char *>(s);
+ size_t inLeft = lenMB;
+ char *pout = wcForm;
+ size_t outLeft = 2;
+ size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
+ if (conversions != ((size_t)(-1))) {
+ return lenMB;
+ }
+ }
+ return 1;
+}
+
+static char *UTF8FromGdkWChar(GdkWChar *wctext, int wclen) {
+ char *utfForm = new char[wclen*3+1]; // Maximum of 3 UTF-8 bytes per character
+ size_t lenU = 0;
+ for (int i = 0; i < wclen && wctext[i]; i++) {
+ unsigned int uch = wctext[i];
+ if (uch < 0x80) {
+ utfForm[lenU++] = static_cast<char>(uch);
+ } else if (uch < 0x800) {
+ utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ } else {
+ utfForm[lenU++] = static_cast<char>(0xE0 | (uch >> 12));
+ utfForm[lenU++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
+ utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ }
+ utfForm[lenU] = '\0';
+ return utfForm;
+}
+
+static char *UTF8FromDBCS(const char *s, int &len) {
+ GdkWChar *wctext = new GdkWChar[len + 1];
+ GdkWChar *wcp = wctext;
+ int wclen = gdk_mbstowcs(wcp, s, len);
+ if (wclen < 1) {
+ // In the annoying case when non-locale chars in the line.
+ // e.g. latin1 chars in Japanese locale.
+ delete []wctext;
+ return 0;
+ }
+
+ char *utfForm = UTF8FromGdkWChar(wctext, wclen);
+ delete []wctext;
+ len = strlen(utfForm);
+ return utfForm;
+}
+
+static size_t UTF8CharLength(const char *s) {
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ unsigned char ch = *us;
+ if (ch < 0x80) {
+ return 1;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ return 2;
+ } else {
+ return 3;
+ }
+}
+
+// On GTK+, wchar_t is 4 bytes
+
+const int maxLengthTextRun = 10000;
+
+void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore) {
+ PenColour(fore);
+ if (gc && drawable) {
+ int xText = rc.left;
+ if (PFont(font_)->pfd) {
+ char *utfForm = 0;
+ bool useGFree = false;
+ if (et == UTF8) {
+ pango_layout_set_text(layout, s, len);
+ } else {
+ if (!utfForm) {
+ SetConverter(PFont(font_)->characterSet);
+ utfForm = UTF8FromIconv(conv, s, len);
+ }
+ if (!utfForm) { // iconv failed so try DBCS if DBCS mode
+ if (et == dbcs) {
+ // Convert to utf8
+ utfForm = UTF8FromDBCS(s, len);
+ }
+ }
+ if (!utfForm) { // iconv and DBCS failed so treat as Latin1
+ utfForm = UTF8FromLatin1(s, len);
+ }
+ pango_layout_set_text(layout, utfForm, len);
+ }
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+#ifdef PANGO_VERSION
+ PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0);
+#else
+ PangoLayoutLine *pll = pango_layout_get_line(layout,0);
+#endif
+ gdk_draw_layout_line(drawable, gc, xText, ybase, pll);
+ if (useGFree) {
+ g_free(utfForm);
+ } else {
+ delete []utfForm;
+ }
+ return;
+ }
+ // Draw text as a series of segments to avoid limitations in X servers
+ const int segmentLength = 1000;
+ bool draw8bit = true;
+ if (et != singleByte) {
+ GdkWChar wctext[maxLengthTextRun];
+ if (len >= maxLengthTextRun)
+ len = maxLengthTextRun-1;
+ int wclen;
+ if (et == UTF8) {
+ wclen = UTF16FromUTF8(s, len,
+ static_cast<wchar_t *>(static_cast<void *>(wctext)), maxLengthTextRun - 1);
+ } else { // dbcs, so convert using current locale
+ char sMeasure[maxLengthTextRun];
+ memcpy(sMeasure, s, len);
+ sMeasure[len] = '\0';
+ wclen = gdk_mbstowcs(
+ wctext, sMeasure, maxLengthTextRun - 1);
+ }
+ if (wclen > 0) {
+ draw8bit = false;
+ wctext[wclen] = L'\0';
+ GdkWChar *wcp = wctext;
+ while ((wclen > 0) && (xText < maxCoordinate)) {
+ int lenDraw = Platform::Minimum(wclen, segmentLength);
+ gdk_draw_text_wc(drawable, PFont(font_)->pfont, gc,
+ xText, ybase, wcp, lenDraw);
+ wclen -= lenDraw;
+ if (wclen > 0) { // Avoid next calculation if possible as may be expensive
+ xText += gdk_text_width_wc(PFont(font_)->pfont,
+ wcp, lenDraw);
+ }
+ wcp += lenDraw;
+ }
+ }
+ }
+ if (draw8bit) {
+ while ((len > 0) && (xText < maxCoordinate)) {
+ int lenDraw = Platform::Minimum(len, segmentLength);
+ gdk_draw_text(drawable, PFont(font_)->pfont, gc,
+ xText, ybase, s, lenDraw);
+ len -= lenDraw;
+ if (len > 0) { // Avoid next calculation if possible as may be expensive
+ xText += gdk_text_width(PFont(font_)->pfont, s, lenDraw);
+ }
+ s += lenDraw;
+ }
+ }
+ }
+}
+
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ FillRectangle(rc, back);
+ DrawTextBase(rc, font_, ybase, s, len, fore);
+}
+
+// On GTK+, exactly same as DrawTextNoClip
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ FillRectangle(rc, back);
+ DrawTextBase(rc, font_, ybase, s, len, fore);
+}
+
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore) {
+ // Avoid drawing spaces in transparent mode
+ for (int i=0;i<len;i++) {
+ if (s[i] != ' ') {
+ DrawTextBase(rc, font_, ybase, s, len, fore);
+ return;
+ }
+ }
+}
+
+class ClusterIterator {
+ PangoLayoutIter *iter;
+ PangoRectangle pos;
+ int lenPositions;
+public:
+ bool finished;
+ int positionStart;
+ int position;
+ int distance;
+ int curIndex;
+ ClusterIterator(PangoLayout *layout, int len) : lenPositions(len), finished(false),
+ positionStart(0), position(0), distance(0), curIndex(0) {
+ iter = pango_layout_get_iter(layout);
+ pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+ }
+ ~ClusterIterator() {
+ pango_layout_iter_free(iter);
+ }
+
+ void Next() {
+ positionStart = position;
+ if (pango_layout_iter_next_cluster(iter)) {
+ pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+ position = PANGO_PIXELS(pos.x);
+ curIndex = pango_layout_iter_get_index(iter);
+ } else {
+ finished = true;
+ position = PANGO_PIXELS(pos.x + pos.width);
+ curIndex = lenPositions;
+ }
+ distance = position - positionStart;
+ }
+};
+
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+ if (font_.GetID()) {
+ int totalWidth = 0;
+ const int lenPositions = len;
+ if (PFont(font_)->pfd) {
+ if (len == 1) {
+ int width = PFont(font_)->CharWidth(*s, et);
+ if (width) {
+ positions[0] = width;
+ return;
+ }
+ }
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+ if (et == UTF8) {
+ // Simple and direct as UTF-8 is native Pango encoding
+ int i = 0;
+ pango_layout_set_text(layout, s, len);
+ ClusterIterator iti(layout, lenPositions);
+ while (!iti.finished) {
+ iti.Next();
+ int places = iti.curIndex - i;
+ while (i < iti.curIndex) {
+ // Evenly distribute space among bytes of this cluster.
+ // Would be better to find number of characters and then
+ // divide evenly between characters with each byte of a character
+ // being at the same position.
+ positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places;
+ i++;
+ }
+ }
+ PLATFORM_ASSERT(i == lenPositions);
+ } else {
+ int positionsCalculated = 0;
+ if (et == dbcs) {
+ SetConverter(PFont(font_)->characterSet);
+ char *utfForm = UTF8FromIconv(conv, s, len);
+ if (utfForm) {
+ // Convert to UTF-8 so can ask Pango for widths, then
+ // Loop through UTF-8 and DBCS forms, taking account of different
+ // character byte lengths.
+ Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
+ pango_layout_set_text(layout, utfForm, strlen(utfForm));
+ int i = 0;
+ int clusterStart = 0;
+ ClusterIterator iti(layout, strlen(utfForm));
+ while (!iti.finished) {
+ iti.Next();
+ int clusterEnd = iti.curIndex;
+ int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
+ int place = 1;
+ while (clusterStart < clusterEnd) {
+ size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
+ while (lenChar--) {
+ positions[i++] = iti.position - (places - place) * iti.distance / places;
+ positionsCalculated++;
+ }
+ clusterStart += UTF8CharLength(utfForm+clusterStart);
+ place++;
+ }
+ }
+ delete []utfForm;
+ PLATFORM_ASSERT(i == lenPositions);
+ }
+ }
+ if (positionsCalculated < 1 ) {
+ // Either Latin1 or DBCS conversion failed so treat as Latin1.
+ bool useGFree = false;
+ SetConverter(PFont(font_)->characterSet);
+ char *utfForm = UTF8FromIconv(conv, s, len);
+ if (!utfForm) {
+ utfForm = UTF8FromLatin1(s, len);
+ }
+ pango_layout_set_text(layout, utfForm, len);
+ int i = 0;
+ int clusterStart = 0;
+ // Each Latin1 input character may take 1 or 2 bytes in UTF-8
+ // and groups of up to 3 may be represented as ligatures.
+ ClusterIterator iti(layout, strlen(utfForm));
+ while (!iti.finished) {
+ iti.Next();
+ int clusterEnd = iti.curIndex;
+ int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
+ PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
+ for (int charInLig=0; charInLig<ligatureLength; charInLig++) {
+ positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength;
+ }
+ clusterStart = clusterEnd;
+ }
+ if (useGFree) {
+ g_free(utfForm);
+ } else {
+ delete []utfForm;
+ }
+ PLATFORM_ASSERT(i == lenPositions);
+ }
+ }
+ if (len == 1) {
+ PFont(font_)->SetCharWidth(*s, positions[0], et);
+ }
+ return;
+ }
+ GdkFont *gf = PFont(font_)->pfont;
+ bool measure8bit = true;
+ if (et != singleByte) {
+ GdkWChar wctext[maxLengthTextRun];
+ if (len >= maxLengthTextRun)
+ len = maxLengthTextRun-1;
+ int wclen;
+ if (et == UTF8) {
+ wclen = UTF16FromUTF8(s, len,
+ static_cast<wchar_t *>(static_cast<void *>(wctext)), maxLengthTextRun - 1);
+ } else { // dbcsMode, so convert using current locale
+ char sDraw[maxLengthTextRun];
+ memcpy(sDraw, s, len);
+ sDraw[len] = '\0';
+ wclen = gdk_mbstowcs(
+ wctext, sDraw, maxLengthTextRun - 1);
+ }
+ if (wclen > 0) {
+ measure8bit = false;
+ wctext[wclen] = L'\0';
+ // Map widths back to utf-8 or DBCS input string
+ int i = 0;
+ for (int iU = 0; iU < wclen; iU++) {
+ int width = gdk_char_width_wc(gf, wctext[iU]);
+ totalWidth += width;
+ int lenChar;
+ if (et == UTF8) {
+ lenChar = UTF8Len(s[i]);
+ } else {
+ lenChar = mblen(s+i, MB_CUR_MAX);
+ if (lenChar < 0)
+ lenChar = 1;
+ }
+ while (lenChar--) {
+ positions[i++] = totalWidth;
+ }
+ }
+ while (i < len) { // In case of problems with lengths
+ positions[i++] = totalWidth;
+ }
+ }
+ }
+ if (measure8bit) {
+ // Either Latin1 or conversion failed so treat as Latin1.
+ for (int i = 0; i < len; i++) {
+ int width = gdk_char_width(gf, s[i]);
+ totalWidth += width;
+ positions[i] = totalWidth;
+ }
+ }
+ } else {
+ // No font so return an ascending range of values
+ for (int i = 0; i < len; i++) {
+ positions[i] = i + 1;
+ }
+ }
+}
+
+int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+ if (font_.GetID()) {
+ if (PFont(font_)->pfd) {
+ char *utfForm = 0;
+ pango_layout_set_font_description(layout, PFont(font_)->pfd);
+ PangoRectangle pos;
+ bool useGFree = false;
+ if (et == UTF8) {
+ pango_layout_set_text(layout, s, len);
+ } else {
+ if (et == dbcs) {
+ // Convert to utf8
+ utfForm = UTF8FromDBCS(s, len);
+ }
+ if (!utfForm) { // DBCS failed so treat as iconv
+ SetConverter(PFont(font_)->characterSet);
+ utfForm = UTF8FromIconv(conv, s, len);
+ }
+ if (!utfForm) { // g_locale_to_utf8 failed so treat as Latin1
+ utfForm = UTF8FromLatin1(s, len);
+ }
+ pango_layout_set_text(layout, utfForm, len);
+ }
+#ifdef PANGO_VERSION
+ PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0);
+#else
+ PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0);
+#endif
+ pango_layout_line_get_extents(pangoLine, NULL, &pos);
+ if (useGFree) {
+ g_free(utfForm);
+ } else {
+ delete []utfForm;
+ }
+ return PANGO_PIXELS(pos.width);
+ }
+ if (et == UTF8) {
+ GdkWChar wctext[maxLengthTextRun];
+ size_t wclen = UTF16FromUTF8(s, len, static_cast<wchar_t *>(static_cast<void *>(wctext)),
+ sizeof(wctext) / sizeof(GdkWChar) - 1);
+ wctext[wclen] = L'\0';
+ return gdk_text_width_wc(PFont(font_)->pfont, wctext, wclen);
+ } else {
+ return gdk_text_width(PFont(font_)->pfont, s, len);
+ }
+ } else {
+ return 1;
+ }
+}
+
+int SurfaceImpl::WidthChar(Font &font_, char ch) {
+ if (font_.GetID()) {
+ if (PFont(font_)->pfd) {
+ return WidthText(font_, &ch, 1);
+ }
+ return gdk_char_width(PFont(font_)->pfont, ch);
+ } else {
+ return 1;
+ }
+}
+
+// Three possible strategies for determining ascent and descent of font:
+// 1) Call gdk_string_extents with string containing all letters, numbers and punctuation.
+// 2) Use the ascent and descent fields of GdkFont.
+// 3) Call gdk_string_extents with string as 1 but also including accented capitals.
+// Smallest values given by 1 and largest by 3 with 2 in between.
+// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and
+// descenders but are mostly OK except for accented characters like Å which are
+// rarely used in code.
+
+// This string contains a good range of characters to test for size.
+//const char largeSizeString[] = "ÂÃÅÄ `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
+// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+#ifndef FAST_WAY
+const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+#endif
+
+int SurfaceImpl::Ascent(Font &font_) {
+ if (!(font_.GetID()))
+ return 1;
+#ifdef FAST_WAY
+ FontMutexLock();
+ int ascent = PFont(font_)->ascent;
+ if ((ascent == 0) && (PFont(font_)->pfd)) {
+ PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
+ PFont(font_)->pfd, pango_context_get_language(pcontext));
+ PFont(font_)->ascent =
+ PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
+ pango_font_metrics_unref(metrics);
+ ascent = PFont(font_)->ascent;
+ }
+ if ((ascent == 0) && (PFont(font_)->pfont)) {
+ ascent = PFont(font_)->pfont->ascent;
+ }
+ if (ascent == 0) {
+ ascent = 1;
+ }
+ FontMutexUnlock();
+ return ascent;
+#else
+
+ gint lbearing;
+ gint rbearing;
+ gint width;
+ gint ascent;
+ gint descent;
+
+ gdk_string_extents(PFont(font_)->pfont, sizeString,
+ &lbearing, &rbearing, &width, &ascent, &descent);
+ return ascent;
+#endif
+}
+
+int SurfaceImpl::Descent(Font &font_) {
+ if (!(font_.GetID()))
+ return 1;
+#ifdef FAST_WAY
+
+ if (PFont(font_)->pfd) {
+ PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
+ PFont(font_)->pfd, pango_context_get_language(pcontext));
+ int descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
+ pango_font_metrics_unref(metrics);
+ return descent;
+ }
+ return PFont(font_)->pfont->descent;
+#else
+
+ gint lbearing;
+ gint rbearing;
+ gint width;
+ gint ascent;
+ gint descent;
+
+ gdk_string_extents(PFont(font_)->pfont, sizeString,
+ &lbearing, &rbearing, &width, &ascent, &descent);
+ return descent;
+#endif
+}
+
+int SurfaceImpl::InternalLeading(Font &) {
+ return 0;
+}
+
+int SurfaceImpl::ExternalLeading(Font &) {
+ return 0;
+}
+
+int SurfaceImpl::Height(Font &font_) {
+ return Ascent(font_) + Descent(font_);
+}
+
+int SurfaceImpl::AverageCharWidth(Font &font_) {
+ return WidthChar(font_, 'n');
+}
+
+int SurfaceImpl::SetPalette(Palette *, bool) {
+ // Handled in palette allocation for GTK so this does nothing
+ return 0;
+}
+
+void SurfaceImpl::SetClip(PRectangle rc) {
+ GdkRectangle area = {rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top};
+ gdk_gc_set_clip_rectangle(gc, &area);
+}
+
+void SurfaceImpl::FlushCachedState() {}
+
+void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+ if (unicodeMode_)
+ et = UTF8;
+}
+
+void SurfaceImpl::SetDBCSMode(int codePage) {
+ if (codePage && (codePage != SC_CP_UTF8))
+ et = dbcs;
+}
+
+Surface *Surface::Allocate() {
+ return new SurfaceImpl;
+}
+
+Window::~Window() {}
+
+void Window::Destroy() {
+ if (wid)
+ gtk_widget_destroy(GTK_WIDGET(wid));
+ wid = 0;
+}
+
+bool Window::HasFocus() {
+ return GTK_WIDGET_HAS_FOCUS(wid);
+}
+
+PRectangle Window::GetPosition() {
+ // Before any size allocated pretend its 1000 wide so not scrolled
+ PRectangle rc(0, 0, 1000, 1000);
+ if (wid) {
+ rc.left = PWidget(wid)->allocation.x;
+ rc.top = PWidget(wid)->allocation.y;
+ if (PWidget(wid)->allocation.width > 20) {
+ rc.right = rc.left + PWidget(wid)->allocation.width;
+ rc.bottom = rc.top + PWidget(wid)->allocation.height;
+ }
+ }
+ return rc;
+}
+
+void Window::SetPosition(PRectangle rc) {
+ GtkAllocation alloc;
+ alloc.x = rc.left;
+ alloc.y = rc.top;
+ alloc.width = rc.Width();
+ alloc.height = rc.Height();
+ gtk_widget_size_allocate(PWidget(wid), &alloc);
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window relativeTo) {
+ int ox = 0;
+ int oy = 0;
+ gdk_window_get_origin(PWidget(relativeTo.wid)->window, &ox, &oy);
+ ox += rc.left;
+ if (ox < 0)
+ ox = 0;
+ oy += rc.top;
+ if (oy < 0)
+ oy = 0;
+
+ /* do some corrections to fit into screen */
+ int sizex = rc.right - rc.left;
+ int sizey = rc.bottom - rc.top;
+ int screenWidth = gdk_screen_width();
+ int screenHeight = gdk_screen_height();
+ if (sizex > screenWidth)
+ ox = 0; /* the best we can do */
+ else if (ox + sizex > screenWidth)
+ ox = screenWidth - sizex;
+ if (oy + sizey > screenHeight)
+ oy = screenHeight - sizey;
+
+ gtk_window_move(GTK_WINDOW(PWidget(wid)), ox, oy);
+
+ gtk_widget_set_usize(PWidget(wid), sizex, sizey);
+}
+
+PRectangle Window::GetClientPosition() {
+ // On GTK+, the client position is the window position
+ return GetPosition();
+}
+
+void Window::Show(bool show) {
+ if (show)
+ gtk_widget_show(PWidget(wid));
+}
+
+void Window::InvalidateAll() {
+ if (wid) {
+ gtk_widget_queue_draw(PWidget(wid));
+ }
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+ if (wid) {
+ gtk_widget_queue_draw_area(PWidget(wid),
+ rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top);
+ }
+}
+
+void Window::SetFont(Font &) {
+ // Can not be done generically but only needed for ListBox
+}
+
+void Window::SetCursor(Cursor curs) {
+ // We don't set the cursor to same value numerous times under gtk because
+ // it stores the cursor in the window once it's set
+ if (curs == cursorLast)
+ return;
+
+ cursorLast = curs;
+ GdkCursor *gdkCurs;
+ switch (curs) {
+ case cursorText:
+ gdkCurs = gdk_cursor_new(GDK_XTERM);
+ break;
+ case cursorArrow:
+ gdkCurs = gdk_cursor_new(GDK_LEFT_PTR);
+ break;
+ case cursorUp:
+ gdkCurs = gdk_cursor_new(GDK_CENTER_PTR);
+ break;
+ case cursorWait:
+ gdkCurs = gdk_cursor_new(GDK_WATCH);
+ break;
+ case cursorHand:
+ gdkCurs = gdk_cursor_new(GDK_HAND2);
+ break;
+ case cursorReverseArrow:
+ gdkCurs = gdk_cursor_new(GDK_RIGHT_PTR);
+ break;
+ default:
+ gdkCurs = gdk_cursor_new(GDK_LEFT_PTR);
+ cursorLast = cursorArrow;
+ break;
+ }
+
+ if (PWidget(wid)->window)
+ gdk_window_set_cursor(PWidget(wid)->window, gdkCurs);
+ gdk_cursor_destroy(gdkCurs);
+}
+
+void Window::SetTitle(const char *s) {
+ gtk_window_set_title(GTK_WINDOW(wid), s);
+}
+
+/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
+ gdk window coordinates */
+PRectangle Window::GetMonitorRect(Point pt) {
+ gint x_offset, y_offset;
+ pt = pt;
+
+ gdk_window_get_origin(PWidget(wid)->window, &x_offset, &y_offset);
+
+#if GTK_CHECK_VERSION(2,2,0)
+ // GTK+ 2.2+
+ {
+ GdkScreen* screen;
+ gint monitor_num;
+ GdkRectangle rect;
+
+ screen = gtk_widget_get_screen(PWidget(wid));
+ monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + x_offset, pt.y + y_offset);
+ gdk_screen_get_monitor_geometry(screen, monitor_num, &rect);
+ rect.x -= x_offset;
+ rect.y -= y_offset;
+ return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
+ }
+#else
+ return PRectangle(-x_offset, -y_offset, (-x_offset) + gdk_screen_width(),
+ (-y_offset) + gdk_screen_height());
+#endif
+}
+
+struct ListImage {
+ const char *xpm_data;
+ GdkPixbuf *pixbuf;
+};
+
+static void list_image_free(gpointer, gpointer value, gpointer) {
+ ListImage *list_image = (ListImage *) value;
+ if (list_image->pixbuf)
+ gdk_pixbuf_unref (list_image->pixbuf);
+ g_free(list_image);
+}
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+enum {
+ PIXBUF_COLUMN,
+ TEXT_COLUMN,
+ N_COLUMNS
+};
+
+class ListBoxX : public ListBox {
+ WindowID list;
+ WindowID scroller;
+ void *pixhash;
+ GtkCellRenderer* pixbuf_renderer;
+ XPMSet xset;
+ int desiredVisibleRows;
+ unsigned int maxItemCharacters;
+ unsigned int aveCharWidth;
+public:
+ CallBackAction doubleClickAction;
+ void *doubleClickActionData;
+
+ ListBoxX() : list(0), pixhash(NULL), pixbuf_renderer(0),
+ desiredVisibleRows(5), maxItemCharacters(0),
+ aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) {
+ }
+ virtual ~ListBoxX() {
+ if (pixhash) {
+ g_hash_table_foreach((GHashTable *) pixhash, list_image_free, NULL);
+ g_hash_table_destroy((GHashTable *) pixhash);
+ }
+ }
+ virtual void SetFont(Font &font);
+ 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);
+ virtual int Length();
+ virtual void Select(int n);
+ virtual int GetSelection();
+ virtual int Find(const char *prefix);
+ virtual void GetValue(int n, char *value, int len);
+ virtual void RegisterImage(int type, const char *xpm_data);
+ virtual void ClearRegisteredImages();
+ virtual void SetDoubleClickAction(CallBackAction action, void *data) {
+ doubleClickAction = action;
+ doubleClickActionData = data;
+ }
+ virtual void SetList(const char *listText, char separator, char typesep);
+};
+
+ListBox *ListBox::Allocate() {
+ ListBoxX *lb = new ListBoxX();
+ return lb;
+}
+
+static gboolean ButtonPress(GtkWidget *, GdkEventButton* ev, gpointer p) {
+ try {
+ ListBoxX* lb = reinterpret_cast<ListBoxX*>(p);
+ if (ev->type == GDK_2BUTTON_PRESS && lb->doubleClickAction != NULL) {
+ lb->doubleClickAction(lb->doubleClickActionData);
+ return TRUE;
+ }
+
+ } catch (...) {
+ // No pointer back to Scintilla to save status
+ }
+ return FALSE;
+}
+
+/* Change the active color to the selected color so the listbox uses the color
+scheme that it would use if it had the focus. */
+static void StyleSet(GtkWidget *w, GtkStyle*, void*) {
+ GtkStyle* style;
+
+ g_return_if_fail(w != NULL);
+
+ /* Copy the selected color to active. Note that the modify calls will cause
+ recursive calls to this function after the value is updated and w->style to
+ be set to a new object */
+ style = gtk_widget_get_style(w);
+ if (style == NULL)
+ return;
+ if (!gdk_color_equal(&style->base[GTK_STATE_SELECTED], &style->base[GTK_STATE_ACTIVE]))
+ gtk_widget_modify_base(w, GTK_STATE_ACTIVE, &style->base[GTK_STATE_SELECTED]);
+
+ style = gtk_widget_get_style(w);
+ if (style == NULL)
+ return;
+ if (!gdk_color_equal(&style->text[GTK_STATE_SELECTED], &style->text[GTK_STATE_ACTIVE]))
+ gtk_widget_modify_text(w, GTK_STATE_ACTIVE, &style->text[GTK_STATE_SELECTED]);
+}
+
+void ListBoxX::Create(Window &, int, Point, int, bool) {
+ wid = gtk_window_new(GTK_WINDOW_POPUP);
+
+ GtkWidget *frame = gtk_frame_new(NULL);
+ gtk_widget_show(frame);
+ gtk_container_add(GTK_CONTAINER(GetID()), frame);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 0);
+
+ scroller = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scroller), 0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(frame), PWidget(scroller));
+ gtk_widget_show(PWidget(scroller));
+
+ /* Tree and its model */
+ GtkListStore *store =
+ gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+
+ list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ g_signal_connect(G_OBJECT(list), "style-set", G_CALLBACK(StyleSet), NULL);
+
+ GtkTreeSelection *selection =
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
+ gtk_tree_view_set_reorderable(GTK_TREE_VIEW(list), FALSE);
+
+ /* Columns */
+ GtkTreeViewColumn *column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_title(column, "Autocomplete");
+
+ pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_renderer_set_fixed_size(pixbuf_renderer, 0, -1);
+ gtk_tree_view_column_pack_start(column, pixbuf_renderer, FALSE);
+ gtk_tree_view_column_add_attribute(column, pixbuf_renderer,
+ "pixbuf", PIXBUF_COLUMN);
+
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer), 1);
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "text", TEXT_COLUMN);
+
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(list), "fixed-height-mode"))
+ g_object_set(G_OBJECT(list), "fixed-height-mode", TRUE, NULL);
+
+ GtkWidget *wid = PWidget(list); // No code inside the G_OBJECT macro
+ gtk_container_add(GTK_CONTAINER(PWidget(scroller)), wid);
+ gtk_widget_show(wid);
+ g_signal_connect(G_OBJECT(wid), "button_press_event",
+ G_CALLBACK(ButtonPress), this);
+ gtk_widget_realize(PWidget(wid));
+}
+
+void ListBoxX::SetFont(Font &scint_font) {
+ // Only do for Pango font as there have been crashes for GDK fonts
+ if (Created() && PFont(scint_font)->pfd) {
+ // Current font is Pango font
+ gtk_widget_modify_font(PWidget(list), PFont(scint_font)->pfd);
+ }
+}
+
+void ListBoxX::SetAverageCharWidth(int width) {
+ aveCharWidth = width;
+}
+
+void ListBoxX::SetVisibleRows(int rows) {
+ desiredVisibleRows = rows;
+}
+
+int ListBoxX::GetVisibleRows() const {
+ return desiredVisibleRows;
+}
+
+PRectangle ListBoxX::GetDesiredRect() {
+ // Before any size allocated pretend its 100 wide so not scrolled
+ PRectangle rc(0, 0, 100, 100);
+ if (wid) {
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+
+ GtkRequisition req;
+ int height;
+
+ // First calculate height of the clist for our desired visible
+ // row count otherwise it tries to expand to the total # of rows
+ // Get cell height
+ int row_width=0;
+ int row_height=0;
+ GtkTreeViewColumn * column =
+ gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0);
+ gtk_tree_view_column_cell_get_size(column, NULL,
+ NULL, NULL, &row_width, &row_height);
+ int ythickness = PWidget(list)->style->ythickness;
+ height = (rows * row_height
+ + 2 * (ythickness
+ + GTK_CONTAINER(PWidget(list))->border_width + 1));
+ gtk_widget_set_usize(GTK_WIDGET(PWidget(list)), -1, height);
+
+ // Get the size of the scroller because we set usize on the window
+ gtk_widget_size_request(GTK_WIDGET(scroller), &req);
+ rc.right = req.width;
+ rc.bottom = req.height;
+
+ gtk_widget_set_usize(GTK_WIDGET(list), -1, -1);
+ int width = maxItemCharacters;
+ if (width < 12)
+ width = 12;
+ rc.right = width * (aveCharWidth + aveCharWidth / 3);
+ if (Length() > rows)
+ rc.right = rc.right + 16;
+ }
+ return rc;
+}
+
+int ListBoxX::CaretFromEdge() {
+ gint renderer_width, renderer_height;
+ gtk_cell_renderer_get_fixed_size(pixbuf_renderer, &renderer_width,
+ &renderer_height);
+ return 4 + renderer_width;
+}
+
+void ListBoxX::Clear() {
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
+ gtk_list_store_clear(GTK_LIST_STORE(model));
+ maxItemCharacters = 0;
+}
+
+static void init_pixmap(ListImage *list_image) {
+ const char *textForm = list_image->xpm_data;
+ const char * const * xpm_lineform = reinterpret_cast<const char * const *>(textForm);
+ const char **xpm_lineformfromtext = 0;
+ // The XPM data can be either in atext form as will be read from a file
+ // or in a line form (array of char *) as will be used for images defined in code.
+ // Test for text form and convert to line form
+ if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
+ // Test done is two parts to avoid possibility of overstepping the memory
+ // if memcmp implemented strangely. Must be 4 bytes at least at destination.
+ xpm_lineformfromtext = XPM::LinesFormFromTextForm(textForm);
+ xpm_lineform = xpm_lineformfromtext;
+ }
+
+ // Drop any existing pixmap/bitmap as data may have changed
+ if (list_image->pixbuf)
+ gdk_pixbuf_unref(list_image->pixbuf);
+ list_image->pixbuf =
+ gdk_pixbuf_new_from_xpm_data((const gchar**)xpm_lineform);
+ delete []xpm_lineformfromtext;
+}
+
+#define SPACING 5
+
+void ListBoxX::Append(char *s, int type) {
+ ListImage *list_image = NULL;
+ if ((type >= 0) && pixhash) {
+ list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash
+ , (gconstpointer) GINT_TO_POINTER(type));
+ }
+ GtkTreeIter iter;
+ GtkListStore *store =
+ GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
+ gtk_list_store_append(GTK_LIST_STORE(store), &iter);
+ if (list_image) {
+ if (NULL == list_image->pixbuf)
+ init_pixmap(list_image);
+ if (list_image->pixbuf) {
+ gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+ PIXBUF_COLUMN, list_image->pixbuf,
+ TEXT_COLUMN, s, -1);
+
+ gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf);
+ gint renderer_height, renderer_width;
+ gtk_cell_renderer_get_fixed_size(pixbuf_renderer,
+ &renderer_width, &renderer_height);
+ if (pixbuf_width > renderer_width)
+ gtk_cell_renderer_set_fixed_size(pixbuf_renderer,
+ pixbuf_width, -1);
+ } else {
+ gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+ TEXT_COLUMN, s, -1);
+ }
+ } else {
+ gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+ TEXT_COLUMN, s, -1);
+ }
+ size_t len = strlen(s);
+ if (maxItemCharacters < len)
+ maxItemCharacters = len;
+}
+
+int ListBoxX::Length() {
+ if (wid)
+ return gtk_tree_model_iter_n_children(gtk_tree_view_get_model
+ (GTK_TREE_VIEW(list)), NULL);
+ return 0;
+}
+
+void ListBoxX::Select(int n) {
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
+ GtkTreeSelection *selection =
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
+
+ if (n < 0) {
+ gtk_tree_selection_unselect_all(selection);
+ return;
+ }
+
+ bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE;
+ if (valid) {
+ gtk_tree_selection_select_iter(selection, &iter);
+
+ // Move the scrollbar to show the selection.
+ int total = Length();
+ GtkAdjustment *adj =
+ gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(list));
+ gfloat value = ((gfloat)n / total) * (adj->upper - adj->lower)
+ + adj->lower - adj->page_size / 2;
+
+ // Get cell height
+ int row_width;
+ int row_height;
+ GtkTreeViewColumn * column =
+ gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0);
+ gtk_tree_view_column_cell_get_size(column, NULL, NULL,
+ NULL, &row_width, &row_height);
+
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+ if (rows & 0x1) {
+ // Odd rows to display -- We are now in the middle.
+ // Align it so that we don't chop off rows.
+ value += (gfloat)row_height / 2.0;
+ }
+ // Clamp it.
+ value = (value < 0)? 0 : value;
+ value = (value > (adj->upper - adj->page_size))?
+ (adj->upper - adj->page_size) : value;
+
+ // Set it.
+ gtk_adjustment_set_value(adj, value);
+ } else {
+ gtk_tree_selection_unselect_all(selection);
+ }
+}
+
+int ListBoxX::GetSelection() {
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
+ int *indices = gtk_tree_path_get_indices(path);
+ // Don't free indices.
+ if (indices)
+ return indices[0];
+ }
+ return -1;
+}
+
+int ListBoxX::Find(const char *prefix) {
+ GtkTreeIter iter;
+ GtkTreeModel *model =
+ gtk_tree_view_get_model(GTK_TREE_VIEW(list));
+ bool valid = gtk_tree_model_get_iter_first(model, &iter) != FALSE;
+ int i = 0;
+ while(valid) {
+ gchar *s;
+ gtk_tree_model_get(model, &iter, TEXT_COLUMN, &s, -1);
+ if (s && (0 == strncmp(prefix, s, strlen(prefix)))) {
+ return i;
+ }
+ valid = gtk_tree_model_iter_next(model, &iter) != FALSE;
+ i++;
+ }
+ return -1;
+}
+
+void ListBoxX::GetValue(int n, char *value, int len) {
+ char *text = NULL;
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
+ bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE;
+ if (valid) {
+ gtk_tree_model_get(model, &iter, TEXT_COLUMN, &text, -1);
+ }
+ if (text && len > 0) {
+ strncpy(value, text, len);
+ value[len - 1] = '\0';
+ } else {
+ value[0] = '\0';
+ }
+}
+
+// g_return_if_fail causes unnecessary compiler warning in release compile.
+#ifdef _MSC_VER
+#pragma warning(disable: 4127)
+#endif
+
+void ListBoxX::RegisterImage(int type, const char *xpm_data) {
+ g_return_if_fail(xpm_data);
+
+ // Saved and use the saved copy so caller's copy can disappear.
+ xset.Add(type, xpm_data);
+ XPM *pxpm = xset.Get(type);
+ xpm_data = reinterpret_cast<const char *>(pxpm->InLinesForm());
+
+ if (!pixhash) {
+ pixhash = g_hash_table_new(g_direct_hash, g_direct_equal);
+ }
+ ListImage *list_image = (ListImage *) g_hash_table_lookup((GHashTable *) pixhash,
+ (gconstpointer) GINT_TO_POINTER(type));
+ if (list_image) {
+ // Drop icon already registered
+ if (list_image->pixbuf)
+ gdk_pixbuf_unref(list_image->pixbuf);
+ list_image->pixbuf = NULL;
+ list_image->xpm_data = xpm_data;
+ } else {
+ list_image = g_new0(ListImage, 1);
+ list_image->xpm_data = xpm_data;
+ g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type),
+ (gpointer) list_image);
+ }
+}
+
+void ListBoxX::ClearRegisteredImages() {
+ xset.Clear();
+}
+
+void ListBoxX::SetList(const char *listText, char separator, char typesep) {
+ Clear();
+ int count = strlen(listText) + 1;
+ char *words = new char[count];
+ if (words) {
+ memcpy(words, listText, count);
+ char *startword = words;
+ char *numword = NULL;
+ int i = 0;
+ for (; words[i]; i++) {
+ if (words[i] == separator) {
+ words[i] = '\0';
+ if (numword)
+ *numword = '\0';
+ 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';
+ Append(startword, numword?atoi(numword + 1):-1);
+ }
+ delete []words;
+ }
+}
+
+Menu::Menu() : mid(0) {}
+
+void Menu::CreatePopUp() {
+ Destroy();
+ mid = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
+}
+
+void Menu::Destroy() {
+ if (mid)
+ g_object_unref(G_OBJECT(mid));
+ mid = 0;
+}
+
+void Menu::Show(Point pt, Window &) {
+ int screenHeight = gdk_screen_height();
+ int screenWidth = gdk_screen_width();
+ GtkItemFactory *factory = reinterpret_cast<GtkItemFactory *>(mid);
+ GtkWidget *widget = gtk_item_factory_get_widget(factory, "<main>");
+ gtk_widget_show_all(widget);
+ GtkRequisition requisition;
+ gtk_widget_size_request(widget, &requisition);
+ if ((pt.x + requisition.width) > screenWidth) {
+ pt.x = screenWidth - requisition.width;
+ }
+ if ((pt.y + requisition.height) > screenHeight) {
+ pt.y = screenHeight - requisition.height;
+ }
+ gtk_item_factory_popup(factory, pt.x - 4, pt.y - 4, 3,
+ gtk_get_current_event_time());
+}
+
+ElapsedTime::ElapsedTime() {
+ GTimeVal curTime;
+ g_get_current_time(&curTime);
+ bigBit = curTime.tv_sec;
+ littleBit = curTime.tv_usec;
+}
+
+class DynamicLibraryImpl : public DynamicLibrary {
+protected:
+ GModule* m;
+public:
+ DynamicLibraryImpl(const char *modulePath) {
+ m = g_module_open(modulePath, G_MODULE_BIND_LAZY);
+ }
+
+ virtual ~DynamicLibraryImpl() {
+ if (m != NULL)
+ g_module_close(m);
+ }
+
+ // Use g_module_symbol to get a pointer to the relevant function.
+ virtual Function FindFunction(const char *name) {
+ if (m != NULL) {
+ gpointer fn_address = NULL;
+ gboolean status = g_module_symbol(m, name, &fn_address);
+ if (status)
+ return static_cast<Function>(fn_address);
+ else
+ return NULL;
+ } else
+ return NULL;
+ }
+
+ virtual bool IsValid() {
+ return m != NULL;
+ }
+};
+
+DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
+ return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
+}
+
+double ElapsedTime::Duration(bool reset) {
+ GTimeVal curTime;
+ g_get_current_time(&curTime);
+ long endBigBit = curTime.tv_sec;
+ long endLittleBit = curTime.tv_usec;
+ double result = 1000000.0 * (endBigBit - bigBit);
+ result += endLittleBit - littleBit;
+ result /= 1000000.0;
+ if (reset) {
+ bigBit = endBigBit;
+ littleBit = endLittleBit;
+ }
+ return result;
+}
+
+ColourDesired Platform::Chrome() {
+ return ColourDesired(0xe0, 0xe0, 0xe0);
+}
+
+ColourDesired Platform::ChromeHighlight() {
+ return ColourDesired(0xff, 0xff, 0xff);
+}
+
+const char *Platform::DefaultFont() {
+#ifdef G_OS_WIN32
+ return "Lucida Console";
+#else
+ return "!Sans";
+#endif
+}
+
+int Platform::DefaultFontSize() {
+#ifdef G_OS_WIN32
+ return 10;
+#else
+ return 12;
+#endif
+}
+
+unsigned int Platform::DoubleClickTime() {
+ return 500; // Half a second
+}
+
+bool Platform::MouseButtonBounce() {
+ return true;
+}
+
+void Platform::DebugDisplay(const char *s) {
+ fprintf(stderr, "%s", s);
+}
+
+bool Platform::IsKeyDown(int) {
+ // TODO: discover state of keys in GTK+/X
+ return false;
+}
+
+long Platform::SendScintilla(
+ WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
+ return scintilla_send_message(SCINTILLA(w), msg, wParam, lParam);
+}
+
+long Platform::SendScintillaPointer(
+ WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
+ return scintilla_send_message(SCINTILLA(w), msg, wParam,
+ reinterpret_cast<sptr_t>(lParam));
+}
+
+bool Platform::IsDBCSLeadByte(int codePage, char ch) {
+ // Byte ranges found in Wikipedia articles with relevant search strings in each case
+ unsigned char uch = static_cast<unsigned char>(ch);
+ switch (codePage) {
+ case 932:
+ // Shift_jis
+ return ((uch >= 0x81) && (uch <= 0x9F)) ||
+ ((uch >= 0xE0) && (uch <= 0xEF));
+ case 936:
+ // GBK
+ return (uch >= 0x81) && (uch <= 0xFE);
+ case 950:
+ // Big5
+ return (uch >= 0x81) && (uch <= 0xFE);
+ // Korean EUC-KR may be code page 949.
+ }
+ return false;
+}
+
+int Platform::DBCSCharLength(int codePage, const char *s) {
+ if (codePage == 932 || codePage == 936 || codePage == 950) {
+ return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1;
+ } else {
+ int bytes = mblen(s, MB_CUR_MAX);
+ if (bytes >= 1)
+ return bytes;
+ else
+ return 1;
+ }
+}
+
+int Platform::DBCSCharMaxLength() {
+ return MB_CUR_MAX;
+ //return 2;
+}
+
+// These are utility functions not really tied to a platform
+
+int Platform::Minimum(int a, int b) {
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int Platform::Maximum(int a, int b) {
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+//#define TRACE
+
+#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
+
+// Not supported for GTK+
+static bool assertionPopUps = true;
+
+bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
+ bool ret = assertionPopUps;
+ assertionPopUps = assertionPopUps_;
+ return ret;
+}
+
+void Platform::Assert(const char *c, const char *file, int line) {
+ char buffer[2000];
+ sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
+ strcat(buffer, "\r\n");
+ Platform::DebugDisplay(buffer);
+ abort();
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+ if (val > maxVal)
+ val = maxVal;
+ if (val < minVal)
+ val = minVal;
+ return val;
+}
+
+void Platform_Initialise() {
+ FontMutexAllocate();
+}
+
+void Platform_Finalise() {
+ FontMutexFree();
+}
diff --git a/scintilla/gtk/ScintillaGTK.cxx b/scintilla/gtk/ScintillaGTK.cxx
new file mode 100644
index 0000000..3865a6e
--- /dev/null
+++ b/scintilla/gtk/ScintillaGTK.cxx
@@ -0,0 +1,2536 @@
+// Scintilla source code edit control
+// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
+// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <new>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <string>
+#include <vector>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "Platform.h"
+
+#if PLAT_GTK_WIN32
+#include "windows.h"
+#endif
+
+#include "Scintilla.h"
+#include "ScintillaWidget.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "PropSetSimple.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "SVector.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "AutoComplete.h"
+#include "ViewStyle.h"
+#include "Decoration.h"
+#include "CharClassify.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+#include "UniConversion.h"
+
+#include "gtk/gtksignal.h"
+#include "gtk/gtkmarshal.h"
+#include "scintilla-marshal.h"
+
+#ifdef SCI_LEXER
+#include <glib.h>
+#include <gmodule.h>
+#include "ExternalLexer.h"
+#endif
+
+#include "Converter.h"
+
+#ifdef _MSC_VER
+// Constant conditional expressions are because of GTK+ headers
+#pragma warning(disable: 4127)
+// Ignore unreferenced local functions in GTK+ headers
+#pragma warning(disable: 4505)
+#endif
+
+#if GTK_CHECK_VERSION(2,6,0)
+#define USE_GTK_CLIPBOARD
+#endif
+
+#define OBJECT_CLASS GObjectClass
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+extern char *UTF8FromLatin1(const char *s, int &len);
+
+class ScintillaGTK : public ScintillaBase {
+ _ScintillaObject *sci;
+ Window wText;
+ Window scrollbarv;
+ Window scrollbarh;
+ GtkObject *adjustmentv;
+ GtkObject *adjustmenth;
+ int scrollBarWidth;
+ int scrollBarHeight;
+
+ // Because clipboard access is asynchronous, copyText is created by Copy
+#ifndef USE_GTK_CLIPBOARD
+ SelectionText copyText;
+#endif
+
+ SelectionText primary;
+
+ GdkEventButton evbtn;
+ bool capturedMouse;
+ bool dragWasDropped;
+ int lastKey;
+ int rectangularSelectionModifier;
+
+ GtkWidgetClass *parentClass;
+
+ static GdkAtom atomClipboard;
+ static GdkAtom atomUTF8;
+ static GdkAtom atomString;
+ static GdkAtom atomUriList;
+ static GdkAtom atomDROPFILES_DND;
+ GdkAtom atomSought;
+
+#if PLAT_GTK_WIN32
+ CLIPFORMAT cfColumnSelect;
+#endif
+
+ Window wPreedit;
+ Window wPreeditDraw;
+ GtkIMContext *im_context;
+
+ // Wheel mouse support
+ unsigned int linesPerScroll;
+ GTimeVal lastWheelMouseTime;
+ gint lastWheelMouseDirection;
+ gint wheelMouseIntensity;
+
+ GdkRegion *rgnUpdate;
+
+ // Private so ScintillaGTK objects can not be copied
+ ScintillaGTK(const ScintillaGTK &);
+ ScintillaGTK &operator=(const ScintillaGTK &);
+
+public:
+ ScintillaGTK(_ScintillaObject *sci_);
+ virtual ~ScintillaGTK();
+ static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
+private:
+ virtual void Initialise();
+ virtual void Finalise();
+ virtual void DisplayCursor(Window::Cursor c);
+ virtual bool DragThreshold(Point ptStart, Point ptNow);
+ virtual void StartDrag();
+ int TargetAsUTF8(char *text);
+ int EncodedFromUTF8(char *utf8, char *encoded);
+ virtual bool ValidCodePage(int codePage) const;
+public: // Public for scintilla_send_message
+ virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+private:
+ virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ virtual void SetTicking(bool on);
+ virtual bool SetIdle(bool on);
+ virtual void SetMouseCapture(bool on);
+ virtual bool HaveMouseCapture();
+ virtual bool PaintContains(PRectangle rc);
+ void FullPaint();
+ virtual PRectangle GetClientRectangle();
+ void SyncPaint(PRectangle rc);
+ virtual void ScrollText(int linesToMove);
+ virtual void SetVerticalScrollPos();
+ virtual void SetHorizontalScrollPos();
+ virtual bool ModifyScrollBars(int nMax, int nPage);
+ void ReconfigureScrollBars();
+ virtual void NotifyChange();
+ virtual void NotifyFocus(bool focus);
+ virtual void NotifyParent(SCNotification scn);
+ void NotifyKey(int key, int modifiers);
+ void NotifyURIDropped(const char *list);
+ const char *CharacterSetID() const;
+ virtual CaseFolder *CaseFolderForEncoding();
+ virtual std::string CaseMapString(const std::string &s, int caseMapping);
+ virtual int KeyDefault(int key, int modifiers);
+ virtual void CopyToClipboard(const SelectionText &selectedText);
+ virtual void Copy();
+ virtual void Paste();
+ virtual void CreateCallTipWindow(PRectangle rc);
+ virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+ bool OwnPrimarySelection();
+ virtual void ClaimSelection();
+ void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
+ void ReceivedSelection(GtkSelectionData *selection_data);
+ void ReceivedDrop(GtkSelectionData *selection_data);
+ static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
+#ifdef USE_GTK_CLIPBOARD
+ void StoreOnClipboard(SelectionText *clipText);
+ static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
+ static void ClipboardClearSelection(GtkClipboard* clip, void *data);
+#endif
+
+ void UnclaimSelection(GdkEventSelection *selection_event);
+ void Resize(int width, int height);
+
+ // Callback functions
+ void RealizeThis(GtkWidget *widget);
+ static void Realize(GtkWidget *widget);
+ void UnRealizeThis(GtkWidget *widget);
+ static void UnRealize(GtkWidget *widget);
+ void MapThis();
+ static void Map(GtkWidget *widget);
+ void UnMapThis();
+ static void UnMap(GtkWidget *widget);
+ static gint CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis);
+ gint FocusInThis(GtkWidget *widget);
+ static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
+ gint FocusOutThis(GtkWidget *widget);
+ static gint FocusOut(GtkWidget *widget, GdkEventFocus *event);
+ static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition);
+ static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation);
+ gint Expose(GtkWidget *widget, GdkEventExpose *ose);
+ static gint ExposeMain(GtkWidget *widget, GdkEventExpose *ose);
+ static void Draw(GtkWidget *widget, GdkRectangle *area);
+ void ForAll(GtkCallback callback, gpointer callback_data);
+ static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
+
+ static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
+ static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
+ gint PressThis(GdkEventButton *event);
+ static gint Press(GtkWidget *widget, GdkEventButton *event);
+ static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
+ static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
+ static gint Motion(GtkWidget *widget, GdkEventMotion *event);
+ gboolean KeyThis(GdkEventKey *event);
+ static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
+ static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
+ gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
+ static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
+ void CommitThis(char *str);
+ static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
+ void PreeditChangedThis();
+ static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
+ static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
+ static gint RealizeText(GtkWidget *widget, void*);
+ static void Destroy(GObject *object);
+ static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
+ guint time);
+ static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
+ guint info, guint time);
+ static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
+ static void DragBegin(GtkWidget *widget, GdkDragContext *context);
+ gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
+ static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, guint dragtime);
+ static void DragLeave(GtkWidget *widget, GdkDragContext *context,
+ guint time);
+ static void DragEnd(GtkWidget *widget, GdkDragContext *context);
+ static gboolean Drop(GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, guint time);
+ static void DragDataReceived(GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
+ static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
+ GtkSelectionData *selection_data, guint info, guint time);
+ static gint TimeOut(ScintillaGTK *sciThis);
+ static gboolean IdleCallback(ScintillaGTK *sciThis);
+ static gboolean StyleIdle(ScintillaGTK *sciThis);
+ virtual void QueueStyling(int upTo);
+ static void PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *widget);
+
+ gint ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
+ static gint ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
+
+ static gint ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
+ static gint PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);
+
+ static sptr_t DirectFunction(ScintillaGTK *sciThis,
+ unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+};
+
+enum {
+ COMMAND_SIGNAL,
+ NOTIFY_SIGNAL,
+ LAST_SIGNAL
+};
+
+static gint scintilla_signals[LAST_SIGNAL] = { 0 };
+
+enum {
+ TARGET_STRING,
+ TARGET_TEXT,
+ TARGET_COMPOUND_TEXT,
+ TARGET_UTF8_STRING,
+ TARGET_URI
+};
+
+GdkAtom ScintillaGTK::atomClipboard = 0;
+GdkAtom ScintillaGTK::atomUTF8 = 0;
+GdkAtom ScintillaGTK::atomString = 0;
+GdkAtom ScintillaGTK::atomUriList = 0;
+GdkAtom ScintillaGTK::atomDROPFILES_DND = 0;
+
+static const GtkTargetEntry clipboardCopyTargets[] = {
+ { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
+ { (gchar *) "STRING", 0, TARGET_STRING },
+};
+static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]);
+
+static const GtkTargetEntry clipboardPasteTargets[] = {
+ { (gchar *) "text/uri-list", 0, TARGET_URI },
+ { (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
+ { (gchar *) "STRING", 0, TARGET_STRING },
+};
+static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]);
+
+static GtkWidget *PWidget(Window &w) {
+ return reinterpret_cast<GtkWidget *>(w.GetID());
+}
+
+static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
+ ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(widget);
+ return reinterpret_cast<ScintillaGTK *>(scio->pscin);
+}
+
+ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
+ adjustmentv(0), adjustmenth(0),
+ scrollBarWidth(30), scrollBarHeight(30),
+ capturedMouse(false), dragWasDropped(false),
+ lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0),
+ im_context(NULL),
+ lastWheelMouseDirection(0),
+ wheelMouseIntensity(0),
+ rgnUpdate(0) {
+ sci = sci_;
+ wMain = GTK_WIDGET(sci);
+
+#if PLAT_GTK_WIN32
+ rectangularSelectionModifier = SCMOD_ALT;
+#else
+ rectangularSelectionModifier = SCMOD_CTRL;
+#endif
+
+#if PLAT_GTK_WIN32
+ // There does not seem to be a real standard for indicating that the clipboard
+ // contains a rectangular selection, so copy Developer Studio.
+ cfColumnSelect = static_cast<CLIPFORMAT>(
+ ::RegisterClipboardFormat("MSDEVColumnSelect"));
+
+ // Get intellimouse parameters when running on win32; otherwise use
+ // reasonable default
+#ifndef SPI_GETWHEELSCROLLLINES
+#define SPI_GETWHEELSCROLLLINES 104
+#endif
+ ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
+#else
+ linesPerScroll = 4;
+#endif
+ lastWheelMouseTime.tv_sec = 0;
+ lastWheelMouseTime.tv_usec = 0;
+
+ Initialise();
+}
+
+ScintillaGTK::~ScintillaGTK() {
+}
+
+void ScintillaGTK::RealizeThis(GtkWidget *widget) {
+ //Platform::DebugPrintf("ScintillaGTK::realize this\n");
+ GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+ GdkWindowAttr attrs;
+ attrs.window_type = GDK_WINDOW_CHILD;
+ attrs.x = widget->allocation.x;
+ attrs.y = widget->allocation.y;
+ attrs.width = widget->allocation.width;
+ attrs.height = widget->allocation.height;
+ attrs.wclass = GDK_INPUT_OUTPUT;
+ attrs.visual = gtk_widget_get_visual(widget);
+ attrs.colormap = gtk_widget_get_colormap(widget);
+ attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
+ GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
+ attrs.cursor = cursor;
+ widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
+ GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR);
+ gdk_window_set_user_data(widget->window, widget);
+ gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]);
+ gdk_window_show(widget->window);
+ gdk_cursor_destroy(cursor);
+ widget->style = gtk_style_attach(widget->style, widget->window);
+ wPreedit = gtk_window_new(GTK_WINDOW_POPUP);
+ wPreeditDraw = gtk_drawing_area_new();
+ GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro
+ g_signal_connect(G_OBJECT(predrw), "expose_event",
+ G_CALLBACK(ExposePreedit), this);
+ gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
+ gtk_widget_realize(PWidget(wPreedit));
+ gtk_widget_realize(predrw);
+ gtk_widget_show(predrw);
+
+ im_context = gtk_im_multicontext_new();
+ g_signal_connect(G_OBJECT(im_context), "commit",
+ G_CALLBACK(Commit), this);
+ g_signal_connect(G_OBJECT(im_context), "preedit_changed",
+ G_CALLBACK(PreeditChanged), this);
+ gtk_im_context_set_client_window(im_context, widget->window);
+ GtkWidget *widtxt = PWidget(wText); // // No code inside the G_OBJECT macro
+ g_signal_connect_after(G_OBJECT(widtxt), "style_set",
+ G_CALLBACK(ScintillaGTK::StyleSetText), NULL);
+ g_signal_connect_after(G_OBJECT(widtxt), "realize",
+ G_CALLBACK(ScintillaGTK::RealizeText), NULL);
+ gtk_widget_realize(widtxt);
+ gtk_widget_realize(PWidget(scrollbarv));
+ gtk_widget_realize(PWidget(scrollbarh));
+}
+
+void ScintillaGTK::Realize(GtkWidget *widget) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ sciThis->RealizeThis(widget);
+}
+
+void ScintillaGTK::UnRealizeThis(GtkWidget *widget) {
+ try {
+ if (GTK_WIDGET_MAPPED(widget)) {
+ gtk_widget_unmap(widget);
+ }
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
+ gtk_widget_unrealize(PWidget(wText));
+ gtk_widget_unrealize(PWidget(scrollbarv));
+ gtk_widget_unrealize(PWidget(scrollbarh));
+ gtk_widget_unrealize(PWidget(wPreedit));
+ gtk_widget_unrealize(PWidget(wPreeditDraw));
+ g_object_unref(im_context);
+ im_context = NULL;
+ if (GTK_WIDGET_CLASS(parentClass)->unrealize)
+ GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
+
+ Finalise();
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::UnRealize(GtkWidget *widget) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ sciThis->UnRealizeThis(widget);
+}
+
+static void MapWidget(GtkWidget *widget) {
+ if (widget &&
+ GTK_WIDGET_VISIBLE(widget) &&
+ !GTK_WIDGET_MAPPED(widget)) {
+ gtk_widget_map(widget);
+ }
+}
+
+void ScintillaGTK::MapThis() {
+ try {
+ //Platform::DebugPrintf("ScintillaGTK::map this\n");
+ GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED);
+ MapWidget(PWidget(wText));
+ MapWidget(PWidget(scrollbarh));
+ MapWidget(PWidget(scrollbarv));
+ wMain.SetCursor(Window::cursorArrow);
+ scrollbarv.SetCursor(Window::cursorArrow);
+ scrollbarh.SetCursor(Window::cursorArrow);
+ ChangeSize();
+ gdk_window_show(PWidget(wMain)->window);
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::Map(GtkWidget *widget) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ sciThis->MapThis();
+}
+
+void ScintillaGTK::UnMapThis() {
+ try {
+ //Platform::DebugPrintf("ScintillaGTK::unmap this\n");
+ GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED);
+ DropGraphics();
+ gdk_window_hide(PWidget(wMain)->window);
+ gtk_widget_unmap(PWidget(wText));
+ gtk_widget_unmap(PWidget(scrollbarh));
+ gtk_widget_unmap(PWidget(scrollbarv));
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::UnMap(GtkWidget *widget) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ sciThis->UnMapThis();
+}
+
+void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) {
+ try {
+ (*callback) (PWidget(wText), callback_data);
+ (*callback) (PWidget(scrollbarv), callback_data);
+ (*callback) (PWidget(scrollbarh), callback_data);
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) {
+ ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container);
+
+ if (callback != NULL && include_internals) {
+ sciThis->ForAll(callback, callback_data);
+ }
+}
+
+gint ScintillaGTK::CursorMoved(GtkWidget *, int xoffset, int yoffset, ScintillaGTK *sciThis) {
+ GdkRectangle area;
+ area.x = xoffset;
+ area.y = yoffset;
+ area.width = 1;
+ area.height = 1;
+ gtk_im_context_set_cursor_location(sciThis->im_context, &area);
+ return FALSE;
+}
+
+gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
+ try {
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+ SetFocusState(true);
+ if (im_context != NULL) {
+ gchar *str = NULL;
+ gint cursor_pos;
+
+ gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos);
+ if (PWidget(wPreedit) != NULL) {
+ if (strlen(str) > 0) {
+ gtk_widget_show(PWidget(wPreedit));
+ } else {
+ gtk_widget_hide(PWidget(wPreedit));
+ }
+ }
+ g_free(str);
+ gtk_im_context_focus_in(im_context);
+ }
+
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ return sciThis->FocusInThis(widget);
+}
+
+gint ScintillaGTK::FocusOutThis(GtkWidget *widget) {
+ try {
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+ SetFocusState(false);
+
+ if (PWidget(wPreedit) != NULL)
+ gtk_widget_hide(PWidget(wPreedit));
+ if (im_context != NULL)
+ gtk_im_context_focus_out(im_context);
+
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ return sciThis->FocusOutThis(widget);
+}
+
+void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ requisition->width = 600;
+ requisition->height = gdk_screen_height();
+ GtkRequisition child_requisition;
+ gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition);
+ gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition);
+}
+
+void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED(widget))
+ gdk_window_move_resize(widget->window,
+ widget->allocation.x,
+ widget->allocation.y,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ sciThis->Resize(allocation->width, allocation->height);
+
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::Initialise() {
+ //Platform::DebugPrintf("ScintillaGTK::Initialise\n");
+ parentClass = reinterpret_cast<GtkWidgetClass *>(
+ gtk_type_class(gtk_container_get_type()));
+
+ GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS);
+ GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE);
+ gtk_widget_set_events(PWidget(wMain),
+ GDK_EXPOSURE_MASK
+ | GDK_STRUCTURE_MASK
+ | GDK_KEY_PRESS_MASK
+ | GDK_KEY_RELEASE_MASK
+ | GDK_FOCUS_CHANGE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+
+ wText = gtk_drawing_area_new();
+ gtk_widget_set_parent(PWidget(wText), PWidget(wMain));
+ GtkWidget *widtxt = PWidget(wText); // No code inside the G_OBJECT macro
+ gtk_widget_show(widtxt);
+ g_signal_connect(G_OBJECT(widtxt), "expose_event",
+ G_CALLBACK(ScintillaGTK::ExposeText), this);
+ gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
+ // Avoid background drawing flash
+ gtk_widget_set_double_buffered(widtxt, FALSE);
+ gtk_drawing_area_size(GTK_DRAWING_AREA(widtxt),
+ 100,100);
+ adjustmentv = gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0);
+ scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv));
+ GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS);
+ g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
+ G_CALLBACK(ScrollSignal), this);
+ gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain));
+ gtk_widget_show(PWidget(scrollbarv));
+
+ adjustmenth = gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0);
+ scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth));
+ GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS);
+ g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
+ G_CALLBACK(ScrollHSignal), this);
+ gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain));
+ gtk_widget_show(PWidget(scrollbarh));
+
+ gtk_widget_grab_focus(PWidget(wMain));
+
+ gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
+ clipboardCopyTargets, nClipboardCopyTargets);
+
+#ifndef USE_GTK_CLIPBOARD
+ gtk_selection_add_targets(GTK_WIDGET(PWidget(wMain)), atomClipboard,
+ clipboardPasteTargets, nClipboardPasteTargets);
+#endif
+
+ gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)),
+ GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets,
+ static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
+
+ // Set caret period based on GTK settings
+ gboolean blinkOn = false;
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(
+ G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
+ g_object_get(G_OBJECT(
+ gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL);
+ }
+ if (blinkOn &&
+ g_object_class_find_property(G_OBJECT_GET_CLASS(
+ G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
+ gint value;
+ g_object_get(G_OBJECT(
+ gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL);
+ caret.period = gint(value / 1.75);
+ } else {
+ caret.period = 0;
+ }
+
+ SetTicking(true);
+}
+
+void ScintillaGTK::Finalise() {
+ SetTicking(false);
+ ScintillaBase::Finalise();
+}
+
+void ScintillaGTK::DisplayCursor(Window::Cursor c) {
+ if (cursorMode == SC_CURSORNORMAL)
+ wText.SetCursor(c);
+ else
+ wText.SetCursor(static_cast<Window::Cursor>(cursorMode));
+}
+
+bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) {
+ return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
+ ptStart.x, ptStart.y, ptNow.x, ptNow.y);
+}
+
+void ScintillaGTK::StartDrag() {
+ dragWasDropped = false;
+ inDragDrop = ddDragging;
+ GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets);
+ gtk_drag_begin(GTK_WIDGET(PWidget(wMain)),
+ tl,
+ static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE),
+ evbtn.button,
+ reinterpret_cast<GdkEvent *>(&evbtn));
+}
+
+static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
+ const char *charSetSource, bool transliterations, bool silent=false) {
+ // s is not const because of different versions of iconv disagreeing about const
+ *lenResult = 0;
+ char *destForm = 0;
+ Converter conv(charSetDest, charSetSource, transliterations);
+ if (conv) {
+ destForm = new char[len*3+1];
+ char *pin = s;
+ size_t inLeft = len;
+ char *pout = destForm;
+ size_t outLeft = len*3+1;
+ size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
+ if (conversions == ((size_t)(-1))) {
+ if (!silent)
+ fprintf(stderr, "iconv %s->%s failed for %s\n",
+ charSetSource, charSetDest, static_cast<char *>(s));
+ delete []destForm;
+ destForm = 0;
+ } else {
+//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
+ *pout = '\0';
+ *lenResult = pout - destForm;
+ }
+ } else {
+fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
+ }
+ if (!destForm) {
+ destForm = new char[1];
+ destForm[0] = '\0';
+ *lenResult = 0;
+ }
+ return destForm;
+}
+
+// Returns the target converted to UTF8.
+// Return the length in bytes.
+int ScintillaGTK::TargetAsUTF8(char *text) {
+ int targetLength = targetEnd - targetStart;
+ if (IsUnicodeMode()) {
+ if (text) {
+ pdoc->GetCharRange(text, targetStart, targetLength);
+ }
+ } else {
+ // Need to convert
+ const char *charSetBuffer = CharacterSetID();
+ if (*charSetBuffer) {
+//~ fprintf(stderr, "AsUTF8 %s %d %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
+ char *s = new char[targetLength];
+ if (s) {
+ pdoc->GetCharRange(s, targetStart, targetLength);
+//~ fprintf(stderr, " \"%s\"\n", s);
+ if (text) {
+ char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
+ memcpy(text, tmputf, targetLength);
+ delete []tmputf;
+//~ fprintf(stderr, " \"%s\"\n", text);
+ }
+ delete []s;
+ }
+ } else {
+ if (text) {
+ pdoc->GetCharRange(text, targetStart, targetLength);
+ }
+ }
+ }
+//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
+ return targetLength;
+}
+
+// Translates a nul terminated UTF8 string into the document encoding.
+// Return the length of the result in bytes.
+int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
+ int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8);
+ if (IsUnicodeMode()) {
+ if (encoded) {
+ memcpy(encoded, utf8, inputLength);
+ }
+ return inputLength;
+ } else {
+ // Need to convert
+ const char *charSetBuffer = CharacterSetID();
+ if (*charSetBuffer) {
+ int outLength = 0;
+ char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
+ if (tmpEncoded) {
+ if (encoded) {
+ memcpy(encoded, tmpEncoded, outLength);
+ }
+ delete []tmpEncoded;
+ }
+ return outLength;
+ } else {
+ if (encoded) {
+ memcpy(encoded, utf8, inputLength);
+ }
+ return inputLength;
+ }
+ }
+ // Fail
+ return 0;
+}
+
+bool ScintillaGTK::ValidCodePage(int codePage) const {
+ return codePage == 0
+ || codePage == SC_CP_UTF8
+ || codePage == 932
+ || codePage == 936
+ || codePage == 950
+ || codePage == SC_CP_DBCS;
+}
+
+sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ try {
+ switch (iMessage) {
+
+ case SCI_GRABFOCUS:
+ gtk_widget_grab_focus(PWidget(wMain));
+ break;
+
+ case SCI_GETDIRECTFUNCTION:
+ return reinterpret_cast<sptr_t>(DirectFunction);
+
+ case SCI_GETDIRECTPOINTER:
+ return reinterpret_cast<sptr_t>(this);
+
+#ifdef SCI_LEXER
+ case SCI_LOADLEXERLIBRARY:
+ LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
+ break;
+#endif
+ case SCI_TARGETASUTF8:
+ return TargetAsUTF8(reinterpret_cast<char*>(lParam));
+
+ case SCI_ENCODEDFROMUTF8:
+ return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
+ reinterpret_cast<char*>(lParam));
+
+ case SCI_SETRECTANGULARSELECTIONMODIFIER:
+ rectangularSelectionModifier = wParam;
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONMODIFIER:
+ return rectangularSelectionModifier;
+
+ default:
+ return ScintillaBase::WndProc(iMessage, wParam, lParam);
+ }
+ } catch (std::bad_alloc&) {
+ errorStatus = SC_STATUS_BADALLOC;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return 0l;
+}
+
+sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
+ return 0;
+}
+
+void ScintillaGTK::SetTicking(bool on) {
+ if (timer.ticking != on) {
+ timer.ticking = on;
+ if (timer.ticking) {
+ timer.tickerID = reinterpret_cast<TickerID>(gtk_timeout_add(timer.tickSize, (GtkFunction)TimeOut, this));
+ } else {
+ gtk_timeout_remove(GPOINTER_TO_UINT(timer.tickerID));
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+bool ScintillaGTK::SetIdle(bool on) {
+ if (on) {
+ // Start idler, if it's not running.
+ if (!idler.state) {
+ idler.state = true;
+ idler.idlerID = reinterpret_cast<IdlerID>(
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
+ reinterpret_cast<GSourceFunc>(IdleCallback), this, NULL));
+ }
+ } else {
+ // Stop idler, if it's running
+ if (idler.state) {
+ idler.state = false;
+ g_source_remove(GPOINTER_TO_UINT(idler.idlerID));
+ }
+ }
+ return true;
+}
+
+void ScintillaGTK::SetMouseCapture(bool on) {
+ if (mouseDownCaptures) {
+ if (on) {
+ gtk_grab_add(GTK_WIDGET(PWidget(wMain)));
+ } else {
+ gtk_grab_remove(GTK_WIDGET(PWidget(wMain)));
+ }
+ }
+ capturedMouse = on;
+}
+
+bool ScintillaGTK::HaveMouseCapture() {
+ return capturedMouse;
+}
+
+bool ScintillaGTK::PaintContains(PRectangle rc) {
+ bool contains = true;
+ if (paintState == painting) {
+ if (!rcPaint.Contains(rc)) {
+ contains = false;
+ } else if (rgnUpdate) {
+ GdkRectangle grc = {rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top};
+ if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) {
+ contains = false;
+ }
+ }
+ }
+ return contains;
+}
+
+// Redraw all of text area. This paint will not be abandoned.
+void ScintillaGTK::FullPaint() {
+ wText.InvalidateAll();
+}
+
+PRectangle ScintillaGTK::GetClientRectangle() {
+ PRectangle rc = wMain.GetClientPosition();
+ if (verticalScrollBarVisible)
+ rc.right -= scrollBarWidth;
+ if (horizontalScrollBarVisible && (wrapState == eWrapNone))
+ rc.bottom -= scrollBarHeight;
+ // Move to origin
+ rc.right -= rc.left;
+ rc.bottom -= rc.top;
+ rc.left = 0;
+ rc.top = 0;
+ return rc;
+}
+
+// Synchronously paint a rectangle of the window.
+void ScintillaGTK::SyncPaint(PRectangle rc) {
+ paintState = painting;
+ rcPaint = rc;
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+ if ((PWidget(wText))->window) {
+ Surface *sw = Surface::Allocate();
+ if (sw) {
+ sw->Init(PWidget(wText)->window, PWidget(wText));
+ Paint(sw, rc);
+ sw->Release();
+ delete sw;
+ }
+ }
+ if (paintState == paintAbandoned) {
+ // Painting area was insufficient to cover new styling or brace highlight positions
+ FullPaint();
+ }
+ paintState = notPainting;
+}
+
+void ScintillaGTK::ScrollText(int linesToMove) {
+ int diff = vs.lineHeight * -linesToMove;
+ //Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
+ // rc.left, rc.top, rc.right, rc.bottom);
+ GtkWidget *wi = PWidget(wText);
+
+ gdk_window_scroll(wi->window, 0, -diff);
+ gdk_window_process_updates(wi->window, FALSE);
+}
+
+void ScintillaGTK::SetVerticalScrollPos() {
+ DwellEnd(true);
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine);
+}
+
+void ScintillaGTK::SetHorizontalScrollPos() {
+ DwellEnd(true);
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2);
+}
+
+bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) {
+ bool modified = false;
+ int pageScroll = LinesToScroll();
+
+ if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) ||
+ GTK_ADJUSTMENT(adjustmentv)->page_size != nPage ||
+ GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) {
+ GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1;
+ GTK_ADJUSTMENT(adjustmentv)->page_size = nPage;
+ GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll;
+ gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
+ modified = true;
+ }
+
+ PRectangle rcText = GetTextRectangle();
+ int horizEndPreferred = scrollWidth;
+ if (horizEndPreferred < 0)
+ horizEndPreferred = 0;
+ unsigned int pageWidth = rcText.Width();
+ unsigned int pageIncrement = pageWidth / 3;
+ unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
+ if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred ||
+ GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth ||
+ GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement ||
+ GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) {
+ GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred;
+ GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth;
+ GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth;
+ GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement;
+ gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
+ modified = true;
+ }
+ return modified;
+}
+
+void ScintillaGTK::ReconfigureScrollBars() {
+ PRectangle rc = wMain.GetClientPosition();
+ Resize(rc.Width(), rc.Height());
+}
+
+void ScintillaGTK::NotifyChange() {
+ g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
+ Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
+}
+
+void ScintillaGTK::NotifyFocus(bool focus) {
+ g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
+ Platform::LongFromTwoShorts
+ (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
+}
+
+void ScintillaGTK::NotifyParent(SCNotification scn) {
+ scn.nmhdr.hwndFrom = PWidget(wMain);
+ scn.nmhdr.idFrom = GetCtrlID();
+ g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
+ GetCtrlID(), &scn);
+}
+
+void ScintillaGTK::NotifyKey(int key, int modifiers) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_KEY;
+ scn.ch = key;
+ scn.modifiers = modifiers;
+
+ NotifyParent(scn);
+}
+
+void ScintillaGTK::NotifyURIDropped(const char *list) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_URIDROPPED;
+ scn.text = list;
+
+ NotifyParent(scn);
+}
+
+const char *CharacterSetID(int characterSet);
+
+const char *ScintillaGTK::CharacterSetID() const {
+ return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
+}
+
+class CaseFolderUTF8 : public CaseFolderTable {
+public:
+ CaseFolderUTF8() {
+ StandardASCII();
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if ((lenMixed == 1) && (sizeFolded > 0)) {
+ folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
+ return 1;
+ } else {
+ gchar *mapped = g_utf8_casefold(mixed, lenMixed);
+ size_t lenMapped = strlen(mapped);
+ if (lenMapped < sizeFolded) {
+ memcpy(folded, mapped, lenMapped);
+ } else {
+ lenMapped = 0;
+ }
+ g_free(mapped);
+ return lenMapped;
+ }
+ }
+};
+
+CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
+ if (pdoc->dbcsCodePage == SC_CP_UTF8) {
+ return new CaseFolderUTF8();
+ } else {
+ CaseFolderTable *pcf = new CaseFolderTable();
+ const char *charSetBuffer = CharacterSetID();
+ if ((pdoc->dbcsCodePage == 0) && charSetBuffer) {
+ pcf->StandardASCII();
+ // Only for single byte encodings
+ for (int i=0x80; i<0x100; i++) {
+ char sCharacter[2] = "A";
+ sCharacter[0] = i;
+ int convertedLength = 1;
+ const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1,
+ "UTF-8", charSetBuffer, false);
+ if (sUTF8) {
+ gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
+ if (mapped) {
+ int mappedLength = strlen(mapped);
+ const char *mappedBack = ConvertText(&mappedLength, mapped,
+ mappedLength, charSetBuffer, "UTF-8", false, true);
+ if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
+ pcf->SetTranslation(sCharacter[0], mappedBack[0]);
+ }
+ delete []mappedBack;
+ g_free(mapped);
+ }
+ }
+ delete []sUTF8;
+ }
+ }
+ return pcf;
+ }
+}
+
+std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
+ if (s.size() == 0)
+ return std::string();
+
+ if (caseMapping == cmSame)
+ return s;
+
+ const char *needsFree1 = 0; // Must be freed with delete []
+ const char *charSetBuffer = CharacterSetID();
+ const char *sUTF8 = s.c_str();
+ int rangeBytes = s.size();
+
+ int convertedLength = rangeBytes;
+ // Change text to UTF-8
+ if (!IsUnicodeMode()) {
+ // Need to convert
+ if (*charSetBuffer) {
+ sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
+ "UTF-8", charSetBuffer, false);
+ needsFree1 = sUTF8;
+ }
+ }
+ gchar *mapped; // Must be freed with g_free
+ if (caseMapping == cmUpper) {
+ mapped = g_utf8_strup(sUTF8, convertedLength);
+ } else {
+ mapped = g_utf8_strdown(sUTF8, convertedLength);
+ }
+ int mappedLength = strlen(mapped);
+ char *mappedBack = mapped;
+
+ char *needsFree2 = 0; // Must be freed with delete []
+ if (!IsUnicodeMode()) {
+ if (*charSetBuffer) {
+ mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
+ needsFree2 = mappedBack;
+ }
+ }
+
+ std::string ret(mappedBack, mappedLength);
+ g_free(mapped);
+ delete []needsFree1;
+ delete []needsFree2;
+ return ret;
+}
+
+int ScintillaGTK::KeyDefault(int key, int modifiers) {
+ if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT)) {
+ if (key < 256) {
+ NotifyKey(key, modifiers);
+ return 0;
+ } else {
+ // Pass up to container in case it is an accelerator
+ NotifyKey(key, modifiers);
+ return 0;
+ }
+ } else {
+ // Pass up to container in case it is an accelerator
+ NotifyKey(key, modifiers);
+ return 0;
+ }
+ //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
+}
+
+void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
+#ifndef USE_GTK_CLIPBOARD
+ copyText.Copy(selectedText);
+ gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
+ atomClipboard,
+ GDK_CURRENT_TIME);
+#else
+ SelectionText *clipText = new SelectionText();
+ clipText->Copy(selectedText);
+ StoreOnClipboard(clipText);
+#endif
+}
+
+void ScintillaGTK::Copy() {
+ if (!sel.Empty()) {
+#ifndef USE_GTK_CLIPBOARD
+ CopySelectionRange(&copyText);
+ gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
+ atomClipboard,
+ GDK_CURRENT_TIME);
+#else
+ SelectionText *clipText = new SelectionText();
+ CopySelectionRange(clipText);
+ StoreOnClipboard(clipText);
+#endif
+#if PLAT_GTK_WIN32
+ if (sel.IsRectangular()) {
+ ::OpenClipboard(NULL);
+ ::SetClipboardData(cfColumnSelect, 0);
+ ::CloseClipboard();
+ }
+#endif
+ }
+}
+
+void ScintillaGTK::Paste() {
+ atomSought = atomUTF8;
+ gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
+ atomClipboard, atomSought, GDK_CURRENT_TIME);
+}
+
+void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
+ if (!ct.wCallTip.Created()) {
+ ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
+ ct.wDraw = gtk_drawing_area_new();
+ GtkWidget *widcdrw = PWidget(ct.wDraw); // // No code inside the G_OBJECT macro
+ gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
+ g_signal_connect(G_OBJECT(widcdrw), "expose_event",
+ G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
+ g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
+ G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
+ gtk_widget_set_events(widcdrw,
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
+ }
+ gtk_drawing_area_size(GTK_DRAWING_AREA(PWidget(ct.wDraw)),
+ rc.Width(), rc.Height());
+ ct.wDraw.Show();
+ if (PWidget(ct.wCallTip)->window) {
+ gdk_window_resize(PWidget(ct.wCallTip)->window, rc.Width(), rc.Height());
+ }
+}
+
+void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
+ char fulllabel[200];
+ strcpy(fulllabel, "/");
+ strcat(fulllabel, label);
+ GtkItemFactoryCallback menuSig = GtkItemFactoryCallback(PopUpCB);
+ GtkItemFactoryEntry itemEntry = {
+ fulllabel, NULL,
+ menuSig,
+ cmd,
+ const_cast<gchar *>(label[0] ? "<Item>" : "<Separator>"),
+ NULL
+ };
+ gtk_item_factory_create_item(GTK_ITEM_FACTORY(popup.GetID()),
+ &itemEntry, this, 1);
+ if (cmd) {
+ GtkWidget *item = gtk_item_factory_get_widget_by_action(
+ reinterpret_cast<GtkItemFactory *>(popup.GetID()), cmd);
+ if (item)
+ gtk_widget_set_sensitive(item, enabled);
+ }
+}
+
+bool ScintillaGTK::OwnPrimarySelection() {
+ return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
+ == GTK_WIDGET(PWidget(wMain))->window) &&
+ (GTK_WIDGET(PWidget(wMain))->window != NULL));
+}
+
+void ScintillaGTK::ClaimSelection() {
+ // X Windows has a 'primary selection' as well as the clipboard.
+ // Whenever the user selects some text, we become the primary selection
+ if (!sel.Empty() && GTK_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
+ primarySelection = true;
+ gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
+ GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
+ primary.Free();
+ } else if (OwnPrimarySelection()) {
+ primarySelection = true;
+ if (primary.s == NULL)
+ gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
+ } else {
+ primarySelection = false;
+ primary.Free();
+ }
+}
+
+// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
+void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
+ char *data = reinterpret_cast<char *>(selectionData->data);
+ int len = selectionData->length;
+ GdkAtom selectionTypeData = selectionData->type;
+
+ // Return empty string if selection is not a string
+ if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
+ char *empty = new char[1];
+ empty[0] = '\0';
+ selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
+ return;
+ }
+
+ // Check for "\n\0" ending to string indicating that selection is rectangular
+ bool isRectangular;
+#if PLAT_GTK_WIN32
+ isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
+#else
+ isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
+ if (isRectangular)
+ len--; // Forget the extra '\0'
+#endif
+
+ char *dest;
+ if (selectionTypeData == GDK_TARGET_STRING) {
+ dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
+ if (IsUnicodeMode()) {
+ // Unknown encoding so assume in Latin1
+ char *destPrevious = dest;
+ dest = UTF8FromLatin1(dest, len);
+ selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
+ delete []destPrevious;
+ } else {
+ // Assume buffer is in same encoding as selection
+ selText.Set(dest, len, pdoc->dbcsCodePage,
+ vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
+ }
+ } else { // UTF-8
+ dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
+ selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
+ const char *charSetBuffer = CharacterSetID();
+ if (!IsUnicodeMode() && *charSetBuffer) {
+ // Convert to locale
+ dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
+ selText.Set(dest, len, pdoc->dbcsCodePage,
+ vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
+ }
+ }
+}
+
+void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
+ try {
+ if ((selection_data->selection == atomClipboard) ||
+ (selection_data->selection == GDK_SELECTION_PRIMARY)) {
+ if ((atomSought == atomUTF8) && (selection_data->length <= 0)) {
+ atomSought = atomString;
+ gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
+ selection_data->selection, atomSought, GDK_CURRENT_TIME);
+ } else if ((selection_data->length > 0) &&
+ ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8))) {
+ SelectionText selText;
+ GetGtkSelectionText(selection_data, selText);
+
+ UndoGroup ug(pdoc);
+ if (selection_data->selection != GDK_SELECTION_PRIMARY) {
+ ClearSelection();
+ }
+ SelectionPosition selStart = sel.IsRectangular() ?
+ sel.Rectangular().Start() :
+ sel.Range(sel.Main()).Start();
+
+ if (selText.rectangular) {
+ PasteRectangular(selStart, selText.s, selText.len);
+ } else {
+ InsertPaste(selStart, selText.s, selText.len);
+ }
+ EnsureCaretVisible();
+ }
+ }
+// else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
+// (int)(atomUTF8));
+ Redraw();
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
+ dragWasDropped = true;
+ if (selection_data->type == atomUriList || selection_data->type == atomDROPFILES_DND) {
+ char *ptr = new char[selection_data->length + 1];
+ ptr[selection_data->length] = '\0';
+ memcpy(ptr, selection_data->data, selection_data->length);
+ NotifyURIDropped(ptr);
+ delete []ptr;
+ } else if ((selection_data->type == GDK_TARGET_STRING) || (selection_data->type == atomUTF8)) {
+ if (selection_data->length > 0) {
+ SelectionText selText;
+ GetGtkSelectionText(selection_data, selText);
+ DropAt(posDrop, selText.s, false, selText.rectangular);
+ }
+ } else if (selection_data->length > 0) {
+ //~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast<void *>(selection_data->type));
+ }
+ Redraw();
+}
+
+
+
+void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
+#if PLAT_GTK_WIN32
+ // GDK on Win32 expands any \n into \r\n, so make a copy of
+ // the clip text now with newlines converted to \n. Use { } to hide symbols
+ // from code below
+ SelectionText *newline_normalized = NULL;
+ {
+ int tmpstr_len;
+ char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
+ newline_normalized = new SelectionText();
+ newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
+ text = newline_normalized;
+ }
+#endif
+
+ // Convert text to utf8 if it isn't already
+ SelectionText *converted = 0;
+ if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
+ const char *charSet = ::CharacterSetID(text->characterSet);
+ if (*charSet) {
+ int new_len;
+ char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
+ converted = new SelectionText();
+ converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
+ text = converted;
+ }
+ }
+
+ // Here is a somewhat evil kludge.
+ // As I can not work out how to store data on the clipboard in multiple formats
+ // and need some way to mark the clipping as being stream or rectangular,
+ // the terminating \0 is included in the length for rectangular clippings.
+ // All other tested aplications behave benignly by ignoring the \0.
+ // The #if is here because on Windows cfColumnSelect clip entry is used
+ // instead as standard indicator of rectangularness (so no need to kludge)
+ const char *textData = text->s ? text->s : "";
+ int len = strlen(textData);
+#if PLAT_GTK_WIN32 == 0
+ if (text->rectangular)
+ len++;
+#endif
+
+ if (info == TARGET_UTF8_STRING) {
+ gtk_selection_data_set_text(selection_data, textData, len);
+ } else {
+ gtk_selection_data_set(selection_data,
+ static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
+ 8, reinterpret_cast<const unsigned char *>(textData), len);
+ }
+ delete converted;
+
+#if PLAT_GTK_WIN32
+ delete newline_normalized;
+#endif
+}
+
+#ifdef USE_GTK_CLIPBOARD
+void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) {
+ GtkClipboard *clipBoard =
+ gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
+ if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
+ return;
+
+ if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
+ ClipboardGetSelection, ClipboardClearSelection, clipText)) {
+ gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets);
+ }
+}
+
+void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
+ GetSelection(selection_data, info, static_cast<SelectionText*>(data));
+}
+
+void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) {
+ SelectionText *obj = static_cast<SelectionText*>(data);
+ delete obj;
+}
+#endif
+
+void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
+ try {
+ //Platform::DebugPrintf("UnclaimSelection\n");
+ if (selection_event->selection == GDK_SELECTION_PRIMARY) {
+ //Platform::DebugPrintf("UnclaimPrimarySelection\n");
+ if (!OwnPrimarySelection()) {
+ primary.Free();
+ primarySelection = false;
+ FullPaint();
+ }
+ }
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::Resize(int width, int height) {
+ //Platform::DebugPrintf("Resize %d %d\n", width, height);
+ //printf("Resize %d %d\n", width, height);
+
+ // Not always needed, but some themes can have different sizes of scrollbars
+ scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width;
+ scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height;
+
+ // These allocations should never produce negative sizes as they would wrap around to huge
+ // unsigned numbers inside GTK+ causing warnings.
+ bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
+ int horizontalScrollBarHeight = scrollBarHeight;
+ if (!showSBHorizontal)
+ horizontalScrollBarHeight = 0;
+
+ GtkAllocation alloc;
+ if (showSBHorizontal) {
+ gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh)));
+ alloc.x = 0;
+ alloc.y = height - scrollBarHeight;
+ alloc.width = Platform::Maximum(1, width - scrollBarWidth) + 1;
+ alloc.height = horizontalScrollBarHeight;
+ gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc);
+ } else {
+ gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh)));
+ }
+
+ if (verticalScrollBarVisible) {
+ gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv)));
+ alloc.x = width - scrollBarWidth;
+ alloc.y = 0;
+ alloc.width = scrollBarWidth;
+ alloc.height = Platform::Maximum(1, height - scrollBarHeight) + 1;
+ if (!showSBHorizontal)
+ alloc.height += scrollBarWidth-1;
+ gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc);
+ } else {
+ gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv)));
+ }
+ if (GTK_WIDGET_MAPPED(PWidget(wMain))) {
+ ChangeSize();
+ }
+
+ alloc.x = 0;
+ alloc.y = 0;
+ alloc.width = Platform::Maximum(1, width - scrollBarWidth);
+ alloc.height = Platform::Maximum(1, height - scrollBarHeight);
+ if (!showSBHorizontal)
+ alloc.height += scrollBarHeight;
+ if (!verticalScrollBarVisible)
+ alloc.width += scrollBarWidth;
+ gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc);
+}
+
+static void SetAdjustmentValue(GtkObject *object, int value) {
+ GtkAdjustment *adjustment = GTK_ADJUSTMENT(object);
+ int maxValue = static_cast<int>(
+ adjustment->upper - adjustment->page_size);
+ if (value > maxValue)
+ value = maxValue;
+ if (value < 0)
+ value = 0;
+ gtk_adjustment_set_value(adjustment, value);
+}
+
+static int modifierTranslated(int sciModifier) {
+ switch (sciModifier) {
+ case SCMOD_SHIFT:
+ return GDK_SHIFT_MASK;
+ case SCMOD_CTRL:
+ return GDK_CONTROL_MASK;
+ case SCMOD_ALT:
+ return GDK_MOD1_MASK;
+ case SCMOD_SUPER:
+ return GDK_MOD4_MASK;
+ default:
+ return 0;
+ }
+}
+
+gint ScintillaGTK::PressThis(GdkEventButton *event) {
+ try {
+ //Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
+ // Do not use GTK+ double click events as Scintilla has its own double click detection
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ evbtn = *event;
+ Point pt;
+ pt.x = int(event->x);
+ pt.y = int(event->y);
+ PRectangle rcClient = GetClientRectangle();
+ //Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
+ // pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+ if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) {
+ Platform::DebugPrintf("Bad location\n");
+ return FALSE;
+ }
+
+ bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
+
+ gtk_widget_grab_focus(PWidget(wMain));
+ if (event->button == 1) {
+ // On X, instead of sending literal modifiers use the user specified
+ // modifier, defaulting to control instead of alt.
+ // This is because most X window managers grab alt + click for moving
+ ButtonDown(pt, event->time,
+ (event->state & GDK_SHIFT_MASK) != 0,
+ (event->state & GDK_CONTROL_MASK) != 0,
+ (event->state & modifierTranslated(rectangularSelectionModifier)) != 0);
+ } else if (event->button == 2) {
+ // Grab the primary selection if it exists
+ SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
+ if (OwnPrimarySelection() && primary.s == NULL)
+ CopySelectionRange(&primary);
+
+ sel.Clear();
+ SetSelection(pos, pos);
+ atomSought = atomUTF8;
+ gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
+ atomSought, event->time);
+ } else if (event->button == 3) {
+ if (displayPopupMenu) {
+ // PopUp menu
+ // Convert to screen
+ int ox = 0;
+ int oy = 0;
+ gdk_window_get_origin(PWidget(wMain)->window, &ox, &oy);
+ ContextMenu(Point(pt.x + ox, pt.y + oy));
+ } else {
+ return FALSE;
+ }
+ } else if (event->button == 4) {
+ // Wheel scrolling up (only GTK 1.x does it this way)
+ if (ctrl)
+ SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6);
+ else
+ SetAdjustmentValue(adjustmentv, topLine - 3);
+ } else if (event->button == 5) {
+ // Wheel scrolling down (only GTK 1.x does it this way)
+ if (ctrl)
+ SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6);
+ else
+ SetAdjustmentValue(adjustmentv, topLine + 3);
+ }
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return TRUE;
+}
+
+gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
+ if (event->window != widget->window)
+ return FALSE;
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ return sciThis->PressThis(event);
+}
+
+gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ //Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
+ if (!sciThis->HaveMouseCapture())
+ return FALSE;
+ if (event->button == 1) {
+ Point pt;
+ pt.x = int(event->x);
+ pt.y = int(event->y);
+ //Platform::DebugPrintf("Up %x %x %d %d %d\n",
+ // sciThis,event->window,event->time, pt.x, pt.y);
+ if (event->window != PWidget(sciThis->wMain)->window)
+ // If mouse released on scroll bar then the position is relative to the
+ // scrollbar, not the drawing window so just repeat the most recent point.
+ pt = sciThis->ptMouseLast;
+ sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0);
+ }
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
+// button4/5/6/7 events to the GTK app
+gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
+ GdkEventScroll *event) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+
+ if (widget == NULL || event == NULL)
+ return FALSE;
+
+ // Compute amount and direction to scroll (even tho on win32 there is
+ // intensity of scrolling info in the native message, gtk doesn't
+ // support this so we simulate similarly adaptive scrolling)
+ // Note that this is disabled on OS X (Darwin) where the X11 server already has
+ // and adaptive scrolling algorithm that fights with this one
+ int cLineScroll;
+#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__)
+ cLineScroll = sciThis->linesPerScroll;
+ if (cLineScroll == 0)
+ cLineScroll = 4;
+ sciThis->wheelMouseIntensity = cLineScroll;
+#else
+ int timeDelta = 1000000;
+ GTimeVal curTime;
+ g_get_current_time(&curTime);
+ if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec)
+ timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec;
+ else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1)
+ timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec);
+ if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) {
+ if (sciThis->wheelMouseIntensity < 12)
+ sciThis->wheelMouseIntensity++;
+ cLineScroll = sciThis->wheelMouseIntensity;
+ } else {
+ cLineScroll = sciThis->linesPerScroll;
+ if (cLineScroll == 0)
+ cLineScroll = 4;
+ sciThis->wheelMouseIntensity = cLineScroll;
+ }
+#endif
+ if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) {
+ cLineScroll *= -1;
+ }
+ g_get_current_time(&sciThis->lastWheelMouseTime);
+ sciThis->lastWheelMouseDirection = event->direction;
+
+ // Note: Unpatched versions of win32gtk don't set the 'state' value so
+ // only regular scrolling is supported there. Also, unpatched win32gtk
+ // issues spurious button 2 mouse events during wheeling, which can cause
+ // problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
+
+ // Data zoom not supported
+ if (event->state & GDK_SHIFT_MASK) {
+ return FALSE;
+ }
+
+ // Horizontal scrolling
+ if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) {
+ sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll);
+
+ // Text font size zoom
+ } else if (event->state & GDK_CONTROL_MASK) {
+ if (cLineScroll < 0) {
+ sciThis->KeyCommand(SCI_ZOOMIN);
+ } else {
+ sciThis->KeyCommand(SCI_ZOOMOUT);
+ }
+
+ // Regular scrolling
+ } else {
+ sciThis->ScrollTo(sciThis->topLine + cLineScroll);
+ }
+ return TRUE;
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ //Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
+ if (event->window != widget->window)
+ return FALSE;
+ int x = 0;
+ int y = 0;
+ GdkModifierType state;
+ if (event->is_hint) {
+ gdk_window_get_pointer(event->window, &x, &y, &state);
+ } else {
+ x = static_cast<int>(event->x);
+ y = static_cast<int>(event->y);
+ state = static_cast<GdkModifierType>(event->state);
+ }
+ //Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
+ // sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
+ Point pt(x, y);
+ sciThis->ButtonMove(pt);
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+// Map the keypad keys to their equivalent functions
+static int KeyTranslate(int keyIn) {
+ switch (keyIn) {
+ case GDK_ISO_Left_Tab:
+ return SCK_TAB;
+ case GDK_KP_Down:
+ return SCK_DOWN;
+ case GDK_KP_Up:
+ return SCK_UP;
+ case GDK_KP_Left:
+ return SCK_LEFT;
+ case GDK_KP_Right:
+ return SCK_RIGHT;
+ case GDK_KP_Home:
+ return SCK_HOME;
+ case GDK_KP_End:
+ return SCK_END;
+ case GDK_KP_Page_Up:
+ return SCK_PRIOR;
+ case GDK_KP_Page_Down:
+ return SCK_NEXT;
+ case GDK_KP_Delete:
+ return SCK_DELETE;
+ case GDK_KP_Insert:
+ return SCK_INSERT;
+ case GDK_KP_Enter:
+ return SCK_RETURN;
+
+ case GDK_Down:
+ return SCK_DOWN;
+ case GDK_Up:
+ return SCK_UP;
+ case GDK_Left:
+ return SCK_LEFT;
+ case GDK_Right:
+ return SCK_RIGHT;
+ case GDK_Home:
+ return SCK_HOME;
+ case GDK_End:
+ return SCK_END;
+ case GDK_Page_Up:
+ return SCK_PRIOR;
+ case GDK_Page_Down:
+ return SCK_NEXT;
+ case GDK_Delete:
+ return SCK_DELETE;
+ case GDK_Insert:
+ return SCK_INSERT;
+ case GDK_Escape:
+ return SCK_ESCAPE;
+ case GDK_BackSpace:
+ return SCK_BACK;
+ case GDK_Tab:
+ return SCK_TAB;
+ case GDK_Return:
+ return SCK_RETURN;
+ case GDK_KP_Add:
+ return SCK_ADD;
+ case GDK_KP_Subtract:
+ return SCK_SUBTRACT;
+ case GDK_KP_Divide:
+ return SCK_DIVIDE;
+ case GDK_Super_L:
+ return SCK_WIN;
+ case GDK_Super_R:
+ return SCK_RWIN;
+ case GDK_Menu:
+ return SCK_MENU;
+ default:
+ return keyIn;
+ }
+}
+
+gboolean ScintillaGTK::KeyThis(GdkEventKey *event) {
+ try {
+ //fprintf(stderr, "SC-key: %d %x [%s]\n",
+ // event->keyval, event->state, (event->length > 0) ? event->string : "empty");
+ if (gtk_im_context_filter_keypress(im_context, event)) {
+ return 1;
+ }
+ if (!event->keyval) {
+ return true;
+ }
+
+ bool shift = (event->state & GDK_SHIFT_MASK) != 0;
+ bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
+ bool alt = (event->state & GDK_MOD1_MASK) != 0;
+ guint key = event->keyval;
+ if (ctrl && (key < 128))
+ key = toupper(key);
+ else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9))
+ key &= 0x7F;
+ // Hack for keys over 256 and below command keys but makes Hungarian work.
+ // This will have to change for Unicode
+ else if (key >= 0xFE00)
+ key = KeyTranslate(key);
+
+ bool consumed = false;
+ bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
+ if (!consumed)
+ consumed = added;
+ //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed);
+ if (event->keyval == 0xffffff && event->length > 0) {
+ ClearSelection();
+ if (pdoc->InsertCString(CurrentPosition(), event->string)) {
+ MovePositionTo(CurrentPosition() + event->length);
+ }
+ }
+ return consumed;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ return sciThis->KeyThis(event);
+}
+
+gboolean ScintillaGTK::KeyRelease(GtkWidget *, GdkEventKey * /*event*/) {
+ //Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
+ return FALSE;
+}
+
+gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
+ try {
+ gchar *str;
+ gint cursor_pos;
+ PangoAttrList *attrs;
+
+ gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
+ PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
+ pango_layout_set_attributes(layout, attrs);
+
+ GdkGC *gc = gdk_gc_new(widget->window);
+ GdkColor color[2] = { {0, 0x0000, 0x0000, 0x0000},
+ {0, 0xffff, 0xffff, 0xffff}
+ };
+ gdk_color_alloc(gdk_colormap_get_system(), color);
+ gdk_color_alloc(gdk_colormap_get_system(), color + 1);
+
+ gdk_gc_set_foreground(gc, color + 1);
+ gdk_draw_rectangle(widget->window, gc, TRUE, ose->area.x, ose->area.y,
+ ose->area.width, ose->area.height);
+
+ gdk_gc_set_foreground(gc, color);
+ gdk_gc_set_background(gc, color + 1);
+ gdk_draw_layout(widget->window, gc, 0, 0, layout);
+
+ gdk_gc_unref(gc);
+ g_free(str);
+ pango_attr_list_unref(attrs);
+ g_object_unref(layout);
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return TRUE;
+}
+
+gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
+ return sciThis->ExposePreeditThis(widget, ose);
+}
+
+void ScintillaGTK::CommitThis(char *utfVal) {
+ try {
+ //~ fprintf(stderr, "Commit '%s'\n", utfVal);
+ if (IsUnicodeMode()) {
+ AddCharUTF(utfVal, strlen(utfVal));
+ } else {
+ const char *source = CharacterSetID();
+ if (*source) {
+ Converter conv(source, "UTF-8", true);
+ if (conv) {
+ char localeVal[4] = "\0\0\0";
+ char *pin = utfVal;
+ size_t inLeft = strlen(utfVal);
+ char *pout = localeVal;
+ size_t outLeft = sizeof(localeVal);
+ size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
+ if (conversions != ((size_t)(-1))) {
+ *pout = '\0';
+ for (int i = 0; localeVal[i]; i++) {
+ AddChar(localeVal[i]);
+ }
+ } else {
+ fprintf(stderr, "Conversion failed '%s'\n", utfVal);
+ }
+ }
+ }
+ }
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::Commit(GtkIMContext *, char *str, ScintillaGTK *sciThis) {
+ sciThis->CommitThis(str);
+}
+
+void ScintillaGTK::PreeditChangedThis() {
+ try {
+ gchar *str;
+ PangoAttrList *attrs;
+ gint cursor_pos;
+ gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
+ if (strlen(str) > 0) {
+ PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
+ pango_layout_set_attributes(layout, attrs);
+
+ gint w, h;
+ pango_layout_get_pixel_size(layout, &w, &h);
+ g_object_unref(layout);
+
+ gint x, y;
+ gdk_window_get_origin((PWidget(wText))->window, &x, &y);
+
+ Point pt = PointMainCaret();
+ if (pt.x < 0)
+ pt.x = 0;
+ if (pt.y < 0)
+ pt.y = 0;
+
+ gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
+ gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
+ gtk_widget_show(PWidget(wPreedit));
+ gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
+ } else {
+ gtk_widget_hide(PWidget(wPreedit));
+ }
+ g_free(str);
+ pango_attr_list_unref(attrs);
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
+ sciThis->PreeditChangedThis();
+}
+
+gint ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {
+ if (widget->window != NULL)
+ gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
+ return FALSE;
+}
+
+gint ScintillaGTK::RealizeText(GtkWidget *widget, void*) {
+ if (widget->window != NULL)
+ gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
+ return FALSE;
+}
+
+void ScintillaGTK::Destroy(GObject *object) {
+ try {
+ ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
+ // This avoids a double destruction
+ if (!scio->pscin)
+ return;
+ ScintillaGTK *sciThis = reinterpret_cast<ScintillaGTK *>(scio->pscin);
+ //Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
+ sciThis->Finalise();
+
+ delete sciThis;
+ scio->pscin = 0;
+ } catch (...) {
+ // Its dead so nowhere to save the status
+ }
+}
+
+static void DrawChild(GtkWidget *widget, GdkRectangle *area) {
+ GdkRectangle areaIntersect;
+ if (widget &&
+ GTK_WIDGET_DRAWABLE(widget) &&
+ gtk_widget_intersect(widget, area, &areaIntersect)) {
+ gtk_widget_draw(widget, &areaIntersect);
+ }
+}
+
+void ScintillaGTK::Draw(GtkWidget *widget, GdkRectangle *area) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ //Platform::DebugPrintf("Draw %p %0d,%0d %0d,%0d\n", widget, area->x, area->y, area->width, area->height);
+ PRectangle rcPaint(area->x, area->y, area->x + area->width, area->y + area->height);
+ sciThis->SyncPaint(rcPaint);
+ if (GTK_WIDGET_DRAWABLE(PWidget(sciThis->wMain))) {
+ DrawChild(PWidget(sciThis->scrollbarh), area);
+ DrawChild(PWidget(sciThis->scrollbarv), area);
+ }
+
+ Point pt = sciThis->PointMainCaret();
+ pt.y += sciThis->vs.lineHeight - 2;
+ if (pt.x < 0) pt.x = 0;
+ if (pt.y < 0) pt.y = 0;
+ CursorMoved(widget, pt.x, pt.y, sciThis);
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) {
+ try {
+ paintState = painting;
+
+ rcPaint.left = ose->area.x;
+ rcPaint.top = ose->area.y;
+ rcPaint.right = ose->area.x + ose->area.width;
+ rcPaint.bottom = ose->area.y + ose->area.height;
+
+ PLATFORM_ASSERT(rgnUpdate == NULL);
+ rgnUpdate = gdk_region_copy(ose->region);
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(PWidget(wText)->window, PWidget(wText));
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+ if (paintState == paintAbandoned) {
+ // Painting area was insufficient to cover new styling or brace highlight positions
+ FullPaint();
+ }
+ paintState = notPainting;
+
+ if (rgnUpdate) {
+ gdk_region_destroy(rgnUpdate);
+ }
+ rgnUpdate = 0;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+
+ return FALSE;
+}
+
+gint ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
+ return sciThis->ExposeTextThis(widget, ose);
+}
+
+gint ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ //Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n",
+ //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
+ return sciThis->Expose(widget, ose);
+}
+
+gint ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {
+ try {
+ //fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
+ //ose->area.x, ose->area.y, ose->area.width, ose->area.height);
+
+ // The text is painted in ExposeText
+ gtk_container_propagate_expose(
+ GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose);
+ gtk_container_propagate_expose(
+ GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose);
+
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
+ try {
+ sciThis->ScrollTo(static_cast<int>(adj->value), false);
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
+ try {
+ sciThis->HorizontalScrollTo(static_cast<int>(adj->value * 2));
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::SelectionReceived(GtkWidget *widget,
+ GtkSelectionData *selection_data, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ //Platform::DebugPrintf("Selection received\n");
+ sciThis->ReceivedSelection(selection_data);
+}
+
+void ScintillaGTK::SelectionGet(GtkWidget *widget,
+ GtkSelectionData *selection_data, guint info, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ //Platform::DebugPrintf("Selection get\n");
+ if (selection_data->selection == GDK_SELECTION_PRIMARY) {
+ if (sciThis->primary.s == NULL) {
+ sciThis->CopySelectionRange(&sciThis->primary);
+ }
+ sciThis->GetSelection(selection_data, info, &sciThis->primary);
+ }
+#ifndef USE_GTK_CLIPBOARD
+ else {
+ sciThis->GetSelection(selection_data, info, &sciThis->copyText);
+ }
+#endif
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ //Platform::DebugPrintf("Selection clear\n");
+ sciThis->UnclaimSelection(selection_event);
+ return gtk_selection_clear(widget, selection_event);
+}
+
+void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
+ //Platform::DebugPrintf("DragBegin\n");
+}
+
+gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
+ gint x, gint y, guint dragtime) {
+ try {
+ Point npt(x, y);
+ SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace()));
+ GdkDragAction preferredAction = context->suggested_action;
+ SelectionPosition pos = SPositionFromLocation(npt);
+ if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) {
+ // Avoid dragging selection onto itself as that produces a move
+ // with no real effect but which creates undo actions.
+ preferredAction = static_cast<GdkDragAction>(0);
+ } else if (context->actions == static_cast<GdkDragAction>
+ (GDK_ACTION_COPY | GDK_ACTION_MOVE)) {
+ preferredAction = GDK_ACTION_MOVE;
+ }
+ gdk_drag_status(context, preferredAction, dragtime);
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context,
+ gint x, gint y, guint dragtime) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ return sciThis->DragMotionThis(context, x, y, dragtime);
+}
+
+void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ sciThis->SetDragPosition(SelectionPosition(invalidPosition));
+ //Platform::DebugPrintf("DragLeave %x\n", sciThis);
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ // If drag did not result in drop here or elsewhere
+ if (!sciThis->dragWasDropped)
+ sciThis->SetEmptySelection(sciThis->posDrag);
+ sciThis->SetDragPosition(SelectionPosition(invalidPosition));
+ //Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
+ sciThis->inDragDrop = ddNone;
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/,
+ gint, gint, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ //Platform::DebugPrintf("Drop %x\n", sciThis);
+ sciThis->SetDragPosition(SelectionPosition(invalidPosition));
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+ return FALSE;
+}
+
+void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/,
+ gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ sciThis->ReceivedDrop(selection_data);
+ sciThis->SetDragPosition(SelectionPosition(invalidPosition));
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
+ GtkSelectionData *selection_data, guint info, guint) {
+ ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+ try {
+ sciThis->dragWasDropped = true;
+ if (!sciThis->sel.Empty()) {
+ sciThis->GetSelection(selection_data, info, &sciThis->drag);
+ }
+ if (context->action == GDK_ACTION_MOVE) {
+ for (size_t r=0; r<sciThis->sel.Count(); r++) {
+ if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) {
+ if (sciThis->posDrop > sciThis->sel.Range(r).End()) {
+ sciThis->posDrop.Add(-sciThis->sel.Range(r).Length());
+ } else {
+ sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length());
+ }
+ }
+ }
+ sciThis->ClearSelection();
+ }
+ sciThis->SetDragPosition(SelectionPosition(invalidPosition));
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+}
+
+int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
+ sciThis->Tick();
+ return 1;
+}
+
+gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
+ // Idler will be automatically stopped, if there is nothing
+ // to do while idle.
+ bool ret = sciThis->Idle();
+ if (ret == false) {
+ // FIXME: This will remove the idler from GTK, we don't want to
+ // remove it as it is removed automatically when this function
+ // returns false (although, it should be harmless).
+ sciThis->SetIdle(false);
+ }
+ return ret;
+}
+
+gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) {
+ sciThis->IdleStyling();
+ // Idler will be automatically stopped
+ return FALSE;
+}
+
+void ScintillaGTK::QueueStyling(int upTo) {
+ Editor::QueueStyling(upTo);
+ if (!styleNeeded.active) {
+ // Only allow one style needed to be queued
+ styleNeeded.active = true;
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE,
+ reinterpret_cast<GSourceFunc>(StyleIdle), this, NULL);
+ }
+}
+
+void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
+ if (action) {
+ sciThis->Command(action);
+ }
+}
+
+gint ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
+ try {
+ if (event->window != widget->window)
+ return FALSE;
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+ Point pt;
+ pt.x = int(event->x);
+ pt.y = int(event->y);
+ sciThis->ct.MouseClick(pt);
+ sciThis->CallTipClick();
+ } catch (...) {
+ }
+ return TRUE;
+}
+
+gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
+ try {
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(widget->window, widget);
+ surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage);
+ surfaceWindow->SetDBCSMode(ctip->codePage);
+ ctip->PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+ } catch (...) {
+ // No pointer back to Scintilla to save status
+ }
+ return TRUE;
+}
+
+sptr_t ScintillaGTK::DirectFunction(
+ ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ return sciThis->WndProc(iMessage, wParam, lParam);
+}
+
+sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
+ return psci->WndProc(iMessage, wParam, lParam);
+}
+
+static void scintilla_class_init(ScintillaClass *klass);
+static void scintilla_init(ScintillaObject *sci);
+
+extern void Platform_Initialise();
+extern void Platform_Finalise();
+
+GType scintilla_get_type() {
+ static GType scintilla_type = 0;
+ try {
+
+ if (!scintilla_type) {
+ scintilla_type = g_type_from_name("Scintilla");
+ if (!scintilla_type) {
+ static GTypeInfo scintilla_info = {
+ (guint16) sizeof (ScintillaClass),
+ NULL, //(GBaseInitFunc)
+ NULL, //(GBaseFinalizeFunc)
+ (GClassInitFunc) scintilla_class_init,
+ NULL, //(GClassFinalizeFunc)
+ NULL, //gconstpointer data
+ (guint16) sizeof (ScintillaObject),
+ 0, //n_preallocs
+ (GInstanceInitFunc) scintilla_init,
+ NULL //(GTypeValueTable*)
+ };
+
+ scintilla_type = g_type_register_static(
+ GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0);
+ }
+ }
+
+ } catch (...) {
+ }
+ return scintilla_type;
+}
+
+void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
+ Platform_Initialise();
+ atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
+ atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
+ atomString = GDK_SELECTION_TYPE_STRING;
+ atomUriList = gdk_atom_intern("text/uri-list", FALSE);
+ atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE);
+
+ // Define default signal handlers for the class: Could move more
+ // of the signal handlers here (those that currently attached to wDraw
+ // in Initialise() may require coordinate translation?)
+
+ object_class->finalize = Destroy;
+ widget_class->size_request = SizeRequest;
+ widget_class->size_allocate = SizeAllocate;
+ widget_class->expose_event = ExposeMain;
+ widget_class->motion_notify_event = Motion;
+ widget_class->button_press_event = Press;
+ widget_class->button_release_event = MouseRelease;
+ widget_class->scroll_event = ScrollEvent;
+ widget_class->key_press_event = KeyPress;
+ widget_class->key_release_event = KeyRelease;
+ widget_class->focus_in_event = FocusIn;
+ widget_class->focus_out_event = FocusOut;
+ widget_class->selection_received = SelectionReceived;
+ widget_class->selection_get = SelectionGet;
+ widget_class->selection_clear_event = SelectionClear;
+
+ widget_class->drag_data_received = DragDataReceived;
+ widget_class->drag_motion = DragMotion;
+ widget_class->drag_leave = DragLeave;
+ widget_class->drag_end = DragEnd;
+ widget_class->drag_drop = Drop;
+ widget_class->drag_data_get = DragDataGet;
+
+ widget_class->realize = Realize;
+ widget_class->unrealize = UnRealize;
+ widget_class->map = Map;
+ widget_class->unmap = UnMap;
+
+ container_class->forall = MainForAll;
+}
+
+#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
+#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER
+
+static void scintilla_class_init(ScintillaClass *klass) {
+ try {
+ OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
+ GtkContainerClass *container_class = (GtkContainerClass*) klass;
+
+ GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST);
+ scintilla_signals[COMMAND_SIGNAL] = g_signal_new(
+ "command",
+ G_TYPE_FROM_CLASS(object_class),
+ sigflags,
+ G_STRUCT_OFFSET(ScintillaClass, command),
+ NULL, //(GSignalAccumulator)
+ NULL, //(gpointer)
+ SIG_MARSHAL,
+ G_TYPE_NONE,
+ 2, MARSHAL_ARGUMENTS);
+
+ scintilla_signals[NOTIFY_SIGNAL] = g_signal_new(
+ SCINTILLA_NOTIFY,
+ G_TYPE_FROM_CLASS(object_class),
+ sigflags,
+ G_STRUCT_OFFSET(ScintillaClass, notify),
+ NULL,
+ NULL,
+ SIG_MARSHAL,
+ G_TYPE_NONE,
+ 2, MARSHAL_ARGUMENTS);
+
+ klass->command = NULL;
+ klass->notify = NULL;
+
+ ScintillaGTK::ClassInit(object_class, widget_class, container_class);
+ } catch (...) {
+ }
+}
+
+static void scintilla_init(ScintillaObject *sci) {
+ try {
+ GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS);
+ sci->pscin = new ScintillaGTK(sci);
+ } catch (...) {
+ }
+}
+
+GtkWidget* scintilla_new() {
+ return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
+}
+
+void scintilla_set_id(ScintillaObject *sci, uptr_t id) {
+ ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
+ psci->ctrlID = id;
+}
+
+void scintilla_release_resources(void) {
+ try {
+ Platform_Finalise();
+ } catch (...) {
+ }
+}
diff --git a/scintilla/gtk/deps.mak b/scintilla/gtk/deps.mak
new file mode 100644
index 0000000..226705b
--- /dev/null
+++ b/scintilla/gtk/deps.mak
@@ -0,0 +1,337 @@
+PlatGTK.o: PlatGTK.cxx \
+ ../include/Scintilla.h ../include/ScintillaWidget.h \
+ ../src/UniConversion.h ../src/XPM.h Converter.h
+ScintillaGTK.o: ScintillaGTK.cxx \
+ ../include/Scintilla.h ../include/ScintillaWidget.h \
+ ../include/SciLexer.h ../include/PropSet.h ../src/PropSetSimple.h \
+ ../include/Accessor.h ../include/KeyWords.h ../src/SVector.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
+ ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/AutoComplete.h ../src/ViewStyle.h \
+ ../src/Decoration.h ../src/CharClassify.h ../src/Document.h \
+ ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/UniConversion.h scintilla-marshal.h \
+ ../src/ExternalLexer.h Converter.h
+AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../src/AutoComplete.h
+CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/CallTip.h
+CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/CellBuffer.h
+CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h
+ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h
+Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Decoration.h
+DocumentAccessor.o: ../src/DocumentAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/CellBuffer.h ../include/Scintilla.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h
+Document.o: ../src/Document.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/RESearch.h
+Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h
+ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h ../include/KeyWords.h \
+ ../src/ExternalLexer.h
+Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Indicator.h
+KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/KeyMap.h
+KeyWords.o: ../src/KeyWords.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAbaqus.o: ../src/LexAbaqus.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAda.o: ../src/LexAda.cxx ../include/Platform.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/PropSet.h ../include/KeyWords.h \
+ ../include/SciLexer.h
+LexAPDL.o: ../src/LexAPDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAsm.o: ../src/LexAsm.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAsn1.o: ../src/LexAsn1.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexASY.o: ../src/LexASY.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexAU3.o: ../src/LexAU3.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAVE.o: ../src/LexAVE.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexBaan.o: ../src/LexBaan.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexBash.o: ../src/LexBash.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexBasic.o: ../src/LexBasic.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexBullant.o: ../src/LexBullant.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCaml.o: ../src/LexCaml.cxx ../include/Platform.h ../include/PropSet.h \
+ ../src/PropSetSimple.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCLW.o: ../src/LexCLW.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCmake.o: ../src/LexCmake.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCOBOL.o: ../src/LexCOBOL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexConf.o: ../src/LexConf.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexCPP.o: ../src/LexCPP.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexCrontab.o: ../src/LexCrontab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCsound.o: ../src/LexCsound.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCSS.o: ../src/LexCSS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexD.o: ../src/LexD.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexEiffel.o: ../src/LexEiffel.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexErlang.o: ../src/LexErlang.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexEScript.o: ../src/LexEScript.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexFlagship.o: ../src/LexFlagship.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexForth.o: ../src/LexForth.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexFortran.o: ../src/LexFortran.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexGAP.o: ../src/LexGAP.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexGui4Cli.o: ../src/LexGui4Cli.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexHaskell.o: ../src/LexHaskell.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/PropSetSimple.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexHTML.o: ../src/LexHTML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexInno.o: ../src/LexInno.cxx ../include/Platform.h ../src/CharClassify.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexKix.o: ../src/LexKix.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexLisp.o: ../src/LexLisp.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexLout.o: ../src/LexLout.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexLua.o: ../src/LexLua.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexMagik.o: ../src/LexMagik.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMarkdown.o: ../src/LexMarkdown.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMatlab.o: ../src/LexMatlab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMetapost.o: ../src/LexMetapost.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexMMIXAL.o: ../src/LexMMIXAL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMPT.o: ../src/LexMPT.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexMSSQL.o: ../src/LexMSSQL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexMySQL.o: ../src/LexMySQL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexNimrod.o: ../src/LexNimrod.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexNsis.o: ../src/LexNsis.cxx ../include/Platform.h ../src/CharClassify.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexOpal.o: ../src/LexOpal.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexOthers.o: ../src/LexOthers.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPascal.o: ../src/LexPascal.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h \
+ ../src/CharacterSet.h
+LexPB.o: ../src/LexPB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPerl.o: ../src/LexPerl.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexPLM.o: ../src/LexPLM.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexPOV.o: ../src/LexPOV.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPowerPro.o: ../src/LexPowerPro.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \
+ ../src/CharacterSet.h
+LexPowerShell.o: ../src/LexPowerShell.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexProgress.o: ../src/LexProgress.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPS.o: ../src/LexPS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPython.o: ../src/LexPython.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexR.o: ../src/LexR.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexRebol.o: ../src/LexRebol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexRuby.o: ../src/LexRuby.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexScriptol.o: ../src/LexScriptol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexSmalltalk.o: ../src/LexSmalltalk.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSML.o: ../src/LexSML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexSorcus.o: ../src/LexSorcus.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSpecman.o: ../src/LexSpecman.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSpice.o: ../src/LexSpice.cxx ../include/Platform.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/PropSet.h \
+ ../include/KeyWords.h ../include/SciLexer.h
+LexSQL.o: ../src/LexSQL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexTACL.o: ../src/LexTACL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexTADS3.o: ../src/LexTADS3.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexTAL.o: ../src/LexTAL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexTCL.o: ../src/LexTCL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexTeX.o: ../src/LexTeX.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexVB.o: ../src/LexVB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexVerilog.o: ../src/LexVerilog.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexVHDL.o: ../src/LexVHDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexYAML.o: ../src/LexYAML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+PerLine.o: ../src/PerLine.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/CellBuffer.h ../src/PerLine.h
+PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
+ ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Selection.h \
+ ../src/PositionCache.h
+PropSet.o: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h \
+ ../src/PropSetSimple.h
+RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
+RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h
+ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h ../src/PropSetSimple.h \
+ ../include/SciLexer.h ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../include/KeyWords.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h ../src/ScintillaBase.h
+Selection.o: ../src/Selection.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Selection.h
+StyleContext.o: ../src/StyleContext.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h
+Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Style.h
+UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h
+ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h
+WindowAccessor.o: ../src/WindowAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/WindowAccessor.h \
+ ../include/Scintilla.h
+XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
diff --git a/scintilla/gtk/makefile b/scintilla/gtk/makefile
new file mode 100644
index 0000000..d62c8f3
--- /dev/null
+++ b/scintilla/gtk/makefile
@@ -0,0 +1,89 @@
+# Make file for Scintilla on Linux or compatible OS
+# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers.
+# GNU make does not like \r\n line endings so should be saved to CVS in binary form.
+# Builds for GTK+ 2 and no longer supports GTK+ 1.
+# Also works with ming32-make on Windows.
+
+.SUFFIXES: .cxx .c .o .h .a
+ifdef CLANG
+CC = clang
+CCOMP = clang
+else
+CC = g++
+CCOMP = gcc
+endif
+AR = ar
+RANLIB = touch
+
+ifndef windir
+ifeq ($(shell uname),Darwin)
+RANLIB = ranlib
+endif
+endif
+
+COMPLIB=../bin/scintilla.a
+
+vpath %.h ../src ../include
+vpath %.cxx ../src
+
+INCLUDEDIRS=-I ../include -I ../src
+CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -pedantic -DGTK -DSCI_LEXER $(INCLUDEDIRS)
+
+ifdef NOTHREADS
+THREADFLAGS=-DG_THREADS_IMPL_NONE
+else
+THREADFLAGS=
+endif
+
+ifdef DEBUG
+CXXFLAGS=-DDEBUG -g $(CXXBASEFLAGS) $(THREADFLAGS)
+else
+CXXFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS) $(THREADFLAGS)
+endif
+
+CONFIGFLAGS:=$(shell pkg-config --cflags gtk+-2.0)
+MARSHALLER=scintilla-marshal.o
+
+.cxx.o:
+ $(CC) $(CONFIGFLAGS) $(CXXFLAGS) -c $<
+.c.o:
+ $(CCOMP) $(CONFIGFLAGS) $(CXXFLAGS) -w -c $<
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**LEXOBJS=\\\n\(\*.o \)
+LEXOBJS=\
+LexAbaqus.o LexAda.o LexAPDL.o LexAsm.o LexAsn1.o LexASY.o LexAU3.o LexAVE.o \
+LexBaan.o LexBash.o LexBasic.o LexBullant.o LexCaml.o LexCLW.o LexCmake.o \
+LexCOBOL.o LexConf.o LexCPP.o LexCrontab.o LexCsound.o LexCSS.o LexD.o \
+LexEiffel.o LexErlang.o LexEScript.o LexFlagship.o LexForth.o LexFortran.o \
+LexGAP.o LexGui4Cli.o LexHaskell.o LexHTML.o LexInno.o LexKix.o LexLisp.o \
+LexLout.o LexLua.o LexMagik.o LexMarkdown.o LexMatlab.o LexMetapost.o \
+LexMMIXAL.o LexMPT.o LexMSSQL.o LexMySQL.o LexNimrod.o LexNsis.o LexOpal.o \
+LexOthers.o LexPascal.o LexPB.o LexPerl.o LexPLM.o LexPOV.o LexPowerPro.o \
+LexPowerShell.o LexProgress.o LexPS.o LexPython.o LexR.o LexRebol.o LexRuby.o \
+LexScriptol.o LexSmalltalk.o LexSML.o LexSorcus.o LexSpecman.o LexSpice.o \
+LexSQL.o LexTACL.o LexTADS3.o LexTAL.o LexTCL.o LexTeX.o LexVB.o LexVerilog.o \
+LexVHDL.o LexYAML.o
+#--Autogenerated -- end of automatically generated section
+
+all: $(COMPLIB)
+
+clean:
+ rm -f *.o $(COMPLIB)
+
+deps:
+ $(CC) -MM $(CONFIGFLAGS) $(CXXFLAGS) *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak
+
+$(COMPLIB): DocumentAccessor.o WindowAccessor.o KeyWords.o StyleContext.o \
+ CharClassify.o Decoration.o Document.o PerLine.o CallTip.o \
+ ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSet.o PlatGTK.o \
+ KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o ViewStyle.o \
+ RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
+ $(MARSHALLER) $(LEXOBJS)
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+# Automatically generate header dependencies with "make deps"
+include deps.mak
diff --git a/scintilla/gtk/scintilla-marshal.c b/scintilla/gtk/scintilla-marshal.c
new file mode 100644
index 0000000..02da184
--- /dev/null
+++ b/scintilla/gtk/scintilla-marshal.c
@@ -0,0 +1,86 @@
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_int
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* NONE:INT,POINTER (scintilla-marshal.list:1) */
+void
+scintilla_marshal_VOID__INT_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1,
+ gint arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__INT_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_int (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+}
+
diff --git a/scintilla/gtk/scintilla-marshal.h b/scintilla/gtk/scintilla-marshal.h
new file mode 100644
index 0000000..28e94cc
--- /dev/null
+++ b/scintilla/gtk/scintilla-marshal.h
@@ -0,0 +1,21 @@
+
+#ifndef __scintilla_marshal_MARSHAL_H__
+#define __scintilla_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* NONE:INT,POINTER (scintilla-marshal.list:1) */
+extern void scintilla_marshal_VOID__INT_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+#define scintilla_marshal_NONE__INT_POINTER scintilla_marshal_VOID__INT_POINTER
+
+G_END_DECLS
+
+#endif /* __scintilla_marshal_MARSHAL_H__ */
+
diff --git a/scintilla/gtk/scintilla-marshal.list b/scintilla/gtk/scintilla-marshal.list
new file mode 100644
index 0000000..b3cd2aa
--- /dev/null
+++ b/scintilla/gtk/scintilla-marshal.list
@@ -0,0 +1 @@
+NONE:INT,POINTER
diff --git a/scintilla/include/Accessor.h b/scintilla/include/Accessor.h
new file mode 100644
index 0000000..bfe4d4d
--- /dev/null
+++ b/scintilla/include/Accessor.h
@@ -0,0 +1,79 @@
+// Scintilla source code edit control
+/** @file Accessor.h
+ ** Rapid easy access to contents of a Scintilla.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
+
+class Accessor;
+
+typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len);
+
+/**
+ * Interface to data in a Scintilla.
+ */
+class Accessor {
+protected:
+ enum {extremePosition=0x7FFFFFFF};
+ /** @a bufferSize is a trade off between time taken to copy the characters
+ * and retrieval overhead.
+ * @a slopSize positions the buffer before the desired position
+ * in case there is some backtracking. */
+ enum {bufferSize=4000, slopSize=bufferSize/8};
+ char buf[bufferSize+1];
+ int startPos;
+ int endPos;
+ int codePage;
+
+ virtual bool InternalIsLeadByte(char ch)=0;
+ virtual void Fill(int position)=0;
+
+public:
+ Accessor() : startPos(extremePosition), endPos(0), codePage(0) {}
+ virtual ~Accessor() {}
+ char operator[](int position) {
+ if (position < startPos || position >= endPos) {
+ Fill(position);
+ }
+ return buf[position - startPos];
+ }
+ /** Safe version of operator[], returning a defined value for invalid position. */
+ char SafeGetCharAt(int position, char chDefault=' ') {
+ if (position < startPos || position >= endPos) {
+ Fill(position);
+ if (position < startPos || position >= endPos) {
+ // Position is outside range of document
+ return chDefault;
+ }
+ }
+ return buf[position - startPos];
+ }
+ bool IsLeadByte(char ch) {
+ return codePage && InternalIsLeadByte(ch);
+ }
+ void SetCodePage(int codePage_) { codePage = codePage_; }
+
+ virtual bool Match(int pos, const char *s)=0;
+ virtual char StyleAt(int position)=0;
+ virtual int GetLine(int position)=0;
+ virtual int LineStart(int line)=0;
+ virtual int LevelAt(int line)=0;
+ virtual int Length()=0;
+ virtual void Flush()=0;
+ virtual int GetLineState(int line)=0;
+ virtual int SetLineState(int line, int state)=0;
+ virtual int GetPropertyInt(const char *key, int defaultValue=0)=0;
+ virtual char *GetProperties()=0;
+
+ // Style setting
+ virtual void StartAt(unsigned int start, char chMask=31)=0;
+ virtual void SetFlags(char chFlags_, char chWhile_)=0;
+ virtual unsigned int GetStartSegment()=0;
+ virtual void StartSegment(unsigned int pos)=0;
+ virtual void ColourTo(unsigned int pos, int chAttr)=0;
+ virtual void SetLevel(int line, int level)=0;
+ virtual int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0)=0;
+ virtual void IndicatorFill(int start, int end, int indicator, int value)=0;
+};
diff --git a/scintilla/include/Face.py b/scintilla/include/Face.py
new file mode 100644
index 0000000..9a92bb0
--- /dev/null
+++ b/scintilla/include/Face.py
@@ -0,0 +1,110 @@
+# Module for reading and parsing Scintilla.iface file
+
+def sanitiseLine(line):
+ if line[-1:] == '\n': line = line[:-1]
+ if line.find("##") != -1:
+ line = line[:line.find("##")]
+ line = line.strip()
+ return line
+
+def decodeFunction(featureVal):
+ retType, rest = featureVal.split(" ", 1)
+ nameIdent, params = rest.split("(")
+ name, value = nameIdent.split("=")
+ params, rest = params.split(")")
+ param1, param2 = params.split(",")[0:2]
+ return retType, name, value, param1, param2
+
+def decodeEvent(featureVal):
+ retType, rest = featureVal.split(" ", 1)
+ nameIdent, params = rest.split("(")
+ name, value = nameIdent.split("=")
+ return retType, name, value
+
+def decodeParam(p):
+ param = p.strip()
+ type = ""
+ name = ""
+ value = ""
+ if " " in param:
+ type, nv = param.split(" ")
+ if "=" in nv:
+ name, value = nv.split("=")
+ else:
+ name = nv
+ return type, name, value
+
+class Face:
+
+ def __init__(self):
+ self.order = []
+ self.features = {}
+ self.values = {}
+ self.events = {}
+
+ def ReadFromFile(self, name):
+ currentCategory = ""
+ currentComment = []
+ currentCommentFinished = 0
+ file = open(name)
+ for line in file.readlines():
+ line = sanitiseLine(line)
+ if line:
+ if line[0] == "#":
+ if line[1] == " ":
+ if currentCommentFinished:
+ currentComment = []
+ currentCommentFinished = 0
+ currentComment.append(line[2:])
+ else:
+ currentCommentFinished = 1
+ featureType, featureVal = line.split(" ", 1)
+ if featureType in ["fun", "get", "set"]:
+ retType, name, value, param1, param2 = decodeFunction(featureVal)
+ p1 = decodeParam(param1)
+ p2 = decodeParam(param2)
+ self.features[name] = {
+ "FeatureType": featureType,
+ "ReturnType": retType,
+ "Value": value,
+ "Param1Type": p1[0], "Param1Name": p1[1], "Param1Value": p1[2],
+ "Param2Type": p2[0], "Param2Name": p2[1], "Param2Value": p2[2],
+ "Category": currentCategory, "Comment": currentComment
+ }
+ if value in self.values:
+ raise "Duplicate value " + value + " " + name
+ self.values[value] = 1
+ self.order.append(name)
+ elif featureType == "evt":
+ retType, name, value = decodeEvent(featureVal)
+ self.features[name] = {
+ "FeatureType": featureType,
+ "ReturnType": retType,
+ "Value": value,
+ "Category": currentCategory, "Comment": currentComment
+ }
+ if value in self.events:
+ raise "Duplicate event " + value + " " + name
+ self.events[value] = 1
+ self.order.append(name)
+ elif featureType == "cat":
+ currentCategory = featureVal
+ elif featureType == "val":
+ try:
+ name, value = featureVal.split("=", 1)
+ except ValueError:
+ print("Failure %s" % featureVal)
+ raise
+ self.features[name] = {
+ "FeatureType": featureType,
+ "Category": currentCategory,
+ "Value": value }
+ self.order.append(name)
+ elif featureType == "enu" or featureType == "lex":
+ name, value = featureVal.split("=", 1)
+ self.features[name] = {
+ "FeatureType": featureType,
+ "Category": currentCategory,
+ "Value": value }
+ self.order.append(name)
+
diff --git a/scintilla/include/HFacer.py b/scintilla/include/HFacer.py
new file mode 100644
index 0000000..4e6eac8
--- /dev/null
+++ b/scintilla/include/HFacer.py
@@ -0,0 +1,75 @@
+# HFacer.py - regenerate the Scintilla.h and SciLexer.h files from the Scintilla.iface interface
+# definition file.
+# The header files are copied to a temporary file apart from the section between a /* ++Autogenerated*/
+# comment and a /* --Autogenerated*/ comment which is generated by the printHFile and printLexHFile
+# functions. After the temporary file is created, it is copied back to the original file name.
+
+import sys
+import os
+import Face
+
+def Contains(s,sub):
+ return s.find(sub) != -1
+
+def printLexHFile(f,out):
+ for name in f.order:
+ v = f.features[name]
+ if v["FeatureType"] in ["val"]:
+ if Contains(name, "SCE_") or Contains(name, "SCLEX_"):
+ out.write("#define " + name + " " + v["Value"] + "\n")
+
+def printHFile(f,out):
+ for name in f.order:
+ v = f.features[name]
+ if v["Category"] != "Deprecated":
+ if v["FeatureType"] in ["fun", "get", "set"]:
+ featureDefineName = "SCI_" + name.upper()
+ out.write("#define " + featureDefineName + " " + v["Value"] + "\n")
+ elif v["FeatureType"] in ["evt"]:
+ featureDefineName = "SCN_" + name.upper()
+ out.write("#define " + featureDefineName + " " + v["Value"] + "\n")
+ elif v["FeatureType"] in ["val"]:
+ if not (Contains(name, "SCE_") or Contains(name, "SCLEX_")):
+ out.write("#define " + name + " " + v["Value"] + "\n")
+
+def CopyWithInsertion(input, output, genfn, definition):
+ copying = 1
+ for line in input.readlines():
+ if copying:
+ output.write(line)
+ if Contains(line, "/* ++Autogenerated"):
+ copying = 0
+ genfn(definition, output)
+ if Contains(line, "/* --Autogenerated"):
+ copying = 1
+ output.write(line)
+
+def contents(filename):
+ f = open(filename)
+ t = f.read()
+ f.close()
+ return t
+
+def Regenerate(filename, genfn, definition):
+ inText = contents(filename)
+ tempname = "HFacer.tmp"
+ out = open(tempname,"w")
+ hfile = open(filename)
+ CopyWithInsertion(hfile, out, genfn, definition)
+ out.close()
+ hfile.close()
+ outText = contents(tempname)
+ if inText == outText:
+ os.unlink(tempname)
+ else:
+ os.unlink(filename)
+ os.rename(tempname, filename)
+
+f = Face.Face()
+try:
+ f.ReadFromFile("Scintilla.iface")
+ Regenerate("Scintilla.h", printHFile, f)
+ Regenerate("SciLexer.h", printLexHFile, f)
+ print("Maximum ID is %s" % max([x for x in f.values if int(x) < 3000]))
+except:
+ raise
diff --git a/scintilla/include/KeyWords.h b/scintilla/include/KeyWords.h
new file mode 100644
index 0000000..ab9438f
--- /dev/null
+++ b/scintilla/include/KeyWords.h
@@ -0,0 +1,113 @@
+// Scintilla source code edit control
+/** @file KeyWords.h
+ ** Colourise for particular languages.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class WordList {
+public:
+ // Each word contains at least one character - a empty word acts as sentinel at the end.
+ char **words;
+ char *list;
+ int len;
+ bool onlyLineEnds; ///< Delimited by any white space or only line ends
+ bool sorted;
+ int starts[256];
+ WordList(bool onlyLineEnds_ = false) :
+ words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_),
+ sorted(false)
+ {}
+ ~WordList() { Clear(); }
+ operator bool() { return len ? true : false; }
+ void Clear();
+ void Set(const char *s);
+ bool InList(const char *s);
+ bool InListAbbreviated(const char *s, const char marker);
+};
+
+typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler);
+
+/**
+ * A LexerModule is responsible for lexing and folding a particular language.
+ * The class maintains a list of LexerModules which can be searched to find a
+ * module appropriate to a particular language.
+ */
+class LexerModule {
+protected:
+ const LexerModule *next;
+ int language;
+ 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,
+ 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,
+ WordList *keywordlists[], Accessor &styler) const;
+ static const LexerModule *Find(int language);
+ static const LexerModule *Find(const char *languageName);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+/**
+ * Check if a character is a space.
+ * This is ASCII specific but is safe with chars >= 0x80.
+ */
+inline bool isspacechar(unsigned char ch) {
+ return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+inline bool iswordchar(char ch) {
+ return isascii(ch) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+inline bool iswordstart(char ch) {
+ return isascii(ch) && (isalnum(ch) || ch == '_');
+}
+
+inline bool isoperator(char ch) {
+ if (isascii(ch) && 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 == '>' || ch == ',' || ch == '/' ||
+ ch == '?' || ch == '!' || ch == '.' || ch == '~')
+ return true;
+ return false;
+}
diff --git a/scintilla/include/Platform.h b/scintilla/include/Platform.h
new file mode 100644
index 0000000..84b2052
--- /dev/null
+++ b/scintilla/include/Platform.h
@@ -0,0 +1,556 @@
+// Scintilla source code edit control
+/** @file Platform.h
+ ** Interface to platform facilities. Also includes some basic utilities.
+ ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows.
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+// PLAT_GTK = GTK+ on Linux or Win32
+// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32
+// PLAT_WIN = Win32 API on Win32 OS
+// PLAT_WX is wxWindows on any supported platform
+
+#define PLAT_GTK 0
+#define PLAT_GTK_WIN32 0
+#define PLAT_MACOSX 0
+#define PLAT_WIN 0
+#define PLAT_WX 0
+#define PLAT_FOX 0
+
+#if defined(FOX)
+#undef PLAT_FOX
+#define PLAT_FOX 1
+
+#elif defined(__WX__)
+#undef PLAT_WX
+#define PLAT_WX 1
+
+#elif defined(GTK)
+#undef PLAT_GTK
+#define PLAT_GTK 1
+
+#if defined(__WIN32__) || defined(_MSC_VER)
+#undef PLAT_GTK_WIN32
+#define PLAT_GTK_WIN32 1
+#endif
+
+#elif defined(__APPLE__)
+
+#undef PLAT_MACOSX
+#define PLAT_MACOSX 1
+
+#else
+#undef PLAT_WIN
+#define PLAT_WIN 1
+
+#endif
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+// Underlying the implementation of the platform classes are platform specific types.
+// Sometimes these need to be passed around by client code so they are defined here
+
+typedef void *FontID;
+typedef void *SurfaceID;
+typedef void *WindowID;
+typedef void *MenuID;
+typedef void *TickerID;
+typedef void *Function;
+typedef void *IdlerID;
+
+/**
+ * A geometric point class.
+ * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably.
+ */
+class Point {
+public:
+ int x;
+ int y;
+
+ explicit Point(int x_=0, int y_=0) : x(x_), y(y_) {
+ }
+
+ // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+
+ static Point FromLong(long lpoint);
+};
+
+/**
+ * A geometric rectangle class.
+ * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably.
+ * PRectangles contain their top and left sides, but not their right and bottom sides.
+ */
+class PRectangle {
+public:
+ int left;
+ int top;
+ int right;
+ int bottom;
+
+ PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) :
+ left(left_), top(top_), right(right_), bottom(bottom_) {
+ }
+
+ // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+
+ bool operator==(PRectangle &rc) {
+ return (rc.left == left) && (rc.right == right) &&
+ (rc.top == top) && (rc.bottom == bottom);
+ }
+ bool Contains(Point pt) {
+ return (pt.x >= left) && (pt.x <= right) &&
+ (pt.y >= top) && (pt.y <= bottom);
+ }
+ bool Contains(PRectangle rc) {
+ return (rc.left >= left) && (rc.right <= right) &&
+ (rc.top >= top) && (rc.bottom <= bottom);
+ }
+ bool Intersects(PRectangle other) {
+ return (right > other.left) && (left < other.right) &&
+ (bottom > other.top) && (top < other.bottom);
+ }
+ void Move(int xDelta, int yDelta) {
+ left += xDelta;
+ top += yDelta;
+ right += xDelta;
+ bottom += yDelta;
+ }
+ int Width() { return right - left; }
+ int Height() { return bottom - top; }
+ bool Empty() {
+ return (Height() <= 0) || (Width() <= 0);
+ }
+};
+
+/**
+ * In some circumstances, including Win32 in paletted mode and GTK+, each colour
+ * must be allocated before use. The desired colours are held in the ColourDesired class,
+ * and after allocation the allocation entry is stored in the ColourAllocated class. In other
+ * circumstances, such as Win32 in true colour mode, the allocation process just copies
+ * the RGB values from the desired to the allocated class.
+ * As each desired colour requires allocation before it can be used, the ColourPair class
+ * holds both a ColourDesired and a ColourAllocated
+ * The Palette class is responsible for managing the palette of colours which contains a
+ * list of ColourPair objects and performs the allocation.
+ */
+
+/**
+ * Holds a desired RGB colour.
+ */
+class ColourDesired {
+ long co;
+public:
+ ColourDesired(long lcol=0) {
+ co = lcol;
+ }
+
+ ColourDesired(unsigned int red, unsigned int green, unsigned int blue) {
+ Set(red, green, blue);
+ }
+
+ bool operator==(const ColourDesired &other) const {
+ return co == other.co;
+ }
+
+ void Set(long lcol) {
+ co = lcol;
+ }
+
+ void Set(unsigned int red, unsigned int green, unsigned int blue) {
+ co = red | (green << 8) | (blue << 16);
+ }
+
+ static inline unsigned int ValueOfHex(const char ch) {
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else
+ return 0;
+ }
+
+ void Set(const char *val) {
+ if (*val == '#') {
+ val++;
+ }
+ unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
+ unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
+ unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
+ Set(r, g, b);
+ }
+
+ long AsLong() const {
+ return co;
+ }
+
+ unsigned int GetRed() {
+ return co & 0xff;
+ }
+
+ unsigned int GetGreen() {
+ return (co >> 8) & 0xff;
+ }
+
+ unsigned int GetBlue() {
+ return (co >> 16) & 0xff;
+ }
+};
+
+/**
+ * Holds an allocated RGB colour which may be an approximation to the desired colour.
+ */
+class ColourAllocated {
+ long coAllocated;
+
+public:
+
+ ColourAllocated(long lcol=0) {
+ coAllocated = lcol;
+ }
+
+ void Set(long lcol) {
+ coAllocated = lcol;
+ }
+
+ long AsLong() const {
+ return coAllocated;
+ }
+};
+
+/**
+ * Colour pairs hold a desired colour and an allocated colour.
+ */
+struct ColourPair {
+ ColourDesired desired;
+ ColourAllocated allocated;
+
+ ColourPair(ColourDesired desired_=ColourDesired(0,0,0)) {
+ desired = desired_;
+ allocated.Set(desired.AsLong());
+ }
+ void Copy() {
+ allocated.Set(desired.AsLong());
+ }
+};
+
+class Window; // Forward declaration for Palette
+
+/**
+ * Colour palette management.
+ */
+class Palette {
+ int used;
+ int size;
+ ColourPair *entries;
+#if PLAT_GTK
+ void *allocatedPalette; // GdkColor *
+ int allocatedLen;
+#endif
+ // Private so Palette objects can not be copied
+ Palette(const Palette &) {}
+ Palette &operator=(const Palette &) { return *this; }
+public:
+#if PLAT_WIN
+ void *hpal;
+#endif
+ bool allowRealization;
+
+ Palette();
+ ~Palette();
+
+ void Release();
+
+ /**
+ * This method either adds a colour to the list of wanted colours (want==true)
+ * or retrieves the allocated colour back to the ColourPair.
+ * This is one method to make it easier to keep the code for wanting and retrieving in sync.
+ */
+ void WantFind(ColourPair &cp, bool want);
+
+ void Allocate(Window &w);
+};
+
+/**
+ * Font management.
+ */
+class Font {
+protected:
+ FontID fid;
+#if PLAT_WX
+ int ascent;
+#endif
+ // Private so Font objects can not be copied
+ Font(const Font &) {}
+ Font &operator=(const Font &) { fid=0; return *this; }
+public:
+ Font();
+ virtual ~Font();
+
+ virtual void Create(const char *faceName, int characterSet, int size,
+ bool bold, bool italic, int extraFontFlag=0);
+ virtual void Release();
+
+ FontID GetID() { return fid; }
+ // Alias another font - caller guarantees not to Release
+ void SetID(FontID fid_) { fid = fid_; }
+ friend class Surface;
+ friend class SurfaceImpl;
+};
+
+/**
+ * A surface abstracts a place to draw.
+ */
+class Surface {
+private:
+ // Private so Surface objects can not be copied
+ Surface(const Surface &) {}
+ Surface &operator=(const Surface &) { return *this; }
+public:
+ Surface() {}
+ virtual ~Surface() {}
+ static Surface *Allocate();
+
+ virtual void Init(WindowID wid)=0;
+ virtual void Init(SurfaceID sid, WindowID wid)=0;
+ virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0;
+
+ virtual void Release()=0;
+ virtual bool Initialised()=0;
+ virtual void PenColour(ColourAllocated fore)=0;
+ virtual int LogPixelsY()=0;
+ virtual int DeviceHeightFont(int points)=0;
+ virtual void MoveTo(int x_, int y_)=0;
+ virtual void LineTo(int x_, int y_)=0;
+ virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void FillRectangle(PRectangle rc, ColourAllocated back)=0;
+ virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0;
+ virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags)=0;
+ virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
+
+ virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
+ virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0;
+ virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0;
+ virtual int WidthText(Font &font_, const char *s, int len)=0;
+ virtual int WidthChar(Font &font_, char ch)=0;
+ virtual int Ascent(Font &font_)=0;
+ virtual int Descent(Font &font_)=0;
+ virtual int InternalLeading(Font &font_)=0;
+ virtual int ExternalLeading(Font &font_)=0;
+ virtual int Height(Font &font_)=0;
+ virtual int AverageCharWidth(Font &font_)=0;
+
+ virtual int SetPalette(Palette *pal, bool inBackGround)=0;
+ virtual void SetClip(PRectangle rc)=0;
+ virtual void FlushCachedState()=0;
+
+ virtual void SetUnicodeMode(bool unicodeMode_)=0;
+ virtual void SetDBCSMode(int codePage)=0;
+};
+
+/**
+ * A simple callback action passing one piece of untyped user data.
+ */
+typedef void (*CallBackAction)(void*);
+
+/**
+ * Class to hide the details of window manipulation.
+ * Does not own the window which will normally have a longer life than this object.
+ */
+class Window {
+protected:
+ WindowID wid;
+#if PLAT_MACOSX
+ void *windowRef;
+ void *control;
+#endif
+public:
+ Window() : wid(0), cursorLast(cursorInvalid) {
+#if PLAT_MACOSX
+ windowRef = 0;
+ control = 0;
+#endif
+ }
+ Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) {
+#if PLAT_MACOSX
+ windowRef = 0;
+ control = 0;
+#endif
+ }
+ virtual ~Window();
+ Window &operator=(WindowID wid_) {
+ wid = wid_;
+ return *this;
+ }
+ WindowID GetID() const { return wid; }
+ bool Created() const { return wid != 0; }
+ void Destroy();
+ bool HasFocus();
+ PRectangle GetPosition();
+ void SetPosition(PRectangle rc);
+ void SetPositionRelative(PRectangle rc, Window relativeTo);
+ PRectangle GetClientPosition();
+ void Show(bool show=true);
+ void InvalidateAll();
+ void InvalidateRectangle(PRectangle rc);
+ virtual void SetFont(Font &font);
+ enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
+ void SetCursor(Cursor curs);
+ void SetTitle(const char *s);
+ PRectangle GetMonitorRect(Point pt);
+#if PLAT_MACOSX
+ void SetWindow(void *ref) { windowRef = ref; };
+ void SetControl(void *_control) { control = _control; };
+#endif
+private:
+ Cursor cursorLast;
+};
+
+/**
+ * Listbox management.
+ */
+
+class ListBox : public Window {
+public:
+ ListBox();
+ virtual ~ListBox();
+ static ListBox *Allocate();
+
+ virtual void SetFont(Font &font)=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;
+ virtual void Append(char *s, int type = -1)=0;
+ virtual int Length()=0;
+ virtual void Select(int n)=0;
+ virtual int GetSelection()=0;
+ virtual int Find(const char *prefix)=0;
+ virtual void GetValue(int n, char *value, int len)=0;
+ 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;
+};
+
+/**
+ * Menu management.
+ */
+class Menu {
+ MenuID mid;
+public:
+ Menu();
+ MenuID GetID() { return mid; }
+ void CreatePopUp();
+ void Destroy();
+ void Show(Point pt, Window &w);
+};
+
+class ElapsedTime {
+ long bigBit;
+ long littleBit;
+public:
+ ElapsedTime();
+ double Duration(bool reset=false);
+};
+
+/**
+ * Dynamic Library (DLL/SO/...) loading
+ */
+class DynamicLibrary {
+public:
+ virtual ~DynamicLibrary() {}
+
+ /// @return Pointer to function "name", or NULL on failure.
+ virtual Function FindFunction(const char *name) = 0;
+
+ /// @return true if the library was loaded successfully.
+ virtual bool IsValid() = 0;
+
+ /// @return An instance of a DynamicLibrary subclass with "modulePath" loaded.
+ static DynamicLibrary *Load(const char *modulePath);
+};
+
+/**
+ * Platform class used to retrieve system wide parameters such as double click speed
+ * and chrome colour. Not a creatable object, more of a module with several functions.
+ */
+class Platform {
+ // Private so Platform objects can not be copied
+ Platform(const Platform &) {}
+ Platform &operator=(const Platform &) { return *this; }
+public:
+ // Should be private because no new Platforms are ever created
+ // but gcc warns about this
+ Platform() {}
+ ~Platform() {}
+ static ColourDesired Chrome();
+ static ColourDesired ChromeHighlight();
+ static const char *DefaultFont();
+ static int DefaultFontSize();
+ static unsigned int DoubleClickTime();
+ static bool MouseButtonBounce();
+ static void DebugDisplay(const char *s);
+ static bool IsKeyDown(int key);
+ static long SendScintilla(
+ WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
+ static long SendScintillaPointer(
+ WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0);
+ static bool IsDBCSLeadByte(int codePage, char ch);
+ static int DBCSCharLength(int codePage, const char *s);
+ static int DBCSCharMaxLength();
+
+ // These are utility functions not really tied to a platform
+ static int Minimum(int a, int b);
+ static int Maximum(int a, int b);
+ // Next three assume 16 bit shorts and 32 bit longs
+ static long LongFromTwoShorts(short a,short b) {
+ return (a) | ((b) << 16);
+ }
+ static short HighShortFromLong(long x) {
+ return static_cast<short>(x >> 16);
+ }
+ static short LowShortFromLong(long x) {
+ return static_cast<short>(x & 0xffff);
+ }
+ static void DebugPrintf(const char *format, ...);
+ static bool ShowAssertionPopUps(bool assertionPopUps_);
+ static void Assert(const char *c, const char *file, int line);
+ static int Clamp(int val, int minVal, int maxVal);
+};
+
+#ifdef NDEBUG
+#define PLATFORM_ASSERT(c) ((void)0)
+#else
+#ifdef SCI_NAMESPACE
+#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__))
+#else
+#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
+#endif
+#endif
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+// Shut up annoying Visual C++ warnings:
+#ifdef _MSC_VER
+#pragma warning(disable: 4244 4309 4514 4710)
+#endif
+
+#endif
diff --git a/scintilla/include/PropSet.h b/scintilla/include/PropSet.h
new file mode 100644
index 0000000..692044e
--- /dev/null
+++ b/scintilla/include/PropSet.h
@@ -0,0 +1,26 @@
+// Scintilla source code edit control
+/** @file PropSet.h
+ ** An interface to the methods needed for access to property sets inside lexers.
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PROPSET_H
+#define PROPSET_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class PropertyGet {
+public:
+ virtual char *ToString() const=0; // Caller must delete[] the return value
+ virtual int GetInt(const char *key, int defaultValue=0) const=0;
+ virtual ~PropertyGet() {}
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h
new file mode 100644
index 0000000..016ad3d
--- /dev/null
+++ b/scintilla/include/SciLexer.h
@@ -0,0 +1,1390 @@
+/* Scintilla source code edit control */
+/** @file SciLexer.h
+ ** Interface to the added lexer functions in the SciLexer version of the edit control.
+ **/
+/* Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+ * The License.txt file describes the conditions under which this software may be distributed. */
+
+/* Most of this file is automatically generated from the Scintilla.iface interface definition
+ * file which contains any comments about the definitions. HFacer.py does the generation. */
+
+#ifndef SCILEXER_H
+#define SCILEXER_H
+
+/* SciLexer features - not in standard Scintilla */
+
+/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
+#define SCLEX_CONTAINER 0
+#define SCLEX_NULL 1
+#define SCLEX_PYTHON 2
+#define SCLEX_CPP 3
+#define SCLEX_HTML 4
+#define SCLEX_XML 5
+#define SCLEX_PERL 6
+#define SCLEX_SQL 7
+#define SCLEX_VB 8
+#define SCLEX_PROPERTIES 9
+#define SCLEX_ERRORLIST 10
+#define SCLEX_MAKEFILE 11
+#define SCLEX_BATCH 12
+#define SCLEX_XCODE 13
+#define SCLEX_LATEX 14
+#define SCLEX_LUA 15
+#define SCLEX_DIFF 16
+#define SCLEX_CONF 17
+#define SCLEX_PASCAL 18
+#define SCLEX_AVE 19
+#define SCLEX_ADA 20
+#define SCLEX_LISP 21
+#define SCLEX_RUBY 22
+#define SCLEX_EIFFEL 23
+#define SCLEX_EIFFELKW 24
+#define SCLEX_TCL 25
+#define SCLEX_NNCRONTAB 26
+#define SCLEX_BULLANT 27
+#define SCLEX_VBSCRIPT 28
+#define SCLEX_BAAN 31
+#define SCLEX_MATLAB 32
+#define SCLEX_SCRIPTOL 33
+#define SCLEX_ASM 34
+#define SCLEX_CPPNOCASE 35
+#define SCLEX_FORTRAN 36
+#define SCLEX_F77 37
+#define SCLEX_CSS 38
+#define SCLEX_POV 39
+#define SCLEX_LOUT 40
+#define SCLEX_ESCRIPT 41
+#define SCLEX_PS 42
+#define SCLEX_NSIS 43
+#define SCLEX_MMIXAL 44
+#define SCLEX_CLW 45
+#define SCLEX_CLWNOCASE 46
+#define SCLEX_LOT 47
+#define SCLEX_YAML 48
+#define SCLEX_TEX 49
+#define SCLEX_METAPOST 50
+#define SCLEX_POWERBASIC 51
+#define SCLEX_FORTH 52
+#define SCLEX_ERLANG 53
+#define SCLEX_OCTAVE 54
+#define SCLEX_MSSQL 55
+#define SCLEX_VERILOG 56
+#define SCLEX_KIX 57
+#define SCLEX_GUI4CLI 58
+#define SCLEX_SPECMAN 59
+#define SCLEX_AU3 60
+#define SCLEX_APDL 61
+#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_INNOSETUP 76
+#define SCLEX_OPAL 77
+#define SCLEX_SPICE 78
+#define SCLEX_D 79
+#define SCLEX_CMAKE 80
+#define SCLEX_GAP 81
+#define SCLEX_PLM 82
+#define SCLEX_PROGRESS 83
+#define SCLEX_ABAQUS 84
+#define SCLEX_ASYMPTOTE 85
+#define SCLEX_R 86
+#define SCLEX_MAGIK 87
+#define SCLEX_POWERSHELL 88
+#define SCLEX_MYSQL 89
+#define SCLEX_PO 90
+#define SCLEX_TAL 91
+#define SCLEX_COBOL 92
+#define SCLEX_TACL 93
+#define SCLEX_SORCUS 94
+#define SCLEX_POWERPRO 95
+#define SCLEX_NIMROD 96
+#define SCLEX_SML 97
+#define SCLEX_MARKDOWN 98
+#define SCLEX_AUTOMATIC 1000
+#define SCE_P_DEFAULT 0
+#define SCE_P_COMMENTLINE 1
+#define SCE_P_NUMBER 2
+#define SCE_P_STRING 3
+#define SCE_P_CHARACTER 4
+#define SCE_P_WORD 5
+#define SCE_P_TRIPLE 6
+#define SCE_P_TRIPLEDOUBLE 7
+#define SCE_P_CLASSNAME 8
+#define SCE_P_DEFNAME 9
+#define SCE_P_OPERATOR 10
+#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_C_COMMENTDOC 3
+#define SCE_C_NUMBER 4
+#define SCE_C_WORD 5
+#define SCE_C_STRING 6
+#define SCE_C_CHARACTER 7
+#define SCE_C_UUID 8
+#define SCE_C_PREPROCESSOR 9
+#define SCE_C_OPERATOR 10
+#define SCE_C_IDENTIFIER 11
+#define SCE_C_STRINGEOL 12
+#define SCE_C_VERBATIM 13
+#define SCE_C_REGEX 14
+#define SCE_C_COMMENTLINEDOC 15
+#define SCE_C_WORD2 16
+#define SCE_C_COMMENTDOCKEYWORD 17
+#define SCE_C_COMMENTDOCKEYWORDERROR 18
+#define SCE_C_GLOBALCLASS 19
+#define SCE_D_DEFAULT 0
+#define SCE_D_COMMENT 1
+#define SCE_D_COMMENTLINE 2
+#define SCE_D_COMMENTDOC 3
+#define SCE_D_COMMENTNESTED 4
+#define SCE_D_NUMBER 5
+#define SCE_D_WORD 6
+#define SCE_D_WORD2 7
+#define SCE_D_WORD3 8
+#define SCE_D_TYPEDEF 9
+#define SCE_D_STRING 10
+#define SCE_D_STRINGEOL 11
+#define SCE_D_CHARACTER 12
+#define SCE_D_OPERATOR 13
+#define SCE_D_IDENTIFIER 14
+#define SCE_D_COMMENTLINEDOC 15
+#define SCE_D_COMMENTDOCKEYWORD 16
+#define SCE_D_COMMENTDOCKEYWORDERROR 17
+#define SCE_D_STRINGB 18
+#define SCE_D_STRINGR 19
+#define SCE_D_WORD5 20
+#define SCE_D_WORD6 21
+#define SCE_D_WORD7 22
+#define SCE_TCL_DEFAULT 0
+#define SCE_TCL_COMMENT 1
+#define SCE_TCL_COMMENTLINE 2
+#define SCE_TCL_NUMBER 3
+#define SCE_TCL_WORD_IN_QUOTE 4
+#define SCE_TCL_IN_QUOTE 5
+#define SCE_TCL_OPERATOR 6
+#define SCE_TCL_IDENTIFIER 7
+#define SCE_TCL_SUBSTITUTION 8
+#define SCE_TCL_SUB_BRACE 9
+#define SCE_TCL_MODIFIER 10
+#define SCE_TCL_EXPAND 11
+#define SCE_TCL_WORD 12
+#define SCE_TCL_WORD2 13
+#define SCE_TCL_WORD3 14
+#define SCE_TCL_WORD4 15
+#define SCE_TCL_WORD5 16
+#define SCE_TCL_WORD6 17
+#define SCE_TCL_WORD7 18
+#define SCE_TCL_WORD8 19
+#define SCE_TCL_COMMENT_BOX 20
+#define SCE_TCL_BLOCK_COMMENT 21
+#define SCE_H_DEFAULT 0
+#define SCE_H_TAG 1
+#define SCE_H_TAGUNKNOWN 2
+#define SCE_H_ATTRIBUTE 3
+#define SCE_H_ATTRIBUTEUNKNOWN 4
+#define SCE_H_NUMBER 5
+#define SCE_H_DOUBLESTRING 6
+#define SCE_H_SINGLESTRING 7
+#define SCE_H_OTHER 8
+#define SCE_H_COMMENT 9
+#define SCE_H_ENTITY 10
+#define SCE_H_TAGEND 11
+#define SCE_H_XMLSTART 12
+#define SCE_H_XMLEND 13
+#define SCE_H_SCRIPT 14
+#define SCE_H_ASP 15
+#define SCE_H_ASPAT 16
+#define SCE_H_CDATA 17
+#define SCE_H_QUESTION 18
+#define SCE_H_VALUE 19
+#define SCE_H_XCCOMMENT 20
+#define SCE_H_SGML_DEFAULT 21
+#define SCE_H_SGML_COMMAND 22
+#define SCE_H_SGML_1ST_PARAM 23
+#define SCE_H_SGML_DOUBLESTRING 24
+#define SCE_H_SGML_SIMPLESTRING 25
+#define SCE_H_SGML_ERROR 26
+#define SCE_H_SGML_SPECIAL 27
+#define SCE_H_SGML_ENTITY 28
+#define SCE_H_SGML_COMMENT 29
+#define SCE_H_SGML_1ST_PARAM_COMMENT 30
+#define SCE_H_SGML_BLOCK_DEFAULT 31
+#define SCE_HJ_START 40
+#define SCE_HJ_DEFAULT 41
+#define SCE_HJ_COMMENT 42
+#define SCE_HJ_COMMENTLINE 43
+#define SCE_HJ_COMMENTDOC 44
+#define SCE_HJ_NUMBER 45
+#define SCE_HJ_WORD 46
+#define SCE_HJ_KEYWORD 47
+#define SCE_HJ_DOUBLESTRING 48
+#define SCE_HJ_SINGLESTRING 49
+#define SCE_HJ_SYMBOLS 50
+#define SCE_HJ_STRINGEOL 51
+#define SCE_HJ_REGEX 52
+#define SCE_HJA_START 55
+#define SCE_HJA_DEFAULT 56
+#define SCE_HJA_COMMENT 57
+#define SCE_HJA_COMMENTLINE 58
+#define SCE_HJA_COMMENTDOC 59
+#define SCE_HJA_NUMBER 60
+#define SCE_HJA_WORD 61
+#define SCE_HJA_KEYWORD 62
+#define SCE_HJA_DOUBLESTRING 63
+#define SCE_HJA_SINGLESTRING 64
+#define SCE_HJA_SYMBOLS 65
+#define SCE_HJA_STRINGEOL 66
+#define SCE_HJA_REGEX 67
+#define SCE_HB_START 70
+#define SCE_HB_DEFAULT 71
+#define SCE_HB_COMMENTLINE 72
+#define SCE_HB_NUMBER 73
+#define SCE_HB_WORD 74
+#define SCE_HB_STRING 75
+#define SCE_HB_IDENTIFIER 76
+#define SCE_HB_STRINGEOL 77
+#define SCE_HBA_START 80
+#define SCE_HBA_DEFAULT 81
+#define SCE_HBA_COMMENTLINE 82
+#define SCE_HBA_NUMBER 83
+#define SCE_HBA_WORD 84
+#define SCE_HBA_STRING 85
+#define SCE_HBA_IDENTIFIER 86
+#define SCE_HBA_STRINGEOL 87
+#define SCE_HP_START 90
+#define SCE_HP_DEFAULT 91
+#define SCE_HP_COMMENTLINE 92
+#define SCE_HP_NUMBER 93
+#define SCE_HP_STRING 94
+#define SCE_HP_CHARACTER 95
+#define SCE_HP_WORD 96
+#define SCE_HP_TRIPLE 97
+#define SCE_HP_TRIPLEDOUBLE 98
+#define SCE_HP_CLASSNAME 99
+#define SCE_HP_DEFNAME 100
+#define SCE_HP_OPERATOR 101
+#define SCE_HP_IDENTIFIER 102
+#define SCE_HPHP_COMPLEX_VARIABLE 104
+#define SCE_HPA_START 105
+#define SCE_HPA_DEFAULT 106
+#define SCE_HPA_COMMENTLINE 107
+#define SCE_HPA_NUMBER 108
+#define SCE_HPA_STRING 109
+#define SCE_HPA_CHARACTER 110
+#define SCE_HPA_WORD 111
+#define SCE_HPA_TRIPLE 112
+#define SCE_HPA_TRIPLEDOUBLE 113
+#define SCE_HPA_CLASSNAME 114
+#define SCE_HPA_DEFNAME 115
+#define SCE_HPA_OPERATOR 116
+#define SCE_HPA_IDENTIFIER 117
+#define SCE_HPHP_DEFAULT 118
+#define SCE_HPHP_HSTRING 119
+#define SCE_HPHP_SIMPLESTRING 120
+#define SCE_HPHP_WORD 121
+#define SCE_HPHP_NUMBER 122
+#define SCE_HPHP_VARIABLE 123
+#define SCE_HPHP_COMMENT 124
+#define SCE_HPHP_COMMENTLINE 125
+#define SCE_HPHP_HSTRING_VARIABLE 126
+#define SCE_HPHP_OPERATOR 127
+#define SCE_PL_DEFAULT 0
+#define SCE_PL_ERROR 1
+#define SCE_PL_COMMENTLINE 2
+#define SCE_PL_POD 3
+#define SCE_PL_NUMBER 4
+#define SCE_PL_WORD 5
+#define SCE_PL_STRING 6
+#define SCE_PL_CHARACTER 7
+#define SCE_PL_PUNCTUATION 8
+#define SCE_PL_PREPROCESSOR 9
+#define SCE_PL_OPERATOR 10
+#define SCE_PL_IDENTIFIER 11
+#define SCE_PL_SCALAR 12
+#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_BACKTICKS 20
+#define SCE_PL_DATASECTION 21
+#define SCE_PL_HERE_DELIM 22
+#define SCE_PL_HERE_Q 23
+#define SCE_PL_HERE_QQ 24
+#define SCE_PL_HERE_QX 25
+#define SCE_PL_STRING_Q 26
+#define SCE_PL_STRING_QQ 27
+#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_PL_SUB_PROTOTYPE 40
+#define SCE_PL_FORMAT_IDENT 41
+#define SCE_PL_FORMAT 42
+#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_KEYWORD 3
+#define SCE_B_STRING 4
+#define SCE_B_PREPROCESSOR 5
+#define SCE_B_OPERATOR 6
+#define SCE_B_IDENTIFIER 7
+#define SCE_B_DATE 8
+#define SCE_B_STRINGEOL 9
+#define SCE_B_KEYWORD2 10
+#define SCE_B_KEYWORD3 11
+#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_PROPS_ASSIGNMENT 3
+#define SCE_PROPS_DEFVAL 4
+#define SCE_PROPS_KEY 5
+#define SCE_L_DEFAULT 0
+#define SCE_L_COMMAND 1
+#define SCE_L_TAG 2
+#define SCE_L_MATH 3
+#define SCE_L_COMMENT 4
+#define SCE_LUA_DEFAULT 0
+#define SCE_LUA_COMMENT 1
+#define SCE_LUA_COMMENTLINE 2
+#define SCE_LUA_COMMENTDOC 3
+#define SCE_LUA_NUMBER 4
+#define SCE_LUA_WORD 5
+#define SCE_LUA_STRING 6
+#define SCE_LUA_CHARACTER 7
+#define SCE_LUA_LITERALSTRING 8
+#define SCE_LUA_PREPROCESSOR 9
+#define SCE_LUA_OPERATOR 10
+#define SCE_LUA_IDENTIFIER 11
+#define SCE_LUA_STRINGEOL 12
+#define SCE_LUA_WORD2 13
+#define SCE_LUA_WORD3 14
+#define SCE_LUA_WORD4 15
+#define SCE_LUA_WORD5 16
+#define SCE_LUA_WORD6 17
+#define SCE_LUA_WORD7 18
+#define SCE_LUA_WORD8 19
+#define SCE_ERR_DEFAULT 0
+#define SCE_ERR_PYTHON 1
+#define SCE_ERR_GCC 2
+#define SCE_ERR_MS 3
+#define SCE_ERR_CMD 4
+#define SCE_ERR_BORLAND 5
+#define SCE_ERR_PERL 6
+#define SCE_ERR_NET 7
+#define SCE_ERR_LUA 8
+#define SCE_ERR_CTAG 9
+#define SCE_ERR_DIFF_CHANGED 10
+#define SCE_ERR_DIFF_ADDITION 11
+#define SCE_ERR_DIFF_DELETION 12
+#define SCE_ERR_DIFF_MESSAGE 13
+#define SCE_ERR_PHP 14
+#define SCE_ERR_ELF 15
+#define SCE_ERR_IFC 16
+#define SCE_ERR_IFORT 17
+#define SCE_ERR_ABSF 18
+#define SCE_ERR_TIDY 19
+#define SCE_ERR_JAVA_STACK 20
+#define SCE_ERR_VALUE 21
+#define SCE_BAT_DEFAULT 0
+#define SCE_BAT_COMMENT 1
+#define SCE_BAT_WORD 2
+#define SCE_BAT_LABEL 3
+#define SCE_BAT_HIDE 4
+#define SCE_BAT_COMMAND 5
+#define SCE_BAT_IDENTIFIER 6
+#define SCE_BAT_OPERATOR 7
+#define SCE_MAKE_DEFAULT 0
+#define SCE_MAKE_COMMENT 1
+#define SCE_MAKE_PREPROCESSOR 2
+#define SCE_MAKE_IDENTIFIER 3
+#define SCE_MAKE_OPERATOR 4
+#define SCE_MAKE_TARGET 5
+#define SCE_MAKE_IDEOL 9
+#define SCE_DIFF_DEFAULT 0
+#define SCE_DIFF_COMMENT 1
+#define SCE_DIFF_COMMAND 2
+#define SCE_DIFF_HEADER 3
+#define SCE_DIFF_POSITION 4
+#define SCE_DIFF_DELETED 5
+#define SCE_DIFF_ADDED 6
+#define SCE_DIFF_CHANGED 7
+#define SCE_CONF_DEFAULT 0
+#define SCE_CONF_COMMENT 1
+#define SCE_CONF_NUMBER 2
+#define SCE_CONF_IDENTIFIER 3
+#define SCE_CONF_EXTENSION 4
+#define SCE_CONF_PARAMETER 5
+#define SCE_CONF_STRING 6
+#define SCE_CONF_OPERATOR 7
+#define SCE_CONF_IP 8
+#define SCE_CONF_DIRECTIVE 9
+#define SCE_AVE_DEFAULT 0
+#define SCE_AVE_COMMENT 1
+#define SCE_AVE_NUMBER 2
+#define SCE_AVE_WORD 3
+#define SCE_AVE_STRING 6
+#define SCE_AVE_ENUM 7
+#define SCE_AVE_STRINGEOL 8
+#define SCE_AVE_IDENTIFIER 9
+#define SCE_AVE_OPERATOR 10
+#define SCE_AVE_WORD1 11
+#define SCE_AVE_WORD2 12
+#define SCE_AVE_WORD3 13
+#define SCE_AVE_WORD4 14
+#define SCE_AVE_WORD5 15
+#define SCE_AVE_WORD6 16
+#define SCE_ADA_DEFAULT 0
+#define SCE_ADA_WORD 1
+#define SCE_ADA_IDENTIFIER 2
+#define SCE_ADA_NUMBER 3
+#define SCE_ADA_DELIMITER 4
+#define SCE_ADA_CHARACTER 5
+#define SCE_ADA_CHARACTEREOL 6
+#define SCE_ADA_STRING 7
+#define SCE_ADA_STRINGEOL 8
+#define SCE_ADA_LABEL 9
+#define SCE_ADA_COMMENTLINE 10
+#define SCE_ADA_ILLEGAL 11
+#define SCE_BAAN_DEFAULT 0
+#define SCE_BAAN_COMMENT 1
+#define SCE_BAAN_COMMENTDOC 2
+#define SCE_BAAN_NUMBER 3
+#define SCE_BAAN_WORD 4
+#define SCE_BAAN_STRING 5
+#define SCE_BAAN_PREPROCESSOR 6
+#define SCE_BAAN_OPERATOR 7
+#define SCE_BAAN_IDENTIFIER 8
+#define SCE_BAAN_STRINGEOL 9
+#define SCE_BAAN_WORD2 10
+#define SCE_LISP_DEFAULT 0
+#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_EIFFEL_WORD 3
+#define SCE_EIFFEL_STRING 4
+#define SCE_EIFFEL_CHARACTER 5
+#define SCE_EIFFEL_OPERATOR 6
+#define SCE_EIFFEL_IDENTIFIER 7
+#define SCE_EIFFEL_STRINGEOL 8
+#define SCE_NNCRONTAB_DEFAULT 0
+#define SCE_NNCRONTAB_COMMENT 1
+#define SCE_NNCRONTAB_TASK 2
+#define SCE_NNCRONTAB_SECTION 3
+#define SCE_NNCRONTAB_KEYWORD 4
+#define SCE_NNCRONTAB_MODIFIER 5
+#define SCE_NNCRONTAB_ASTERISK 6
+#define SCE_NNCRONTAB_NUMBER 7
+#define SCE_NNCRONTAB_STRING 8
+#define SCE_NNCRONTAB_ENVIRONMENT 9
+#define SCE_NNCRONTAB_IDENTIFIER 10
+#define SCE_FORTH_DEFAULT 0
+#define SCE_FORTH_COMMENT 1
+#define SCE_FORTH_COMMENT_ML 2
+#define SCE_FORTH_IDENTIFIER 3
+#define SCE_FORTH_CONTROL 4
+#define SCE_FORTH_KEYWORD 5
+#define SCE_FORTH_DEFWORD 6
+#define SCE_FORTH_PREWORD1 7
+#define SCE_FORTH_PREWORD2 8
+#define SCE_FORTH_NUMBER 9
+#define SCE_FORTH_STRING 10
+#define SCE_FORTH_LOCALE 11
+#define SCE_MATLAB_DEFAULT 0
+#define SCE_MATLAB_COMMENT 1
+#define SCE_MATLAB_COMMAND 2
+#define SCE_MATLAB_NUMBER 3
+#define SCE_MATLAB_KEYWORD 4
+#define SCE_MATLAB_STRING 5
+#define SCE_MATLAB_OPERATOR 6
+#define SCE_MATLAB_IDENTIFIER 7
+#define SCE_MATLAB_DOUBLEQUOTESTRING 8
+#define SCE_SCRIPTOL_DEFAULT 0
+#define SCE_SCRIPTOL_WHITE 1
+#define SCE_SCRIPTOL_COMMENTLINE 2
+#define SCE_SCRIPTOL_PERSISTENT 3
+#define SCE_SCRIPTOL_CSTYLE 4
+#define SCE_SCRIPTOL_COMMENTBLOCK 5
+#define SCE_SCRIPTOL_NUMBER 6
+#define SCE_SCRIPTOL_STRING 7
+#define SCE_SCRIPTOL_CHARACTER 8
+#define SCE_SCRIPTOL_STRINGEOL 9
+#define SCE_SCRIPTOL_KEYWORD 10
+#define SCE_SCRIPTOL_OPERATOR 11
+#define SCE_SCRIPTOL_IDENTIFIER 12
+#define SCE_SCRIPTOL_TRIPLE 13
+#define SCE_SCRIPTOL_CLASSNAME 14
+#define SCE_SCRIPTOL_PREPROCESSOR 15
+#define SCE_ASM_DEFAULT 0
+#define SCE_ASM_COMMENT 1
+#define SCE_ASM_NUMBER 2
+#define SCE_ASM_STRING 3
+#define SCE_ASM_OPERATOR 4
+#define SCE_ASM_IDENTIFIER 5
+#define SCE_ASM_CPUINSTRUCTION 6
+#define SCE_ASM_MATHINSTRUCTION 7
+#define SCE_ASM_REGISTER 8
+#define SCE_ASM_DIRECTIVE 9
+#define SCE_ASM_DIRECTIVEOPERAND 10
+#define SCE_ASM_COMMENTBLOCK 11
+#define SCE_ASM_CHARACTER 12
+#define SCE_ASM_STRINGEOL 13
+#define SCE_ASM_EXTINSTRUCTION 14
+#define SCE_F_DEFAULT 0
+#define SCE_F_COMMENT 1
+#define SCE_F_NUMBER 2
+#define SCE_F_STRING1 3
+#define SCE_F_STRING2 4
+#define SCE_F_STRINGEOL 5
+#define SCE_F_OPERATOR 6
+#define SCE_F_IDENTIFIER 7
+#define SCE_F_WORD 8
+#define SCE_F_WORD2 9
+#define SCE_F_WORD3 10
+#define SCE_F_PREPROCESSOR 11
+#define SCE_F_OPERATOR2 12
+#define SCE_F_LABEL 13
+#define SCE_F_CONTINUATION 14
+#define SCE_CSS_DEFAULT 0
+#define SCE_CSS_TAG 1
+#define SCE_CSS_CLASS 2
+#define SCE_CSS_PSEUDOCLASS 3
+#define SCE_CSS_UNKNOWN_PSEUDOCLASS 4
+#define SCE_CSS_OPERATOR 5
+#define SCE_CSS_IDENTIFIER 6
+#define SCE_CSS_UNKNOWN_IDENTIFIER 7
+#define SCE_CSS_VALUE 8
+#define SCE_CSS_COMMENT 9
+#define SCE_CSS_ID 10
+#define SCE_CSS_IMPORTANT 11
+#define SCE_CSS_DIRECTIVE 12
+#define SCE_CSS_DOUBLESTRING 13
+#define SCE_CSS_SINGLESTRING 14
+#define SCE_CSS_IDENTIFIER2 15
+#define SCE_CSS_ATTRIBUTE 16
+#define SCE_CSS_IDENTIFIER3 17
+#define SCE_CSS_PSEUDOELEMENT 18
+#define SCE_CSS_EXTENDED_IDENTIFIER 19
+#define SCE_CSS_EXTENDED_PSEUDOCLASS 20
+#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21
+#define SCE_CSS_MEDIA 22
+#define SCE_POV_DEFAULT 0
+#define SCE_POV_COMMENT 1
+#define SCE_POV_COMMENTLINE 2
+#define SCE_POV_NUMBER 3
+#define SCE_POV_OPERATOR 4
+#define SCE_POV_IDENTIFIER 5
+#define SCE_POV_STRING 6
+#define SCE_POV_STRINGEOL 7
+#define SCE_POV_DIRECTIVE 8
+#define SCE_POV_BADDIRECTIVE 9
+#define SCE_POV_WORD2 10
+#define SCE_POV_WORD3 11
+#define SCE_POV_WORD4 12
+#define SCE_POV_WORD5 13
+#define SCE_POV_WORD6 14
+#define SCE_POV_WORD7 15
+#define SCE_POV_WORD8 16
+#define SCE_LOUT_DEFAULT 0
+#define SCE_LOUT_COMMENT 1
+#define SCE_LOUT_NUMBER 2
+#define SCE_LOUT_WORD 3
+#define SCE_LOUT_WORD2 4
+#define SCE_LOUT_WORD3 5
+#define SCE_LOUT_WORD4 6
+#define SCE_LOUT_STRING 7
+#define SCE_LOUT_OPERATOR 8
+#define SCE_LOUT_IDENTIFIER 9
+#define SCE_LOUT_STRINGEOL 10
+#define SCE_ESCRIPT_DEFAULT 0
+#define SCE_ESCRIPT_COMMENT 1
+#define SCE_ESCRIPT_COMMENTLINE 2
+#define SCE_ESCRIPT_COMMENTDOC 3
+#define SCE_ESCRIPT_NUMBER 4
+#define SCE_ESCRIPT_WORD 5
+#define SCE_ESCRIPT_STRING 6
+#define SCE_ESCRIPT_OPERATOR 7
+#define SCE_ESCRIPT_IDENTIFIER 8
+#define SCE_ESCRIPT_BRACE 9
+#define SCE_ESCRIPT_WORD2 10
+#define SCE_ESCRIPT_WORD3 11
+#define SCE_PS_DEFAULT 0
+#define SCE_PS_COMMENT 1
+#define SCE_PS_DSC_COMMENT 2
+#define SCE_PS_DSC_VALUE 3
+#define SCE_PS_NUMBER 4
+#define SCE_PS_NAME 5
+#define SCE_PS_KEYWORD 6
+#define SCE_PS_LITERAL 7
+#define SCE_PS_IMMEVAL 8
+#define SCE_PS_PAREN_ARRAY 9
+#define SCE_PS_PAREN_DICT 10
+#define SCE_PS_PAREN_PROC 11
+#define SCE_PS_TEXT 12
+#define SCE_PS_HEXSTRING 13
+#define SCE_PS_BASE85STRING 14
+#define SCE_PS_BADSTRINGCHAR 15
+#define SCE_NSIS_DEFAULT 0
+#define SCE_NSIS_COMMENT 1
+#define SCE_NSIS_STRINGDQ 2
+#define SCE_NSIS_STRINGLQ 3
+#define SCE_NSIS_STRINGRQ 4
+#define SCE_NSIS_FUNCTION 5
+#define SCE_NSIS_VARIABLE 6
+#define SCE_NSIS_LABEL 7
+#define SCE_NSIS_USERDEFINED 8
+#define SCE_NSIS_SECTIONDEF 9
+#define SCE_NSIS_SUBSECTIONDEF 10
+#define SCE_NSIS_IFDEFINEDEF 11
+#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_MMIXAL_OPCODE 3
+#define SCE_MMIXAL_OPCODE_PRE 4
+#define SCE_MMIXAL_OPCODE_VALID 5
+#define SCE_MMIXAL_OPCODE_UNKNOWN 6
+#define SCE_MMIXAL_OPCODE_POST 7
+#define SCE_MMIXAL_OPERANDS 8
+#define SCE_MMIXAL_NUMBER 9
+#define SCE_MMIXAL_REF 10
+#define SCE_MMIXAL_CHAR 11
+#define SCE_MMIXAL_STRING 12
+#define SCE_MMIXAL_REGISTER 13
+#define SCE_MMIXAL_HEX 14
+#define SCE_MMIXAL_OPERATOR 15
+#define SCE_MMIXAL_SYMBOL 16
+#define SCE_MMIXAL_INCLUDE 17
+#define SCE_CLW_DEFAULT 0
+#define SCE_CLW_LABEL 1
+#define SCE_CLW_COMMENT 2
+#define SCE_CLW_STRING 3
+#define SCE_CLW_USER_IDENTIFIER 4
+#define SCE_CLW_INTEGER_CONSTANT 5
+#define SCE_CLW_REAL_CONSTANT 6
+#define SCE_CLW_PICTURE_STRING 7
+#define SCE_CLW_KEYWORD 8
+#define SCE_CLW_COMPILER_DIRECTIVE 9
+#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_LOT_SET 3
+#define SCE_LOT_PASS 4
+#define SCE_LOT_FAIL 5
+#define SCE_LOT_ABORT 6
+#define SCE_YAML_DEFAULT 0
+#define SCE_YAML_COMMENT 1
+#define SCE_YAML_IDENTIFIER 2
+#define SCE_YAML_KEYWORD 3
+#define SCE_YAML_NUMBER 4
+#define SCE_YAML_REFERENCE 5
+#define SCE_YAML_DOCUMENT 6
+#define SCE_YAML_TEXT 7
+#define SCE_YAML_ERROR 8
+#define SCE_YAML_OPERATOR 9
+#define SCE_TEX_DEFAULT 0
+#define SCE_TEX_SPECIAL 1
+#define SCE_TEX_GROUP 2
+#define SCE_TEX_SYMBOL 3
+#define SCE_TEX_COMMAND 4
+#define SCE_TEX_TEXT 5
+#define SCE_METAPOST_DEFAULT 0
+#define SCE_METAPOST_SPECIAL 1
+#define SCE_METAPOST_GROUP 2
+#define SCE_METAPOST_SYMBOL 3
+#define SCE_METAPOST_COMMAND 4
+#define SCE_METAPOST_TEXT 5
+#define SCE_METAPOST_EXTRA 6
+#define SCE_ERLANG_DEFAULT 0
+#define SCE_ERLANG_COMMENT 1
+#define SCE_ERLANG_VARIABLE 2
+#define SCE_ERLANG_NUMBER 3
+#define SCE_ERLANG_KEYWORD 4
+#define SCE_ERLANG_STRING 5
+#define SCE_ERLANG_OPERATOR 6
+#define SCE_ERLANG_ATOM 7
+#define SCE_ERLANG_FUNCTION_NAME 8
+#define SCE_ERLANG_CHARACTER 9
+#define SCE_ERLANG_MACRO 10
+#define SCE_ERLANG_RECORD 11
+#define SCE_ERLANG_PREPROC 12
+#define SCE_ERLANG_NODE_NAME 13
+#define SCE_ERLANG_COMMENT_FUNCTION 14
+#define SCE_ERLANG_COMMENT_MODULE 15
+#define SCE_ERLANG_COMMENT_DOC 16
+#define SCE_ERLANG_COMMENT_DOC_MACRO 17
+#define SCE_ERLANG_ATOM_QUOTED 18
+#define SCE_ERLANG_MACRO_QUOTED 19
+#define SCE_ERLANG_RECORD_QUOTED 20
+#define SCE_ERLANG_NODE_NAME_QUOTED 21
+#define SCE_ERLANG_BIFS 22
+#define SCE_ERLANG_MODULES 23
+#define SCE_ERLANG_MODULES_ATT 24
+#define SCE_ERLANG_UNKNOWN 31
+#define SCE_MSSQL_DEFAULT 0
+#define SCE_MSSQL_COMMENT 1
+#define SCE_MSSQL_LINE_COMMENT 2
+#define SCE_MSSQL_NUMBER 3
+#define SCE_MSSQL_STRING 4
+#define SCE_MSSQL_OPERATOR 5
+#define SCE_MSSQL_IDENTIFIER 6
+#define SCE_MSSQL_VARIABLE 7
+#define SCE_MSSQL_COLUMN_NAME 8
+#define SCE_MSSQL_STATEMENT 9
+#define SCE_MSSQL_DATATYPE 10
+#define SCE_MSSQL_SYSTABLE 11
+#define SCE_MSSQL_GLOBAL_VARIABLE 12
+#define SCE_MSSQL_FUNCTION 13
+#define SCE_MSSQL_STORED_PROCEDURE 14
+#define SCE_MSSQL_DEFAULT_PREF_DATATYPE 15
+#define SCE_MSSQL_COLUMN_NAME_2 16
+#define SCE_V_DEFAULT 0
+#define SCE_V_COMMENT 1
+#define SCE_V_COMMENTLINE 2
+#define SCE_V_COMMENTLINEBANG 3
+#define SCE_V_NUMBER 4
+#define SCE_V_WORD 5
+#define SCE_V_STRING 6
+#define SCE_V_WORD2 7
+#define SCE_V_WORD3 8
+#define SCE_V_PREPROCESSOR 9
+#define SCE_V_OPERATOR 10
+#define SCE_V_IDENTIFIER 11
+#define SCE_V_STRINGEOL 12
+#define SCE_V_USER 19
+#define SCE_KIX_DEFAULT 0
+#define SCE_KIX_COMMENT 1
+#define SCE_KIX_STRING1 2
+#define SCE_KIX_STRING2 3
+#define SCE_KIX_NUMBER 4
+#define SCE_KIX_VAR 5
+#define SCE_KIX_MACRO 6
+#define SCE_KIX_KEYWORD 7
+#define SCE_KIX_FUNCTIONS 8
+#define SCE_KIX_OPERATOR 9
+#define SCE_KIX_IDENTIFIER 31
+#define SCE_GC_DEFAULT 0
+#define SCE_GC_COMMENTLINE 1
+#define SCE_GC_COMMENTBLOCK 2
+#define SCE_GC_GLOBAL 3
+#define SCE_GC_EVENT 4
+#define SCE_GC_ATTRIBUTE 5
+#define SCE_GC_CONTROL 6
+#define SCE_GC_COMMAND 7
+#define SCE_GC_STRING 8
+#define SCE_GC_OPERATOR 9
+#define SCE_SN_DEFAULT 0
+#define SCE_SN_CODE 1
+#define SCE_SN_COMMENTLINE 2
+#define SCE_SN_COMMENTLINEBANG 3
+#define SCE_SN_NUMBER 4
+#define SCE_SN_WORD 5
+#define SCE_SN_STRING 6
+#define SCE_SN_WORD2 7
+#define SCE_SN_WORD3 8
+#define SCE_SN_PREPROCESSOR 9
+#define SCE_SN_OPERATOR 10
+#define SCE_SN_IDENTIFIER 11
+#define SCE_SN_STRINGEOL 12
+#define SCE_SN_REGEXTAG 13
+#define SCE_SN_SIGNAL 14
+#define SCE_SN_USER 19
+#define SCE_AU3_DEFAULT 0
+#define SCE_AU3_COMMENT 1
+#define SCE_AU3_COMMENTBLOCK 2
+#define SCE_AU3_NUMBER 3
+#define SCE_AU3_FUNCTION 4
+#define SCE_AU3_KEYWORD 5
+#define SCE_AU3_MACRO 6
+#define SCE_AU3_STRING 7
+#define SCE_AU3_OPERATOR 8
+#define SCE_AU3_VARIABLE 9
+#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_AU3_UDF 15
+#define SCE_APDL_DEFAULT 0
+#define SCE_APDL_COMMENT 1
+#define SCE_APDL_COMMENTBLOCK 2
+#define SCE_APDL_NUMBER 3
+#define SCE_APDL_STRING 4
+#define SCE_APDL_OPERATOR 5
+#define SCE_APDL_WORD 6
+#define SCE_APDL_PROCESSOR 7
+#define SCE_APDL_COMMAND 8
+#define SCE_APDL_SLASHCOMMAND 9
+#define SCE_APDL_STARCOMMAND 10
+#define SCE_APDL_ARGUMENT 11
+#define SCE_APDL_FUNCTION 12
+#define SCE_SH_DEFAULT 0
+#define SCE_SH_ERROR 1
+#define SCE_SH_COMMENTLINE 2
+#define SCE_SH_NUMBER 3
+#define SCE_SH_WORD 4
+#define SCE_SH_STRING 5
+#define SCE_SH_CHARACTER 6
+#define SCE_SH_OPERATOR 7
+#define SCE_SH_IDENTIFIER 8
+#define SCE_SH_SCALAR 9
+#define SCE_SH_PARAM 10
+#define SCE_SH_BACKTICKS 11
+#define SCE_SH_HERE_DELIM 12
+#define SCE_SH_HERE_Q 13
+#define SCE_ASN1_DEFAULT 0
+#define SCE_ASN1_COMMENT 1
+#define SCE_ASN1_IDENTIFIER 2
+#define SCE_ASN1_STRING 3
+#define SCE_ASN1_OID 4
+#define SCE_ASN1_SCALAR 5
+#define SCE_ASN1_KEYWORD 6
+#define SCE_ASN1_ATTRIBUTE 7
+#define SCE_ASN1_DESCRIPTOR 8
+#define SCE_ASN1_TYPE 9
+#define SCE_ASN1_OPERATOR 10
+#define SCE_VHDL_DEFAULT 0
+#define SCE_VHDL_COMMENT 1
+#define SCE_VHDL_COMMENTLINEBANG 2
+#define SCE_VHDL_NUMBER 3
+#define SCE_VHDL_STRING 4
+#define SCE_VHDL_OPERATOR 5
+#define SCE_VHDL_IDENTIFIER 6
+#define SCE_VHDL_STRINGEOL 7
+#define SCE_VHDL_KEYWORD 8
+#define SCE_VHDL_STDOPERATOR 9
+#define SCE_VHDL_ATTRIBUTE 10
+#define SCE_VHDL_STDFUNCTION 11
+#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_WHITE 10
+#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_T3_BRACE 20
+#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_WORDOPERATOR 19
+#define SCE_FS_DISABLEDCODE 20
+#define SCE_FS_DEFAULT_C 21
+#define SCE_FS_COMMENTDOC_C 22
+#define SCE_FS_COMMENTLINEDOC_C 23
+#define SCE_FS_KEYWORD_C 24
+#define SCE_FS_KEYWORD2_C 25
+#define SCE_FS_NUMBER_C 26
+#define SCE_FS_STRING_C 27
+#define SCE_FS_PREPROCESSOR_C 28
+#define SCE_FS_OPERATOR_C 29
+#define SCE_FS_IDENTIFIER_C 30
+#define SCE_FS_STRINGEOL_C 31
+#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 SCE_INNO_DEFAULT 0
+#define SCE_INNO_COMMENT 1
+#define SCE_INNO_KEYWORD 2
+#define SCE_INNO_PARAMETER 3
+#define SCE_INNO_SECTION 4
+#define SCE_INNO_PREPROC 5
+#define SCE_INNO_INLINE_EXPANSION 6
+#define SCE_INNO_COMMENT_PASCAL 7
+#define SCE_INNO_KEYWORD_PASCAL 8
+#define SCE_INNO_KEYWORD_USER 9
+#define SCE_INNO_STRING_DOUBLE 10
+#define SCE_INNO_STRING_SINGLE 11
+#define SCE_INNO_IDENTIFIER 12
+#define SCE_OPAL_SPACE 0
+#define SCE_OPAL_COMMENT_BLOCK 1
+#define SCE_OPAL_COMMENT_LINE 2
+#define SCE_OPAL_INTEGER 3
+#define SCE_OPAL_KEYWORD 4
+#define SCE_OPAL_SORT 5
+#define SCE_OPAL_STRING 6
+#define SCE_OPAL_PAR 7
+#define SCE_OPAL_BOOL_CONST 8
+#define SCE_OPAL_DEFAULT 32
+#define SCE_SPICE_DEFAULT 0
+#define SCE_SPICE_IDENTIFIER 1
+#define SCE_SPICE_KEYWORD 2
+#define SCE_SPICE_KEYWORD2 3
+#define SCE_SPICE_KEYWORD3 4
+#define SCE_SPICE_NUMBER 5
+#define SCE_SPICE_DELIMITER 6
+#define SCE_SPICE_VALUE 7
+#define SCE_SPICE_COMMENTLINE 8
+#define SCE_CMAKE_DEFAULT 0
+#define SCE_CMAKE_COMMENT 1
+#define SCE_CMAKE_STRINGDQ 2
+#define SCE_CMAKE_STRINGLQ 3
+#define SCE_CMAKE_STRINGRQ 4
+#define SCE_CMAKE_COMMANDS 5
+#define SCE_CMAKE_PARAMETERS 6
+#define SCE_CMAKE_VARIABLE 7
+#define SCE_CMAKE_USERDEFINED 8
+#define SCE_CMAKE_WHILEDEF 9
+#define SCE_CMAKE_FOREACHDEF 10
+#define SCE_CMAKE_IFDEFINEDEF 11
+#define SCE_CMAKE_MACRODEF 12
+#define SCE_CMAKE_STRINGVAR 13
+#define SCE_CMAKE_NUMBER 14
+#define SCE_GAP_DEFAULT 0
+#define SCE_GAP_IDENTIFIER 1
+#define SCE_GAP_KEYWORD 2
+#define SCE_GAP_KEYWORD2 3
+#define SCE_GAP_KEYWORD3 4
+#define SCE_GAP_KEYWORD4 5
+#define SCE_GAP_STRING 6
+#define SCE_GAP_CHAR 7
+#define SCE_GAP_OPERATOR 8
+#define SCE_GAP_COMMENT 9
+#define SCE_GAP_NUMBER 10
+#define SCE_GAP_STRINGEOL 11
+#define SCE_PLM_DEFAULT 0
+#define SCE_PLM_COMMENT 1
+#define SCE_PLM_STRING 2
+#define SCE_PLM_NUMBER 3
+#define SCE_PLM_IDENTIFIER 4
+#define SCE_PLM_OPERATOR 5
+#define SCE_PLM_CONTROL 6
+#define SCE_PLM_KEYWORD 7
+#define SCE_4GL_DEFAULT 0
+#define SCE_4GL_NUMBER 1
+#define SCE_4GL_WORD 2
+#define SCE_4GL_STRING 3
+#define SCE_4GL_CHARACTER 4
+#define SCE_4GL_PREPROCESSOR 5
+#define SCE_4GL_OPERATOR 6
+#define SCE_4GL_IDENTIFIER 7
+#define SCE_4GL_BLOCK 8
+#define SCE_4GL_END 9
+#define SCE_4GL_COMMENT1 10
+#define SCE_4GL_COMMENT2 11
+#define SCE_4GL_COMMENT3 12
+#define SCE_4GL_COMMENT4 13
+#define SCE_4GL_COMMENT5 14
+#define SCE_4GL_COMMENT6 15
+#define SCE_4GL_DEFAULT_ 16
+#define SCE_4GL_NUMBER_ 17
+#define SCE_4GL_WORD_ 18
+#define SCE_4GL_STRING_ 19
+#define SCE_4GL_CHARACTER_ 20
+#define SCE_4GL_PREPROCESSOR_ 21
+#define SCE_4GL_OPERATOR_ 22
+#define SCE_4GL_IDENTIFIER_ 23
+#define SCE_4GL_BLOCK_ 24
+#define SCE_4GL_END_ 25
+#define SCE_4GL_COMMENT1_ 26
+#define SCE_4GL_COMMENT2_ 27
+#define SCE_4GL_COMMENT3_ 28
+#define SCE_4GL_COMMENT4_ 29
+#define SCE_4GL_COMMENT5_ 30
+#define SCE_4GL_COMMENT6_ 31
+#define SCE_ABAQUS_DEFAULT 0
+#define SCE_ABAQUS_COMMENT 1
+#define SCE_ABAQUS_COMMENTBLOCK 2
+#define SCE_ABAQUS_NUMBER 3
+#define SCE_ABAQUS_STRING 4
+#define SCE_ABAQUS_OPERATOR 5
+#define SCE_ABAQUS_WORD 6
+#define SCE_ABAQUS_PROCESSOR 7
+#define SCE_ABAQUS_COMMAND 8
+#define SCE_ABAQUS_SLASHCOMMAND 9
+#define SCE_ABAQUS_STARCOMMAND 10
+#define SCE_ABAQUS_ARGUMENT 11
+#define SCE_ABAQUS_FUNCTION 12
+#define SCE_ASY_DEFAULT 0
+#define SCE_ASY_COMMENT 1
+#define SCE_ASY_COMMENTLINE 2
+#define SCE_ASY_NUMBER 3
+#define SCE_ASY_WORD 4
+#define SCE_ASY_STRING 5
+#define SCE_ASY_CHARACTER 6
+#define SCE_ASY_OPERATOR 7
+#define SCE_ASY_IDENTIFIER 8
+#define SCE_ASY_STRINGEOL 9
+#define SCE_ASY_COMMENTLINEDOC 10
+#define SCE_ASY_WORD2 11
+#define SCE_R_DEFAULT 0
+#define SCE_R_COMMENT 1
+#define SCE_R_KWORD 2
+#define SCE_R_BASEKWORD 3
+#define SCE_R_OTHERKWORD 4
+#define SCE_R_NUMBER 5
+#define SCE_R_STRING 6
+#define SCE_R_STRING2 7
+#define SCE_R_OPERATOR 8
+#define SCE_R_IDENTIFIER 9
+#define SCE_R_INFIX 10
+#define SCE_R_INFIXEOL 11
+#define SCE_MAGIK_DEFAULT 0
+#define SCE_MAGIK_COMMENT 1
+#define SCE_MAGIK_HYPER_COMMENT 16
+#define SCE_MAGIK_STRING 2
+#define SCE_MAGIK_CHARACTER 3
+#define SCE_MAGIK_NUMBER 4
+#define SCE_MAGIK_IDENTIFIER 5
+#define SCE_MAGIK_OPERATOR 6
+#define SCE_MAGIK_FLOW 7
+#define SCE_MAGIK_CONTAINER 8
+#define SCE_MAGIK_BRACKET_BLOCK 9
+#define SCE_MAGIK_BRACE_BLOCK 10
+#define SCE_MAGIK_SQBRACKET_BLOCK 11
+#define SCE_MAGIK_UNKNOWN_KEYWORD 12
+#define SCE_MAGIK_KEYWORD 13
+#define SCE_MAGIK_PRAGMA 14
+#define SCE_MAGIK_SYMBOL 15
+#define SCE_POWERSHELL_DEFAULT 0
+#define SCE_POWERSHELL_COMMENT 1
+#define SCE_POWERSHELL_STRING 2
+#define SCE_POWERSHELL_CHARACTER 3
+#define SCE_POWERSHELL_NUMBER 4
+#define SCE_POWERSHELL_VARIABLE 5
+#define SCE_POWERSHELL_OPERATOR 6
+#define SCE_POWERSHELL_IDENTIFIER 7
+#define SCE_POWERSHELL_KEYWORD 8
+#define SCE_POWERSHELL_CMDLET 9
+#define SCE_POWERSHELL_ALIAS 10
+#define SCE_MYSQL_DEFAULT 0
+#define SCE_MYSQL_COMMENT 1
+#define SCE_MYSQL_COMMENTLINE 2
+#define SCE_MYSQL_VARIABLE 3
+#define SCE_MYSQL_SYSTEMVARIABLE 4
+#define SCE_MYSQL_KNOWNSYSTEMVARIABLE 5
+#define SCE_MYSQL_NUMBER 6
+#define SCE_MYSQL_MAJORKEYWORD 7
+#define SCE_MYSQL_KEYWORD 8
+#define SCE_MYSQL_DATABASEOBJECT 9
+#define SCE_MYSQL_PROCEDUREKEYWORD 10
+#define SCE_MYSQL_STRING 11
+#define SCE_MYSQL_SQSTRING 12
+#define SCE_MYSQL_DQSTRING 13
+#define SCE_MYSQL_OPERATOR 14
+#define SCE_MYSQL_FUNCTION 15
+#define SCE_MYSQL_IDENTIFIER 16
+#define SCE_MYSQL_QUOTEDIDENTIFIER 17
+#define SCE_MYSQL_USER1 18
+#define SCE_MYSQL_USER2 19
+#define SCE_MYSQL_USER3 20
+#define SCE_MYSQL_HIDDENCOMMAND 21
+#define SCE_PO_DEFAULT 0
+#define SCE_PO_COMMENT 1
+#define SCE_PO_MSGID 2
+#define SCE_PO_MSGID_TEXT 3
+#define SCE_PO_MSGSTR 4
+#define SCE_PO_MSGSTR_TEXT 5
+#define SCE_PO_MSGCTXT 6
+#define SCE_PO_MSGCTXT_TEXT 7
+#define SCE_PO_FUZZY 8
+#define SCE_PAS_DEFAULT 0
+#define SCE_PAS_IDENTIFIER 1
+#define SCE_PAS_COMMENT 2
+#define SCE_PAS_COMMENT2 3
+#define SCE_PAS_COMMENTLINE 4
+#define SCE_PAS_PREPROCESSOR 5
+#define SCE_PAS_PREPROCESSOR2 6
+#define SCE_PAS_NUMBER 7
+#define SCE_PAS_HEXNUMBER 8
+#define SCE_PAS_WORD 9
+#define SCE_PAS_STRING 10
+#define SCE_PAS_STRINGEOL 11
+#define SCE_PAS_CHARACTER 12
+#define SCE_PAS_OPERATOR 13
+#define SCE_PAS_ASM 14
+#define SCE_SORCUS_DEFAULT 0
+#define SCE_SORCUS_COMMAND 1
+#define SCE_SORCUS_PARAMETER 2
+#define SCE_SORCUS_COMMENTLINE 3
+#define SCE_SORCUS_STRING 4
+#define SCE_SORCUS_STRINGEOL 5
+#define SCE_SORCUS_IDENTIFIER 6
+#define SCE_SORCUS_OPERATOR 7
+#define SCE_SORCUS_NUMBER 8
+#define SCE_SORCUS_CONSTANT 9
+#define SCE_POWERPRO_DEFAULT 0
+#define SCE_POWERPRO_COMMENTBLOCK 1
+#define SCE_POWERPRO_COMMENTLINE 2
+#define SCE_POWERPRO_NUMBER 3
+#define SCE_POWERPRO_WORD 4
+#define SCE_POWERPRO_WORD2 5
+#define SCE_POWERPRO_WORD3 6
+#define SCE_POWERPRO_WORD4 7
+#define SCE_POWERPRO_DOUBLEQUOTEDSTRING 8
+#define SCE_POWERPRO_SINGLEQUOTEDSTRING 9
+#define SCE_POWERPRO_LINECONTINUE 10
+#define SCE_POWERPRO_OPERATOR 11
+#define SCE_POWERPRO_IDENTIFIER 12
+#define SCE_POWERPRO_STRINGEOL 13
+#define SCE_POWERPRO_VERBATIM 14
+#define SCE_POWERPRO_ALTQUOTE 15
+#define SCE_POWERPRO_FUNCTION 16
+#define SCE_SML_DEFAULT 0
+#define SCE_SML_IDENTIFIER 1
+#define SCE_SML_TAGNAME 2
+#define SCE_SML_KEYWORD 3
+#define SCE_SML_KEYWORD2 4
+#define SCE_SML_KEYWORD3 5
+#define SCE_SML_LINENUM 6
+#define SCE_SML_OPERATOR 7
+#define SCE_SML_NUMBER 8
+#define SCE_SML_CHAR 9
+#define SCE_SML_STRING 11
+#define SCE_SML_COMMENT 12
+#define SCE_SML_COMMENT1 13
+#define SCE_SML_COMMENT2 14
+#define SCE_SML_COMMENT3 15
+#define SCE_MARKDOWN_DEFAULT 0
+#define SCE_MARKDOWN_LINE_BEGIN 1
+#define SCE_MARKDOWN_STRONG1 2
+#define SCE_MARKDOWN_STRONG2 3
+#define SCE_MARKDOWN_EM1 4
+#define SCE_MARKDOWN_EM2 5
+#define SCE_MARKDOWN_HEADER1 6
+#define SCE_MARKDOWN_HEADER2 7
+#define SCE_MARKDOWN_HEADER3 8
+#define SCE_MARKDOWN_HEADER4 9
+#define SCE_MARKDOWN_HEADER5 10
+#define SCE_MARKDOWN_HEADER6 11
+#define SCE_MARKDOWN_PRECHAR 12
+#define SCE_MARKDOWN_ULIST_ITEM 13
+#define SCE_MARKDOWN_OLIST_ITEM 14
+#define SCE_MARKDOWN_BLOCKQUOTE 15
+#define SCE_MARKDOWN_STRIKEOUT 16
+#define SCE_MARKDOWN_HRULE 17
+#define SCE_MARKDOWN_LINK 18
+#define SCE_MARKDOWN_CODE 19
+#define SCE_MARKDOWN_CODE2 20
+#define SCE_MARKDOWN_CODEBK 21
+/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
+
+#endif
diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h
new file mode 100644
index 0000000..1c98a88
--- /dev/null
+++ b/scintilla/include/Scintilla.h
@@ -0,0 +1,965 @@
+/* Scintilla source code edit control */
+/** @file Scintilla.h
+ ** Interface to the edit control.
+ **/
+/* Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+ * The License.txt file describes the conditions under which this software may be distributed. */
+
+/* Most of this file is automatically generated from the Scintilla.iface interface definition
+ * file which contains any comments about the definitions. HFacer.py does the generation. */
+
+#ifndef SCINTILLA_H
+#define SCINTILLA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_WIN32)
+/* Return false on failure: */
+int Scintilla_RegisterClasses(void *hInstance);
+int Scintilla_ReleaseResources();
+#endif
+int Scintilla_LinkLexers();
+
+#ifdef __cplusplus
+}
+#endif
+
+/* 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. */
+#if defined(_WIN32)
+#include <basetsd.h>
+#endif
+#ifdef MAXULONG_PTR
+typedef ULONG_PTR uptr_t;
+typedef LONG_PTR sptr_t;
+#else
+typedef unsigned long uptr_t;
+typedef long sptr_t;
+#endif
+
+typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
+#define INVALID_POSITION -1
+#define SCI_START 2000
+#define SCI_OPTIONAL_START 3000
+#define SCI_LEXER_START 4000
+#define SCI_ADDTEXT 2001
+#define SCI_ADDSTYLEDTEXT 2002
+#define SCI_INSERTTEXT 2003
+#define SCI_CLEARALL 2004
+#define SCI_CLEARDOCUMENTSTYLE 2005
+#define SCI_GETLENGTH 2006
+#define SCI_GETCHARAT 2007
+#define SCI_GETCURRENTPOS 2008
+#define SCI_GETANCHOR 2009
+#define SCI_GETSTYLEAT 2010
+#define SCI_REDO 2011
+#define SCI_SETUNDOCOLLECTION 2012
+#define SCI_SELECTALL 2013
+#define SCI_SETSAVEPOINT 2014
+#define SCI_GETSTYLEDTEXT 2015
+#define SCI_CANREDO 2016
+#define SCI_MARKERLINEFROMHANDLE 2017
+#define SCI_MARKERDELETEHANDLE 2018
+#define SCI_GETUNDOCOLLECTION 2019
+#define SCWS_INVISIBLE 0
+#define SCWS_VISIBLEALWAYS 1
+#define SCWS_VISIBLEAFTERINDENT 2
+#define SCI_GETVIEWWS 2020
+#define SCI_SETVIEWWS 2021
+#define SCI_POSITIONFROMPOINT 2022
+#define SCI_POSITIONFROMPOINTCLOSE 2023
+#define SCI_GOTOLINE 2024
+#define SCI_GOTOPOS 2025
+#define SCI_SETANCHOR 2026
+#define SCI_GETCURLINE 2027
+#define SCI_GETENDSTYLED 2028
+#define SC_EOL_CRLF 0
+#define SC_EOL_CR 1
+#define SC_EOL_LF 2
+#define SCI_CONVERTEOLS 2029
+#define SCI_GETEOLMODE 2030
+#define SCI_SETEOLMODE 2031
+#define SCI_STARTSTYLING 2032
+#define SCI_SETSTYLING 2033
+#define SCI_GETBUFFEREDDRAW 2034
+#define SCI_SETBUFFEREDDRAW 2035
+#define SCI_SETTABWIDTH 2036
+#define SCI_GETTABWIDTH 2121
+#define SC_CP_UTF8 65001
+#define SC_CP_DBCS 1
+#define SCI_SETCODEPAGE 2037
+#define SCI_SETUSEPALETTE 2039
+#define MARKER_MAX 31
+#define SC_MARK_CIRCLE 0
+#define SC_MARK_ROUNDRECT 1
+#define SC_MARK_ARROW 2
+#define SC_MARK_SMALLRECT 3
+#define SC_MARK_SHORTARROW 4
+#define SC_MARK_EMPTY 5
+#define SC_MARK_ARROWDOWN 6
+#define SC_MARK_MINUS 7
+#define SC_MARK_PLUS 8
+#define SC_MARK_VLINE 9
+#define SC_MARK_LCORNER 10
+#define SC_MARK_TCORNER 11
+#define SC_MARK_BOXPLUS 12
+#define SC_MARK_BOXPLUSCONNECTED 13
+#define SC_MARK_BOXMINUS 14
+#define SC_MARK_BOXMINUSCONNECTED 15
+#define SC_MARK_LCORNERCURVE 16
+#define SC_MARK_TCORNERCURVE 17
+#define SC_MARK_CIRCLEPLUS 18
+#define SC_MARK_CIRCLEPLUSCONNECTED 19
+#define SC_MARK_CIRCLEMINUS 20
+#define SC_MARK_CIRCLEMINUSCONNECTED 21
+#define SC_MARK_BACKGROUND 22
+#define SC_MARK_DOTDOTDOT 23
+#define SC_MARK_ARROWS 24
+#define SC_MARK_PIXMAP 25
+#define SC_MARK_FULLRECT 26
+#define SC_MARK_LEFTRECT 27
+#define SC_MARK_AVAILABLE 28
+#define SC_MARK_UNDERLINE 29
+#define SC_MARK_CHARACTER 10000
+#define SC_MARKNUM_FOLDEREND 25
+#define SC_MARKNUM_FOLDEROPENMID 26
+#define SC_MARKNUM_FOLDERMIDTAIL 27
+#define SC_MARKNUM_FOLDERTAIL 28
+#define SC_MARKNUM_FOLDERSUB 29
+#define SC_MARKNUM_FOLDER 30
+#define SC_MARKNUM_FOLDEROPEN 31
+#define SC_MASK_FOLDERS 0xFE000000
+#define SCI_MARKERDEFINE 2040
+#define SCI_MARKERSETFORE 2041
+#define SCI_MARKERSETBACK 2042
+#define SCI_MARKERADD 2043
+#define SCI_MARKERDELETE 2044
+#define SCI_MARKERDELETEALL 2045
+#define SCI_MARKERGET 2046
+#define SCI_MARKERNEXT 2047
+#define SCI_MARKERPREVIOUS 2048
+#define SCI_MARKERDEFINEPIXMAP 2049
+#define SCI_MARKERADDSET 2466
+#define SCI_MARKERSETALPHA 2476
+#define SC_MARGIN_SYMBOL 0
+#define SC_MARGIN_NUMBER 1
+#define SC_MARGIN_BACK 2
+#define SC_MARGIN_FORE 3
+#define SC_MARGIN_TEXT 4
+#define SC_MARGIN_RTEXT 5
+#define SCI_SETMARGINTYPEN 2240
+#define SCI_GETMARGINTYPEN 2241
+#define SCI_SETMARGINWIDTHN 2242
+#define SCI_GETMARGINWIDTHN 2243
+#define SCI_SETMARGINMASKN 2244
+#define SCI_GETMARGINMASKN 2245
+#define SCI_SETMARGINSENSITIVEN 2246
+#define SCI_GETMARGINSENSITIVEN 2247
+#define STYLE_DEFAULT 32
+#define STYLE_LINENUMBER 33
+#define STYLE_BRACELIGHT 34
+#define STYLE_BRACEBAD 35
+#define STYLE_CONTROLCHAR 36
+#define STYLE_INDENTGUIDE 37
+#define STYLE_CALLTIP 38
+#define STYLE_LASTPREDEFINED 39
+#define STYLE_MAX 255
+#define SC_CHARSET_ANSI 0
+#define SC_CHARSET_DEFAULT 1
+#define SC_CHARSET_BALTIC 186
+#define SC_CHARSET_CHINESEBIG5 136
+#define SC_CHARSET_EASTEUROPE 238
+#define SC_CHARSET_GB2312 134
+#define SC_CHARSET_GREEK 161
+#define SC_CHARSET_HANGUL 129
+#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
+#define SC_CHARSET_JOHAB 130
+#define SC_CHARSET_HEBREW 177
+#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
+#define SCI_STYLESETBOLD 2053
+#define SCI_STYLESETITALIC 2054
+#define SCI_STYLESETSIZE 2055
+#define SCI_STYLESETFONT 2056
+#define SCI_STYLESETEOLFILLED 2057
+#define SCI_STYLERESETDEFAULT 2058
+#define SCI_STYLESETUNDERLINE 2059
+#define SC_CASE_MIXED 0
+#define SC_CASE_UPPER 1
+#define SC_CASE_LOWER 2
+#define SCI_STYLEGETFORE 2481
+#define SCI_STYLEGETBACK 2482
+#define SCI_STYLEGETBOLD 2483
+#define SCI_STYLEGETITALIC 2484
+#define SCI_STYLEGETSIZE 2485
+#define SCI_STYLEGETFONT 2486
+#define SCI_STYLEGETEOLFILLED 2487
+#define SCI_STYLEGETUNDERLINE 2488
+#define SCI_STYLEGETCASE 2489
+#define SCI_STYLEGETCHARACTERSET 2490
+#define SCI_STYLEGETVISIBLE 2491
+#define SCI_STYLEGETCHANGEABLE 2492
+#define SCI_STYLEGETHOTSPOT 2493
+#define SCI_STYLESETCASE 2060
+#define SCI_STYLESETCHARACTERSET 2066
+#define SCI_STYLESETHOTSPOT 2409
+#define SCI_SETSELFORE 2067
+#define SCI_SETSELBACK 2068
+#define SCI_GETSELALPHA 2477
+#define SCI_SETSELALPHA 2478
+#define SCI_GETSELEOLFILLED 2479
+#define SCI_SETSELEOLFILLED 2480
+#define SCI_SETCARETFORE 2069
+#define SCI_ASSIGNCMDKEY 2070
+#define SCI_CLEARCMDKEY 2071
+#define SCI_CLEARALLCMDKEYS 2072
+#define SCI_SETSTYLINGEX 2073
+#define SCI_STYLESETVISIBLE 2074
+#define SCI_GETCARETPERIOD 2075
+#define SCI_SETCARETPERIOD 2076
+#define SCI_SETWORDCHARS 2077
+#define SCI_BEGINUNDOACTION 2078
+#define SCI_ENDUNDOACTION 2079
+#define INDIC_PLAIN 0
+#define INDIC_SQUIGGLE 1
+#define INDIC_TT 2
+#define INDIC_DIAGONAL 3
+#define INDIC_STRIKE 4
+#define INDIC_HIDDEN 5
+#define INDIC_BOX 6
+#define INDIC_ROUNDBOX 7
+#define INDIC_MAX 31
+#define INDIC_CONTAINER 8
+#define INDIC0_MASK 0x20
+#define INDIC1_MASK 0x40
+#define INDIC2_MASK 0x80
+#define INDICS_MASK 0xE0
+#define SCI_INDICSETSTYLE 2080
+#define SCI_INDICGETSTYLE 2081
+#define SCI_INDICSETFORE 2082
+#define SCI_INDICGETFORE 2083
+#define SCI_INDICSETUNDER 2510
+#define SCI_INDICGETUNDER 2511
+#define SCI_SETWHITESPACEFORE 2084
+#define SCI_SETWHITESPACEBACK 2085
+#define SCI_SETWHITESPACESIZE 2086
+#define SCI_GETWHITESPACESIZE 2087
+#define SCI_SETSTYLEBITS 2090
+#define SCI_GETSTYLEBITS 2091
+#define SCI_SETLINESTATE 2092
+#define SCI_GETLINESTATE 2093
+#define SCI_GETMAXLINESTATE 2094
+#define SCI_GETCARETLINEVISIBLE 2095
+#define SCI_SETCARETLINEVISIBLE 2096
+#define SCI_GETCARETLINEBACK 2097
+#define SCI_SETCARETLINEBACK 2098
+#define SCI_STYLESETCHANGEABLE 2099
+#define SCI_AUTOCSHOW 2100
+#define SCI_AUTOCCANCEL 2101
+#define SCI_AUTOCACTIVE 2102
+#define SCI_AUTOCPOSSTART 2103
+#define SCI_AUTOCCOMPLETE 2104
+#define SCI_AUTOCSTOPS 2105
+#define SCI_AUTOCSETSEPARATOR 2106
+#define SCI_AUTOCGETSEPARATOR 2107
+#define SCI_AUTOCSELECT 2108
+#define SCI_AUTOCSETCANCELATSTART 2110
+#define SCI_AUTOCGETCANCELATSTART 2111
+#define SCI_AUTOCSETFILLUPS 2112
+#define SCI_AUTOCSETCHOOSESINGLE 2113
+#define SCI_AUTOCGETCHOOSESINGLE 2114
+#define SCI_AUTOCSETIGNORECASE 2115
+#define SCI_AUTOCGETIGNORECASE 2116
+#define SCI_USERLISTSHOW 2117
+#define SCI_AUTOCSETAUTOHIDE 2118
+#define SCI_AUTOCGETAUTOHIDE 2119
+#define SCI_AUTOCSETDROPRESTOFWORD 2270
+#define SCI_AUTOCGETDROPRESTOFWORD 2271
+#define SCI_REGISTERIMAGE 2405
+#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
+#define SCI_GETUSETABS 2125
+#define SCI_SETLINEINDENTATION 2126
+#define SCI_GETLINEINDENTATION 2127
+#define SCI_GETLINEINDENTPOSITION 2128
+#define SCI_GETCOLUMN 2129
+#define SCI_SETHSCROLLBAR 2130
+#define SCI_GETHSCROLLBAR 2131
+#define SC_IV_NONE 0
+#define SC_IV_REAL 1
+#define SC_IV_LOOKFORWARD 2
+#define SC_IV_LOOKBOTH 3
+#define SCI_SETINDENTATIONGUIDES 2132
+#define SCI_GETINDENTATIONGUIDES 2133
+#define SCI_SETHIGHLIGHTGUIDE 2134
+#define SCI_GETHIGHLIGHTGUIDE 2135
+#define SCI_GETLINEENDPOSITION 2136
+#define SCI_GETCODEPAGE 2137
+#define SCI_GETCARETFORE 2138
+#define SCI_GETUSEPALETTE 2139
+#define SCI_GETREADONLY 2140
+#define SCI_SETCURRENTPOS 2141
+#define SCI_SETSELECTIONSTART 2142
+#define SCI_GETSELECTIONSTART 2143
+#define SCI_SETSELECTIONEND 2144
+#define SCI_GETSELECTIONEND 2145
+#define SCI_SETPRINTMAGNIFICATION 2146
+#define SCI_GETPRINTMAGNIFICATION 2147
+#define SC_PRINT_NORMAL 0
+#define SC_PRINT_INVERTLIGHT 1
+#define SC_PRINT_BLACKONWHITE 2
+#define SC_PRINT_COLOURONWHITE 3
+#define SC_PRINT_COLOURONWHITEDEFAULTBG 4
+#define SCI_SETPRINTCOLOURMODE 2148
+#define SCI_GETPRINTCOLOURMODE 2149
+#define SCFIND_WHOLEWORD 2
+#define SCFIND_MATCHCASE 4
+#define SCFIND_WORDSTART 0x00100000
+#define SCFIND_REGEXP 0x00200000
+#define SCFIND_POSIX 0x00400000
+#define SCI_FINDTEXT 2150
+#define SCI_FORMATRANGE 2151
+#define SCI_GETFIRSTVISIBLELINE 2152
+#define SCI_GETLINE 2153
+#define SCI_GETLINECOUNT 2154
+#define SCI_SETMARGINLEFT 2155
+#define SCI_GETMARGINLEFT 2156
+#define SCI_SETMARGINRIGHT 2157
+#define SCI_GETMARGINRIGHT 2158
+#define SCI_GETMODIFY 2159
+#define SCI_SETSEL 2160
+#define SCI_GETSELTEXT 2161
+#define SCI_GETTEXTRANGE 2162
+#define SCI_HIDESELECTION 2163
+#define SCI_POINTXFROMPOSITION 2164
+#define SCI_POINTYFROMPOSITION 2165
+#define SCI_LINEFROMPOSITION 2166
+#define SCI_POSITIONFROMLINE 2167
+#define SCI_LINESCROLL 2168
+#define SCI_SCROLLCARET 2169
+#define SCI_REPLACESEL 2170
+#define SCI_SETREADONLY 2171
+#define SCI_NULL 2172
+#define SCI_CANPASTE 2173
+#define SCI_CANUNDO 2174
+#define SCI_EMPTYUNDOBUFFER 2175
+#define SCI_UNDO 2176
+#define SCI_CUT 2177
+#define SCI_COPY 2178
+#define SCI_PASTE 2179
+#define SCI_CLEAR 2180
+#define SCI_SETTEXT 2181
+#define SCI_GETTEXT 2182
+#define SCI_GETTEXTLENGTH 2183
+#define SCI_GETDIRECTFUNCTION 2184
+#define SCI_GETDIRECTPOINTER 2185
+#define SCI_SETOVERTYPE 2186
+#define SCI_GETOVERTYPE 2187
+#define SCI_SETCARETWIDTH 2188
+#define SCI_GETCARETWIDTH 2189
+#define SCI_SETTARGETSTART 2190
+#define SCI_GETTARGETSTART 2191
+#define SCI_SETTARGETEND 2192
+#define SCI_GETTARGETEND 2193
+#define SCI_REPLACETARGET 2194
+#define SCI_REPLACETARGETRE 2195
+#define SCI_SEARCHINTARGET 2197
+#define SCI_SETSEARCHFLAGS 2198
+#define SCI_GETSEARCHFLAGS 2199
+#define SCI_CALLTIPSHOW 2200
+#define SCI_CALLTIPCANCEL 2201
+#define SCI_CALLTIPACTIVE 2202
+#define SCI_CALLTIPPOSSTART 2203
+#define SCI_CALLTIPSETHLT 2204
+#define SCI_CALLTIPSETBACK 2205
+#define SCI_CALLTIPSETFORE 2206
+#define SCI_CALLTIPSETFOREHLT 2207
+#define SCI_CALLTIPUSESTYLE 2212
+#define SCI_VISIBLEFROMDOCLINE 2220
+#define SCI_DOCLINEFROMVISIBLE 2221
+#define SCI_WRAPCOUNT 2235
+#define SC_FOLDLEVELBASE 0x400
+#define SC_FOLDLEVELWHITEFLAG 0x1000
+#define SC_FOLDLEVELHEADERFLAG 0x2000
+#define SC_FOLDLEVELNUMBERMASK 0x0FFF
+#define SCI_SETFOLDLEVEL 2222
+#define SCI_GETFOLDLEVEL 2223
+#define SCI_GETLASTCHILD 2224
+#define SCI_GETFOLDPARENT 2225
+#define SCI_SHOWLINES 2226
+#define SCI_HIDELINES 2227
+#define SCI_GETLINEVISIBLE 2228
+#define SCI_SETFOLDEXPANDED 2229
+#define SCI_GETFOLDEXPANDED 2230
+#define SCI_TOGGLEFOLD 2231
+#define SCI_ENSUREVISIBLE 2232
+#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
+#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
+#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008
+#define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010
+#define SC_FOLDFLAG_LEVELNUMBERS 0x0040
+#define SCI_SETFOLDFLAGS 2233
+#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234
+#define SCI_SETTABINDENTS 2260
+#define SCI_GETTABINDENTS 2261
+#define SCI_SETBACKSPACEUNINDENTS 2262
+#define SCI_GETBACKSPACEUNINDENTS 2263
+#define SC_TIME_FOREVER 10000000
+#define SCI_SETMOUSEDWELLTIME 2264
+#define SCI_GETMOUSEDWELLTIME 2265
+#define SCI_WORDSTARTPOSITION 2266
+#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
+#define SC_WRAPVISUALFLAG_END 0x0001
+#define SC_WRAPVISUALFLAG_START 0x0002
+#define SCI_SETWRAPVISUALFLAGS 2460
+#define SCI_GETWRAPVISUALFLAGS 2461
+#define SC_WRAPVISUALFLAGLOC_DEFAULT 0x0000
+#define SC_WRAPVISUALFLAGLOC_END_BY_TEXT 0x0001
+#define SC_WRAPVISUALFLAGLOC_START_BY_TEXT 0x0002
+#define SCI_SETWRAPVISUALFLAGSLOCATION 2462
+#define SCI_GETWRAPVISUALFLAGSLOCATION 2463
+#define SCI_SETWRAPSTARTINDENT 2464
+#define SCI_GETWRAPSTARTINDENT 2465
+#define SC_WRAPINDENT_FIXED 0
+#define SC_WRAPINDENT_SAME 1
+#define SC_WRAPINDENT_INDENT 2
+#define SCI_SETWRAPINDENTMODE 2472
+#define SCI_GETWRAPINDENTMODE 2473
+#define SC_CACHE_NONE 0
+#define SC_CACHE_CARET 1
+#define SC_CACHE_PAGE 2
+#define SC_CACHE_DOCUMENT 3
+#define SCI_SETLAYOUTCACHE 2272
+#define SCI_GETLAYOUTCACHE 2273
+#define SCI_SETSCROLLWIDTH 2274
+#define SCI_GETSCROLLWIDTH 2275
+#define SCI_SETSCROLLWIDTHTRACKING 2516
+#define SCI_GETSCROLLWIDTHTRACKING 2517
+#define SCI_TEXTWIDTH 2276
+#define SCI_SETENDATLASTLINE 2277
+#define SCI_GETENDATLASTLINE 2278
+#define SCI_TEXTHEIGHT 2279
+#define SCI_SETVSCROLLBAR 2280
+#define SCI_GETVSCROLLBAR 2281
+#define SCI_APPENDTEXT 2282
+#define SCI_GETTWOPHASEDRAW 2283
+#define SCI_SETTWOPHASEDRAW 2284
+#define SC_EFF_QUALITY_MASK 0xF
+#define SC_EFF_QUALITY_DEFAULT 0
+#define SC_EFF_QUALITY_NON_ANTIALIASED 1
+#define SC_EFF_QUALITY_ANTIALIASED 2
+#define SC_EFF_QUALITY_LCD_OPTIMIZED 3
+#define SCI_SETFONTQUALITY 2611
+#define SCI_GETFONTQUALITY 2612
+#define SCI_SETFIRSTVISIBLELINE 2613
+#define SC_MULTIPASTE_ONCE 0
+#define SC_MULTIPASTE_EACH 1
+#define SCI_SETMULTIPASTE 2614
+#define SCI_GETMULTIPASTE 2615
+#define SCI_GETTAG 2616
+#define SCI_TARGETFROMSELECTION 2287
+#define SCI_LINESJOIN 2288
+#define SCI_LINESSPLIT 2289
+#define SCI_SETFOLDMARGINCOLOUR 2290
+#define SCI_SETFOLDMARGINHICOLOUR 2291
+#define SCI_LINEDOWN 2300
+#define SCI_LINEDOWNEXTEND 2301
+#define SCI_LINEUP 2302
+#define SCI_LINEUPEXTEND 2303
+#define SCI_CHARLEFT 2304
+#define SCI_CHARLEFTEXTEND 2305
+#define SCI_CHARRIGHT 2306
+#define SCI_CHARRIGHTEXTEND 2307
+#define SCI_WORDLEFT 2308
+#define SCI_WORDLEFTEXTEND 2309
+#define SCI_WORDRIGHT 2310
+#define SCI_WORDRIGHTEXTEND 2311
+#define SCI_HOME 2312
+#define SCI_HOMEEXTEND 2313
+#define SCI_LINEEND 2314
+#define SCI_LINEENDEXTEND 2315
+#define SCI_DOCUMENTSTART 2316
+#define SCI_DOCUMENTSTARTEXTEND 2317
+#define SCI_DOCUMENTEND 2318
+#define SCI_DOCUMENTENDEXTEND 2319
+#define SCI_PAGEUP 2320
+#define SCI_PAGEUPEXTEND 2321
+#define SCI_PAGEDOWN 2322
+#define SCI_PAGEDOWNEXTEND 2323
+#define SCI_EDITTOGGLEOVERTYPE 2324
+#define SCI_CANCEL 2325
+#define SCI_DELETEBACK 2326
+#define SCI_TAB 2327
+#define SCI_BACKTAB 2328
+#define SCI_NEWLINE 2329
+#define SCI_FORMFEED 2330
+#define SCI_VCHOME 2331
+#define SCI_VCHOMEEXTEND 2332
+#define SCI_ZOOMIN 2333
+#define SCI_ZOOMOUT 2334
+#define SCI_DELWORDLEFT 2335
+#define SCI_DELWORDRIGHT 2336
+#define SCI_DELWORDRIGHTEND 2518
+#define SCI_LINECUT 2337
+#define SCI_LINEDELETE 2338
+#define SCI_LINETRANSPOSE 2339
+#define SCI_LINEDUPLICATE 2404
+#define SCI_LOWERCASE 2340
+#define SCI_UPPERCASE 2341
+#define SCI_LINESCROLLDOWN 2342
+#define SCI_LINESCROLLUP 2343
+#define SCI_DELETEBACKNOTLINE 2344
+#define SCI_HOMEDISPLAY 2345
+#define SCI_HOMEDISPLAYEXTEND 2346
+#define SCI_LINEENDDISPLAY 2347
+#define SCI_LINEENDDISPLAYEXTEND 2348
+#define SCI_HOMEWRAP 2349
+#define SCI_HOMEWRAPEXTEND 2450
+#define SCI_LINEENDWRAP 2451
+#define SCI_LINEENDWRAPEXTEND 2452
+#define SCI_VCHOMEWRAP 2453
+#define SCI_VCHOMEWRAPEXTEND 2454
+#define SCI_LINECOPY 2455
+#define SCI_MOVECARETINSIDEVIEW 2401
+#define SCI_LINELENGTH 2350
+#define SCI_BRACEHIGHLIGHT 2351
+#define SCI_BRACEBADLIGHT 2352
+#define SCI_BRACEMATCH 2353
+#define SCI_GETVIEWEOL 2355
+#define SCI_SETVIEWEOL 2356
+#define SCI_GETDOCPOINTER 2357
+#define SCI_SETDOCPOINTER 2358
+#define SCI_SETMODEVENTMASK 2359
+#define EDGE_NONE 0
+#define EDGE_LINE 1
+#define EDGE_BACKGROUND 2
+#define SCI_GETEDGECOLUMN 2360
+#define SCI_SETEDGECOLUMN 2361
+#define SCI_GETEDGEMODE 2362
+#define SCI_SETEDGEMODE 2363
+#define SCI_GETEDGECOLOUR 2364
+#define SCI_SETEDGECOLOUR 2365
+#define SCI_SEARCHANCHOR 2366
+#define SCI_SEARCHNEXT 2367
+#define SCI_SEARCHPREV 2368
+#define SCI_LINESONSCREEN 2370
+#define SCI_USEPOPUP 2371
+#define SCI_SELECTIONISRECTANGLE 2372
+#define SCI_SETZOOM 2373
+#define SCI_GETZOOM 2374
+#define SCI_CREATEDOCUMENT 2375
+#define SCI_ADDREFDOCUMENT 2376
+#define SCI_RELEASEDOCUMENT 2377
+#define SCI_GETMODEVENTMASK 2378
+#define SCI_SETFOCUS 2380
+#define SCI_GETFOCUS 2381
+#define SC_STATUS_OK 0
+#define SC_STATUS_FAILURE 1
+#define SC_STATUS_BADALLOC 2
+#define SCI_SETSTATUS 2382
+#define SCI_GETSTATUS 2383
+#define SCI_SETMOUSEDOWNCAPTURES 2384
+#define SCI_GETMOUSEDOWNCAPTURES 2385
+#define SC_CURSORNORMAL -1
+#define SC_CURSORWAIT 4
+#define SCI_SETCURSOR 2386
+#define SCI_GETCURSOR 2387
+#define SCI_SETCONTROLCHARSYMBOL 2388
+#define SCI_GETCONTROLCHARSYMBOL 2389
+#define SCI_WORDPARTLEFT 2390
+#define SCI_WORDPARTLEFTEXTEND 2391
+#define SCI_WORDPARTRIGHT 2392
+#define SCI_WORDPARTRIGHTEXTEND 2393
+#define VISIBLE_SLOP 0x01
+#define VISIBLE_STRICT 0x04
+#define SCI_SETVISIBLEPOLICY 2394
+#define SCI_DELLINELEFT 2395
+#define SCI_DELLINERIGHT 2396
+#define SCI_SETXOFFSET 2397
+#define SCI_GETXOFFSET 2398
+#define SCI_CHOOSECARETX 2399
+#define SCI_GRABFOCUS 2400
+#define CARET_SLOP 0x01
+#define CARET_STRICT 0x04
+#define CARET_JUMPS 0x10
+#define CARET_EVEN 0x08
+#define SCI_SETXCARETPOLICY 2402
+#define SCI_SETYCARETPOLICY 2403
+#define SCI_SETPRINTWRAPMODE 2406
+#define SCI_GETPRINTWRAPMODE 2407
+#define SCI_SETHOTSPOTACTIVEFORE 2410
+#define SCI_GETHOTSPOTACTIVEFORE 2494
+#define SCI_SETHOTSPOTACTIVEBACK 2411
+#define SCI_GETHOTSPOTACTIVEBACK 2495
+#define SCI_SETHOTSPOTACTIVEUNDERLINE 2412
+#define SCI_GETHOTSPOTACTIVEUNDERLINE 2496
+#define SCI_SETHOTSPOTSINGLELINE 2421
+#define SCI_GETHOTSPOTSINGLELINE 2497
+#define SCI_PARADOWN 2413
+#define SCI_PARADOWNEXTEND 2414
+#define SCI_PARAUP 2415
+#define SCI_PARAUPEXTEND 2416
+#define SCI_POSITIONBEFORE 2417
+#define SCI_POSITIONAFTER 2418
+#define SCI_COPYRANGE 2419
+#define SCI_COPYTEXT 2420
+#define SC_SEL_STREAM 0
+#define SC_SEL_RECTANGLE 1
+#define SC_SEL_LINES 2
+#define SC_SEL_THIN 3
+#define SCI_SETSELECTIONMODE 2422
+#define SCI_GETSELECTIONMODE 2423
+#define SCI_GETLINESELSTARTPOSITION 2424
+#define SCI_GETLINESELENDPOSITION 2425
+#define SCI_LINEDOWNRECTEXTEND 2426
+#define SCI_LINEUPRECTEXTEND 2427
+#define SCI_CHARLEFTRECTEXTEND 2428
+#define SCI_CHARRIGHTRECTEXTEND 2429
+#define SCI_HOMERECTEXTEND 2430
+#define SCI_VCHOMERECTEXTEND 2431
+#define SCI_LINEENDRECTEXTEND 2432
+#define SCI_PAGEUPRECTEXTEND 2433
+#define SCI_PAGEDOWNRECTEXTEND 2434
+#define SCI_STUTTEREDPAGEUP 2435
+#define SCI_STUTTEREDPAGEUPEXTEND 2436
+#define SCI_STUTTEREDPAGEDOWN 2437
+#define SCI_STUTTEREDPAGEDOWNEXTEND 2438
+#define SCI_WORDLEFTEND 2439
+#define SCI_WORDLEFTENDEXTEND 2440
+#define SCI_WORDRIGHTEND 2441
+#define SCI_WORDRIGHTENDEXTEND 2442
+#define SCI_SETWHITESPACECHARS 2443
+#define SCI_SETCHARSDEFAULT 2444
+#define SCI_AUTOCGETCURRENT 2445
+#define SCI_AUTOCGETCURRENTTEXT 2610
+#define SCI_ALLOCATE 2446
+#define SCI_TARGETASUTF8 2447
+#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 SC_ALPHA_TRANSPARENT 0
+#define SC_ALPHA_OPAQUE 255
+#define SC_ALPHA_NOALPHA 256
+#define SCI_SETCARETLINEBACKALPHA 2470
+#define SCI_GETCARETLINEBACKALPHA 2471
+#define CARETSTYLE_INVISIBLE 0
+#define CARETSTYLE_LINE 1
+#define CARETSTYLE_BLOCK 2
+#define SCI_SETCARETSTYLE 2512
+#define SCI_GETCARETSTYLE 2513
+#define SCI_SETINDICATORCURRENT 2500
+#define SCI_GETINDICATORCURRENT 2501
+#define SCI_SETINDICATORVALUE 2502
+#define SCI_GETINDICATORVALUE 2503
+#define SCI_INDICATORFILLRANGE 2504
+#define SCI_INDICATORCLEARRANGE 2505
+#define SCI_INDICATORALLONFOR 2506
+#define SCI_INDICATORVALUEAT 2507
+#define SCI_INDICATORSTART 2508
+#define SCI_INDICATOREND 2509
+#define SCI_SETPOSITIONCACHE 2514
+#define SCI_GETPOSITIONCACHE 2515
+#define SCI_COPYALLOWLINE 2519
+#define SCI_GETCHARACTERPOINTER 2520
+#define SCI_SETKEYSUNICODE 2521
+#define SCI_GETKEYSUNICODE 2522
+#define SCI_INDICSETALPHA 2523
+#define SCI_INDICGETALPHA 2524
+#define SCI_SETEXTRAASCENT 2525
+#define SCI_GETEXTRAASCENT 2526
+#define SCI_SETEXTRADESCENT 2527
+#define SCI_GETEXTRADESCENT 2528
+#define SCI_MARKERSYMBOLDEFINED 2529
+#define SCI_MARGINSETTEXT 2530
+#define SCI_MARGINGETTEXT 2531
+#define SCI_MARGINSETSTYLE 2532
+#define SCI_MARGINGETSTYLE 2533
+#define SCI_MARGINSETSTYLES 2534
+#define SCI_MARGINGETSTYLES 2535
+#define SCI_MARGINTEXTCLEARALL 2536
+#define SCI_MARGINSETSTYLEOFFSET 2537
+#define SCI_MARGINGETSTYLEOFFSET 2538
+#define SCI_ANNOTATIONSETTEXT 2540
+#define SCI_ANNOTATIONGETTEXT 2541
+#define SCI_ANNOTATIONSETSTYLE 2542
+#define SCI_ANNOTATIONGETSTYLE 2543
+#define SCI_ANNOTATIONSETSTYLES 2544
+#define SCI_ANNOTATIONGETSTYLES 2545
+#define SCI_ANNOTATIONGETLINES 2546
+#define SCI_ANNOTATIONCLEARALL 2547
+#define ANNOTATION_HIDDEN 0
+#define ANNOTATION_STANDARD 1
+#define ANNOTATION_BOXED 2
+#define SCI_ANNOTATIONSETVISIBLE 2548
+#define SCI_ANNOTATIONGETVISIBLE 2549
+#define SCI_ANNOTATIONSETSTYLEOFFSET 2550
+#define SCI_ANNOTATIONGETSTYLEOFFSET 2551
+#define UNDO_MAY_COALESCE 1
+#define SCI_ADDUNDOACTION 2560
+#define SCI_CHARPOSITIONFROMPOINT 2561
+#define SCI_CHARPOSITIONFROMPOINTCLOSE 2562
+#define SCI_SETMULTIPLESELECTION 2563
+#define SCI_GETMULTIPLESELECTION 2564
+#define SCI_SETADDITIONALSELECTIONTYPING 2565
+#define SCI_GETADDITIONALSELECTIONTYPING 2566
+#define SCI_SETADDITIONALCARETSBLINK 2567
+#define SCI_GETADDITIONALCARETSBLINK 2568
+#define SCI_SETADDITIONALCARETSVISIBLE 2608
+#define SCI_GETADDITIONALCARETSVISIBLE 2609
+#define SCI_GETSELECTIONS 2570
+#define SCI_CLEARSELECTIONS 2571
+#define SCI_SETSELECTION 2572
+#define SCI_ADDSELECTION 2573
+#define SCI_SETMAINSELECTION 2574
+#define SCI_GETMAINSELECTION 2575
+#define SCI_SETSELECTIONNCARET 2576
+#define SCI_GETSELECTIONNCARET 2577
+#define SCI_SETSELECTIONNANCHOR 2578
+#define SCI_GETSELECTIONNANCHOR 2579
+#define SCI_SETSELECTIONNCARETVIRTUALSPACE 2580
+#define SCI_GETSELECTIONNCARETVIRTUALSPACE 2581
+#define SCI_SETSELECTIONNANCHORVIRTUALSPACE 2582
+#define SCI_GETSELECTIONNANCHORVIRTUALSPACE 2583
+#define SCI_SETSELECTIONNSTART 2584
+#define SCI_GETSELECTIONNSTART 2585
+#define SCI_SETSELECTIONNEND 2586
+#define SCI_GETSELECTIONNEND 2587
+#define SCI_SETRECTANGULARSELECTIONCARET 2588
+#define SCI_GETRECTANGULARSELECTIONCARET 2589
+#define SCI_SETRECTANGULARSELECTIONANCHOR 2590
+#define SCI_GETRECTANGULARSELECTIONANCHOR 2591
+#define SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE 2592
+#define SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE 2593
+#define SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2594
+#define SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2595
+#define SCVS_NONE 0
+#define SCVS_RECTANGULARSELECTION 1
+#define SCVS_USERACCESSIBLE 2
+#define SCI_SETVIRTUALSPACEOPTIONS 2596
+#define SCI_GETVIRTUALSPACEOPTIONS 2597
+#define SCI_SETRECTANGULARSELECTIONMODIFIER 2598
+#define SCI_GETRECTANGULARSELECTIONMODIFIER 2599
+#define SCI_SETADDITIONALSELFORE 2600
+#define SCI_SETADDITIONALSELBACK 2601
+#define SCI_SETADDITIONALSELALPHA 2602
+#define SCI_GETADDITIONALSELALPHA 2603
+#define SCI_SETADDITIONALCARETFORE 2604
+#define SCI_GETADDITIONALCARETFORE 2605
+#define SCI_ROTATESELECTION 2606
+#define SCI_SWAPMAINANCHORCARET 2607
+#define SCI_STARTRECORD 3001
+#define SCI_STOPRECORD 3002
+#define SCI_SETLEXER 4001
+#define SCI_GETLEXER 4002
+#define SCI_COLOURISE 4003
+#define SCI_SETPROPERTY 4004
+#define KEYWORDSET_MAX 8
+#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 SCI_GETLEXERLANGUAGE 4012
+#define SC_MOD_INSERTTEXT 0x1
+#define SC_MOD_DELETETEXT 0x2
+#define SC_MOD_CHANGESTYLE 0x4
+#define SC_MOD_CHANGEFOLD 0x8
+#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_MULTILINEUNDOREDO 0x1000
+#define SC_STARTACTION 0x2000
+#define SC_MOD_CHANGEINDICATOR 0x4000
+#define SC_MOD_CHANGELINESTATE 0x8000
+#define SC_MOD_CHANGEMARGIN 0x10000
+#define SC_MOD_CHANGEANNOTATION 0x20000
+#define SC_MOD_CONTAINER 0x40000
+#define SC_MODEVENTMASKALL 0x7FFFF
+#define SCEN_CHANGE 768
+#define SCEN_SETFOCUS 512
+#define SCEN_KILLFOCUS 256
+#define SCK_DOWN 300
+#define SCK_UP 301
+#define SCK_LEFT 302
+#define SCK_RIGHT 303
+#define SCK_HOME 304
+#define SCK_END 305
+#define SCK_PRIOR 306
+#define SCK_NEXT 307
+#define SCK_DELETE 308
+#define SCK_INSERT 309
+#define SCK_ESCAPE 7
+#define SCK_BACK 8
+#define SCK_TAB 9
+#define SCK_RETURN 13
+#define SCK_ADD 310
+#define SCK_SUBTRACT 311
+#define SCK_DIVIDE 312
+#define SCK_WIN 313
+#define SCK_RWIN 314
+#define SCK_MENU 315
+#define SCMOD_NORM 0
+#define SCMOD_SHIFT 1
+#define SCMOD_CTRL 2
+#define SCMOD_ALT 4
+#define SCMOD_SUPER 8
+#define SCN_STYLENEEDED 2000
+#define SCN_CHARADDED 2001
+#define SCN_SAVEPOINTREACHED 2002
+#define SCN_SAVEPOINTLEFT 2003
+#define SCN_MODIFYATTEMPTRO 2004
+#define SCN_KEY 2005
+#define SCN_DOUBLECLICK 2006
+#define SCN_UPDATEUI 2007
+#define SCN_MODIFIED 2008
+#define SCN_MACRORECORD 2009
+#define SCN_MARGINCLICK 2010
+#define SCN_NEEDSHOWN 2011
+#define SCN_PAINTED 2013
+#define SCN_USERLISTSELECTION 2014
+#define SCN_URIDROPPED 2015
+#define SCN_DWELLSTART 2016
+#define SCN_DWELLEND 2017
+#define SCN_ZOOM 2018
+#define SCN_HOTSPOTCLICK 2019
+#define SCN_HOTSPOTDOUBLECLICK 2020
+#define SCN_CALLTIPCLICK 2021
+#define SCN_AUTOCSELECTION 2022
+#define SCN_INDICATORCLICK 2023
+#define SCN_INDICATORRELEASE 2024
+#define SCN_AUTOCCANCELLED 2025
+#define SCN_AUTOCCHARDELETED 2026
+/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
+
+/* These structures are defined to be exactly the same shape as the Win32
+ * CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs.
+ * So older code that treats Scintilla as a RichEdit will work. */
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+struct Sci_CharacterRange {
+ long cpMin;
+ long cpMax;
+};
+
+struct Sci_TextRange {
+ struct Sci_CharacterRange chrg;
+ char *lpstrText;
+};
+
+struct Sci_TextToFind {
+ struct Sci_CharacterRange chrg;
+ char *lpstrText;
+ struct Sci_CharacterRange chrgText;
+};
+
+#define CharacterRange Sci_CharacterRange
+#define TextRange Sci_TextRange
+#define TextToFind Sci_TextToFind
+
+typedef void *Sci_SurfaceID;
+
+struct Sci_Rectangle {
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+/* This structure is used in printing and requires some of the graphics types
+ * from Platform.h. Not needed by most client code. */
+
+struct Sci_RangeToFormat {
+ Sci_SurfaceID hdc;
+ Sci_SurfaceID hdcTarget;
+ struct Sci_Rectangle rc;
+ struct Sci_Rectangle rcPage;
+ struct Sci_CharacterRange chrg;
+};
+
+#define RangeToFormat Sci_RangeToFormat
+
+struct Sci_NotifyHeader {
+ /* 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. */
+ void *hwndFrom;
+ uptr_t idFrom;
+ unsigned int code;
+};
+
+#define NotifyHeader Sci_NotifyHeader
+
+struct SCNotification {
+ struct Sci_NotifyHeader nmhdr;
+ int position; /* SCN_STYLENEEDED, SCN_MODIFIED, SCN_DWELLSTART, SCN_DWELLEND */
+ int ch; /* SCN_CHARADDED, SCN_KEY */
+ int modifiers; /* SCN_KEY */
+ int modificationType; /* SCN_MODIFIED */
+ const char *text; /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */
+ int length; /* SCN_MODIFIED */
+ int linesAdded; /* SCN_MODIFIED */
+ int message; /* SCN_MACRORECORD */
+ uptr_t wParam; /* SCN_MACRORECORD */
+ sptr_t lParam; /* SCN_MACRORECORD */
+ int line; /* SCN_MODIFIED */
+ int foldLevelNow; /* SCN_MODIFIED */
+ int foldLevelPrev; /* SCN_MODIFIED */
+ int margin; /* SCN_MARGINCLICK */
+ int listType; /* SCN_USERLISTSELECTION */
+ int x; /* SCN_DWELLSTART, SCN_DWELLEND */
+ int y; /* SCN_DWELLSTART, SCN_DWELLEND */
+ int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */
+ int annotationLinesAdded; /* SC_MOD_CHANGEANNOTATION */
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface
new file mode 100644
index 0000000..2a89531
--- /dev/null
+++ b/scintilla/include/Scintilla.iface
@@ -0,0 +1,3784 @@
+## First line may be used for shbang
+
+## This file defines the interface to Scintilla
+
+## Copyright 2000-2003 by Neil Hodgson <neilh@scintilla.org>
+## The License.txt file describes the conditions under which this software may be distributed.
+
+## A line starting with ## is a pure comment and should be stripped by readers.
+## A line starting with #! is for future shbang use
+## A line starting with # followed by a space is a documentation comment and refers
+## to the next feature definition.
+
+## Each feature is defined by a line starting with fun, get, set, val or evt.
+## cat -> start a category
+## fun -> a function
+## get -> a property get function
+## set -> a property set function
+## val -> definition of a constant
+## evt -> an event
+## enu -> associate an enumeration with a set of vals with a prefix
+## lex -> associate a lexer with the lexical classes it produces
+##
+## All other feature names should be ignored. They may be defined in the future.
+## A property may have a set function, a get function or both. Each will have
+## "Get" or "Set" in their names and the corresponding name will have the obvious switch.
+## A property may be subscripted, in which case the first parameter is the subscript.
+## fun, get, and set features have a strict syntax:
+## <featureType><ws><returnType><ws><name>[=<number](<param>,<param>)
+## where <ws> stands for white space.
+## param may be empty (null value) or is <paramType><ws><paramName>[=<value>]
+## Additional white space is allowed between elements.
+## The syntax for evt is <featureType><ws><returnType><ws><name>[=<number]([<param>[,<param>]*])
+## Feature names that contain an underscore are defined by Windows, so in these
+## cases, using the Windows definition is preferred where available.
+## The feature numbers are stable so features will not be renumbered.
+## Features may be removed but they will go through a period of deprecation
+## before removal which is signalled by moving them into the Deprecated category.
+##
+## enu has the syntax enu<ws><enumeration>=<prefix>[<ws><prefix>]* where all the val
+## features in this file starting with a given <prefix> are considered part of the
+## enumeration.
+##
+## lex has the syntax lex<ws><name>=<lexerVal><ws><prefix>[<ws><prefix>]*
+## where name is a reasonably capitalised (Python, XML) identifier or UI name,
+## lexerVal is the val used to specify the lexer, and the list of prefixes is similar
+## to enu. The name may not be the same as that used within the lexer so the lexerVal
+## should be used to tie these entities together.
+
+## Types:
+## void
+## int
+## bool -> integer, 1=true, 0=false
+## position -> integer position in a document
+## colour -> colour integer containing red, green and blue bytes.
+## string -> pointer to const character
+## stringresult -> pointer to character, NULL-> return size of result
+## cells -> pointer to array of cells, each cell containing a style byte and character byte
+## textrange -> range of a min and a max position with an output string
+## findtext -> searchrange, text -> foundposition
+## keymod -> integer containing key in low half and modifiers in high half
+## formatrange
+## Types no longer used:
+## findtextex -> searchrange
+## charrange -> range of a min and a max position
+## charrangeresult -> like charrange, but output param
+## countedstring
+## point -> x,y
+## pointresult -> like point, but output param
+## rectangle -> left,top,right,bottom
+## Client code should ignore definitions containing types it does not understand, except
+## for possibly #defining the constants
+
+## Line numbers and positions start at 0.
+## String arguments may contain NUL ('\0') characters where the calls provide a length
+## argument and retrieve NUL characters. All retrieved strings except for those retrieved
+## by GetLine also have a NUL appended but client code should calculate the size that
+## will be returned rather than relying upon the NUL whenever possible. Allow for the
+## extra NUL character when allocating buffers. The size to allocate for a stringresult
+## can be determined by calling with a NULL (0) pointer.
+
+cat Basics
+
+################################################
+## For Scintilla.h
+val INVALID_POSITION=-1
+# Define start of Scintilla messages to be greater than all Windows edit (EM_*) messages
+# as many EM_ messages can be used although that use is deprecated.
+val SCI_START=2000
+val SCI_OPTIONAL_START=3000
+val SCI_LEXER_START=4000
+
+# Add text to the document at current position.
+fun void AddText=2001(int length, string text)
+
+# Add array of cells to document.
+fun void AddStyledText=2002(int length, cells c)
+
+# Insert string at a position.
+fun void InsertText=2003(position pos, string text)
+
+# Delete all text in the document.
+fun void ClearAll=2004(,)
+
+# Set all style bytes to 0, remove all folding information.
+fun void ClearDocumentStyle=2005(,)
+
+# Returns the number of bytes in the document.
+get int GetLength=2006(,)
+
+# Returns the character byte at the position.
+get int GetCharAt=2007(position pos,)
+
+# Returns the position of the caret.
+get position GetCurrentPos=2008(,)
+
+# Returns the position of the opposite end of the selection to the caret.
+get position GetAnchor=2009(,)
+
+# Returns the style byte at the position.
+get int GetStyleAt=2010(position pos,)
+
+# Redoes the next action on the undo history.
+fun void Redo=2011(,)
+
+# Choose between collecting actions into the undo
+# history and discarding them.
+set void SetUndoCollection=2012(bool collectUndo,)
+
+# Select all the text in the document.
+fun void SelectAll=2013(,)
+
+# Remember the current position in the undo history as the position
+# at which the document was saved.
+fun void SetSavePoint=2014(,)
+
+# Retrieve a buffer of cells.
+# Returns the number of bytes in the buffer not including terminating NULs.
+fun int GetStyledText=2015(, textrange tr)
+
+# Are there any redoable actions in the undo history?
+fun bool CanRedo=2016(,)
+
+# Retrieve the line number at which a particular marker is located.
+fun int MarkerLineFromHandle=2017(int handle,)
+
+# Delete a marker.
+fun void MarkerDeleteHandle=2018(int handle,)
+
+# Is undo history being collected?
+get bool GetUndoCollection=2019(,)
+
+enu WhiteSpace=SCWS_
+val SCWS_INVISIBLE=0
+val SCWS_VISIBLEALWAYS=1
+val SCWS_VISIBLEAFTERINDENT=2
+
+# Are white space characters currently visible?
+# Returns one of SCWS_* constants.
+get int GetViewWS=2020(,)
+
+# Make white space characters invisible, always visible or visible outside indentation.
+set void SetViewWS=2021(int viewWS,)
+
+# Find the position from a point within the window.
+fun position PositionFromPoint=2022(int x, int y)
+
+# Find the position from a point within the window but return
+# INVALID_POSITION if not close to text.
+fun position PositionFromPointClose=2023(int x, int y)
+
+# Set caret to start of a line and ensure it is visible.
+fun void GotoLine=2024(int line,)
+
+# Set caret to a position and ensure it is visible.
+fun void GotoPos=2025(position pos,)
+
+# Set the selection anchor to a position. The anchor is the opposite
+# end of the selection from the caret.
+set void SetAnchor=2026(position posAnchor,)
+
+# Retrieve the text of the line containing the caret.
+# Returns the index of the caret on the line.
+fun int GetCurLine=2027(int length, stringresult text)
+
+# Retrieve the position of the last correctly styled character.
+get position GetEndStyled=2028(,)
+
+enu EndOfLine=SC_EOL_
+val SC_EOL_CRLF=0
+val SC_EOL_CR=1
+val SC_EOL_LF=2
+
+# Convert all line endings in the document to one mode.
+fun void ConvertEOLs=2029(int eolMode,)
+
+# Retrieve the current end of line mode - one of CRLF, CR, or LF.
+get int GetEOLMode=2030(,)
+
+# Set the current end of line mode.
+set void SetEOLMode=2031(int eolMode,)
+
+# Set the current styling position to pos and the styling mask to mask.
+# The styling mask can be used to protect some bits in each styling byte from modification.
+fun void StartStyling=2032(position pos, int mask)
+
+# Change style from current styling position for length characters to a style
+# and move the current styling position to after this newly styled segment.
+fun void SetStyling=2033(int length, int style)
+
+# Is drawing done first into a buffer or direct to the screen?
+get bool GetBufferedDraw=2034(,)
+
+# If drawing is buffered then each line of text is drawn into a bitmap buffer
+# before drawing it to the screen to avoid flicker.
+set void SetBufferedDraw=2035(bool buffered,)
+
+# Change the visible size of a tab to be a multiple of the width of a space character.
+set void SetTabWidth=2036(int tabWidth,)
+
+# Retrieve the visible size of a tab.
+get int GetTabWidth=2121(,)
+
+# The SC_CP_UTF8 value can be used to enter Unicode mode.
+# This is the same value as CP_UTF8 in Windows
+val SC_CP_UTF8=65001
+
+# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+.
+val SC_CP_DBCS=1
+
+# Set the code page used to interpret the bytes of the document as characters.
+# The SC_CP_UTF8 value can be used to enter Unicode mode.
+set void SetCodePage=2037(int codePage,)
+
+# In palette mode, Scintilla uses the environment's palette calls to display
+# more colours. This may lead to ugly displays.
+set void SetUsePalette=2039(bool usePalette,)
+
+enu MarkerSymbol=SC_MARK_
+val MARKER_MAX=31
+val SC_MARK_CIRCLE=0
+val SC_MARK_ROUNDRECT=1
+val SC_MARK_ARROW=2
+val SC_MARK_SMALLRECT=3
+val SC_MARK_SHORTARROW=4
+val SC_MARK_EMPTY=5
+val SC_MARK_ARROWDOWN=6
+val SC_MARK_MINUS=7
+val SC_MARK_PLUS=8
+
+# Shapes used for outlining column.
+val SC_MARK_VLINE=9
+val SC_MARK_LCORNER=10
+val SC_MARK_TCORNER=11
+val SC_MARK_BOXPLUS=12
+val SC_MARK_BOXPLUSCONNECTED=13
+val SC_MARK_BOXMINUS=14
+val SC_MARK_BOXMINUSCONNECTED=15
+val SC_MARK_LCORNERCURVE=16
+val SC_MARK_TCORNERCURVE=17
+val SC_MARK_CIRCLEPLUS=18
+val SC_MARK_CIRCLEPLUSCONNECTED=19
+val SC_MARK_CIRCLEMINUS=20
+val SC_MARK_CIRCLEMINUSCONNECTED=21
+
+# Invisible mark that only sets the line background color.
+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_LEFTRECT=27
+val SC_MARK_AVAILABLE=28
+val SC_MARK_UNDERLINE=29
+
+val SC_MARK_CHARACTER=10000
+
+enu MarkerOutline=SC_MARKNUM_
+# Markers used for outlining column.
+val SC_MARKNUM_FOLDEREND=25
+val SC_MARKNUM_FOLDEROPENMID=26
+val SC_MARKNUM_FOLDERMIDTAIL=27
+val SC_MARKNUM_FOLDERTAIL=28
+val SC_MARKNUM_FOLDERSUB=29
+val SC_MARKNUM_FOLDER=30
+val SC_MARKNUM_FOLDEROPEN=31
+
+val SC_MASK_FOLDERS=0xFE000000
+
+# Set the symbol used for a particular marker number.
+fun void MarkerDefine=2040(int markerNumber, int markerSymbol)
+
+# Set the foreground colour used for a particular marker number.
+fun void MarkerSetFore=2041(int markerNumber, colour fore)
+
+# Set the background colour used for a particular marker number.
+fun void MarkerSetBack=2042(int markerNumber, colour back)
+
+# Add a marker to a line, returning an ID which can be used to find or delete the marker.
+fun int MarkerAdd=2043(int line, int markerNumber)
+
+# Delete a marker from a line.
+fun void MarkerDelete=2044(int line, int markerNumber)
+
+# Delete all markers with a particular number from all lines.
+fun void MarkerDeleteAll=2045(int markerNumber,)
+
+# Get a bit mask of all the markers set on a line.
+fun int MarkerGet=2046(int line,)
+
+# Find the next line after lineStart that includes a marker in mask.
+fun int MarkerNext=2047(int lineStart, int markerMask)
+
+# Find the previous line before lineStart that includes a marker in mask.
+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)
+
+# Set the alpha used for a marker that is drawn in the text area, not the margin.
+fun void MarkerSetAlpha=2476(int markerNumber, int alpha)
+
+enu MarginType=SC_MARGIN_
+val SC_MARGIN_SYMBOL=0
+val SC_MARGIN_NUMBER=1
+val SC_MARGIN_BACK=2
+val SC_MARGIN_FORE=3
+val SC_MARGIN_TEXT=4
+val SC_MARGIN_RTEXT=5
+
+# Set a margin to be either numeric or symbolic.
+set void SetMarginTypeN=2240(int margin, int marginType)
+
+# Retrieve the type of a margin.
+get int GetMarginTypeN=2241(int margin,)
+
+# Set the width of a margin to a width expressed in pixels.
+set void SetMarginWidthN=2242(int margin, int pixelWidth)
+
+# Retrieve the width of a margin in pixels.
+get int GetMarginWidthN=2243(int margin,)
+
+# Set a mask that determines which markers are displayed in a margin.
+set void SetMarginMaskN=2244(int margin, int mask)
+
+# Retrieve the marker mask of a margin.
+get int GetMarginMaskN=2245(int margin,)
+
+# Make a margin sensitive or insensitive to mouse clicks.
+set void SetMarginSensitiveN=2246(int margin, bool sensitive)
+
+# Retrieve the mouse click sensitivity of a margin.
+get bool GetMarginSensitiveN=2247(int margin,)
+
+# Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles.
+# Style 39 is for future use.
+enu StylesCommon=STYLE_
+val STYLE_DEFAULT=32
+val STYLE_LINENUMBER=33
+val STYLE_BRACELIGHT=34
+val STYLE_BRACEBAD=35
+val STYLE_CONTROLCHAR=36
+val STYLE_INDENTGUIDE=37
+val STYLE_CALLTIP=38
+val STYLE_LASTPREDEFINED=39
+val STYLE_MAX=255
+
+# Character set identifiers are used in StyleSetCharacterSet.
+# The values are the same as the Windows *_CHARSET values.
+enu CharacterSet=SC_CHARSET_
+val SC_CHARSET_ANSI=0
+val SC_CHARSET_DEFAULT=1
+val SC_CHARSET_BALTIC=186
+val SC_CHARSET_CHINESEBIG5=136
+val SC_CHARSET_EASTEUROPE=238
+val SC_CHARSET_GB2312=134
+val SC_CHARSET_GREEK=161
+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
+val SC_CHARSET_JOHAB=130
+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(,)
+
+# Set the foreground colour of a style.
+set void StyleSetFore=2051(int style, colour fore)
+
+# Set the background colour of a style.
+set void StyleSetBack=2052(int style, colour back)
+
+# Set a style to be bold or not.
+set void StyleSetBold=2053(int style, bool bold)
+
+# Set a style to be italic or not.
+set void StyleSetItalic=2054(int style, bool italic)
+
+# Set the size of characters of a style.
+set void StyleSetSize=2055(int style, int sizePoints)
+
+# Set the font of a style.
+set void StyleSetFont=2056(int style, string fontName)
+
+# Set a style to have its end of line filled or not.
+set void StyleSetEOLFilled=2057(int style, bool filled)
+
+# Reset the default style to its state at startup
+fun void StyleResetDefault=2058(,)
+
+# Set a style to be underlined or not.
+set void StyleSetUnderline=2059(int style, bool underline)
+
+enu CaseVisible=SC_CASE_
+val SC_CASE_MIXED=0
+val SC_CASE_UPPER=1
+val SC_CASE_LOWER=2
+
+# Get the foreground colour of a style.
+get colour StyleGetFore=2481(int style,)
+
+# Get the background colour of a style.
+get colour StyleGetBack=2482(int style,)
+
+# Get is a style bold or not.
+get bool StyleGetBold=2483(int style,)
+
+# Get is a style italic or not.
+get bool StyleGetItalic=2484(int style,)
+
+# Get the size of characters of a style.
+get int StyleGetSize=2485(int style,)
+
+# Get the font of a style.
+# Returns the length of the fontName
+fun int StyleGetFont=2486(int style, stringresult fontName)
+
+# Get is a style to have its end of line filled or not.
+get bool StyleGetEOLFilled=2487(int style,)
+
+# Get is a style underlined or not.
+get bool StyleGetUnderline=2488(int style,)
+
+# Get is a style mixed case, or to force upper or lower case.
+get int StyleGetCase=2489(int style,)
+
+# Get the character get of the font in a style.
+get int StyleGetCharacterSet=2490(int style,)
+
+# Get is a style visible or not.
+get bool StyleGetVisible=2491(int style,)
+
+# Get is a style changeable or not (read only).
+# Experimental feature, currently buggy.
+get bool StyleGetChangeable=2492(int style,)
+
+# Get is a style a hotspot or not.
+get bool StyleGetHotSpot=2493(int style,)
+
+# Set a style to be mixed case, or to force upper or lower case.
+set void StyleSetCase=2060(int style, int caseForce)
+
+# Set the character set of the font in a style.
+set void StyleSetCharacterSet=2066(int style, int characterSet)
+
+# Set a style to be a hotspot or not.
+set void StyleSetHotSpot=2409(int style, bool hotspot)
+
+# Set the foreground colour of the main and additional selections and whether to use this setting.
+fun void SetSelFore=2067(bool useSetting, colour fore)
+
+# Set the background colour of the main and additional selections and whether to use this setting.
+fun void SetSelBack=2068(bool useSetting, colour back)
+
+# Get the alpha of the selection.
+get int GetSelAlpha=2477(,)
+
+# Set the alpha of the selection.
+set void SetSelAlpha=2478(int alpha,)
+
+# Is the selection end of line filled?
+get bool GetSelEOLFilled=2479(,)
+
+# Set the selection to have its end of line filled or not.
+set void SetSelEOLFilled=2480(bool filled,)
+
+# Set the foreground colour of the caret.
+set void SetCaretFore=2069(colour fore,)
+
+# When key+modifier combination km is pressed perform msg.
+fun void AssignCmdKey=2070(keymod km, int msg)
+
+# When key+modifier combination km is pressed do nothing.
+fun void ClearCmdKey=2071(keymod km,)
+
+# Drop all key mappings.
+fun void ClearAllCmdKeys=2072(,)
+
+# Set the styles for a segment of the document.
+fun void SetStylingEx=2073(int length, string styles)
+
+# Set a style to be visible or not.
+set void StyleSetVisible=2074(int style, bool visible)
+
+# Get the time in milliseconds that the caret is on and off.
+get int GetCaretPeriod=2075(,)
+
+# Get the time in milliseconds that the caret is on and off. 0 = steady on.
+set void SetCaretPeriod=2076(int periodMilliseconds,)
+
+# Set the set of characters making up words for when moving or selecting by word.
+# First sets defaults like SetCharsDefault.
+set void SetWordChars=2077(, string characters)
+
+# Start a sequence of actions that is undone and redone as a unit.
+# May be nested.
+fun void BeginUndoAction=2078(,)
+
+# End a sequence of actions that is undone and redone as a unit.
+fun void EndUndoAction=2079(,)
+
+# Indicator style enumeration and some constants
+enu IndicatorStyle=INDIC_
+val INDIC_PLAIN=0
+val INDIC_SQUIGGLE=1
+val INDIC_TT=2
+val INDIC_DIAGONAL=3
+val INDIC_STRIKE=4
+val INDIC_HIDDEN=5
+val INDIC_BOX=6
+val INDIC_ROUNDBOX=7
+val INDIC_MAX=31
+val INDIC_CONTAINER=8
+val INDIC0_MASK=0x20
+val INDIC1_MASK=0x40
+val INDIC2_MASK=0x80
+val INDICS_MASK=0xE0
+
+# Set an indicator to plain, squiggle or TT.
+set void IndicSetStyle=2080(int indic, int style)
+
+# Retrieve the style of an indicator.
+get int IndicGetStyle=2081(int indic,)
+
+# Set the foreground colour of an indicator.
+set void IndicSetFore=2082(int indic, colour fore)
+
+# Retrieve the foreground colour of an indicator.
+get colour IndicGetFore=2083(int indic,)
+
+# Set an indicator to draw under text or over(default).
+set void IndicSetUnder=2510(int indic, bool under)
+
+# Retrieve whether indicator drawn under or over text.
+get bool IndicGetUnder=2511(int indic,)
+
+# Set the foreground colour of all whitespace and whether to use this setting.
+fun void SetWhitespaceFore=2084(bool useSetting, colour fore)
+
+# Set the background colour of all whitespace and whether to use this setting.
+fun void SetWhitespaceBack=2085(bool useSetting, colour back)
+
+# Set the size of the dots used to mark space characters.
+set void SetWhitespaceSize=2086(int size,)
+
+# Get the size of the dots used to mark space characters.
+get int GetWhitespaceSize=2087(,)
+
+# Divide each styling byte into lexical class bits (default: 5) and indicator
+# bits (default: 3). If a lexer requires more than 32 lexical states, then this
+# is used to expand the possible states.
+set void SetStyleBits=2090(int bits,)
+
+# Retrieve number of bits in style bytes used to hold the lexical state.
+get int GetStyleBits=2091(,)
+
+# Used to hold extra styling information for each line.
+set void SetLineState=2092(int line, int state)
+
+# Retrieve the extra styling information for a line.
+get int GetLineState=2093(int line,)
+
+# Retrieve the last line number that has line state.
+get int GetMaxLineState=2094(,)
+
+# Is the background of the line containing the caret in a different colour?
+get bool GetCaretLineVisible=2095(,)
+
+# Display the background of the line containing the caret in a different colour.
+set void SetCaretLineVisible=2096(bool show,)
+
+# Get the colour of the background of the line containing the caret.
+get colour GetCaretLineBack=2097(,)
+
+# Set the colour of the background of the line containing the caret.
+set void SetCaretLineBack=2098(colour back,)
+
+# Set a style to be changeable or not (read only).
+# Experimental feature, currently buggy.
+set void StyleSetChangeable=2099(int style, bool changeable)
+
+# Display a auto-completion list.
+# The lenEntered parameter indicates how many characters before
+# the caret should be used to provide context.
+fun void AutoCShow=2100(int lenEntered, string itemList)
+
+# Remove the auto-completion list from the screen.
+fun void AutoCCancel=2101(,)
+
+# Is there an auto-completion list visible?
+fun bool AutoCActive=2102(,)
+
+# Retrieve the position of the caret when the auto-completion list was displayed.
+fun position AutoCPosStart=2103(,)
+
+# User has selected an item so remove the list and insert the selection.
+fun void AutoCComplete=2104(,)
+
+# Define a set of character that when typed cancel the auto-completion list.
+fun void AutoCStops=2105(, string characterSet)
+
+# Change the separator character in the string setting up an auto-completion list.
+# Default is space but can be changed if items contain space.
+set void AutoCSetSeparator=2106(int separatorCharacter,)
+
+# Retrieve the auto-completion list separator character.
+get int AutoCGetSeparator=2107(,)
+
+# Select the item in the auto-completion list that starts with a string.
+fun void AutoCSelect=2108(, string text)
+
+# Should the auto-completion list be cancelled if the user backspaces to a
+# position before where the box was created.
+set void AutoCSetCancelAtStart=2110(bool cancel,)
+
+# Retrieve whether auto-completion cancelled by backspacing before start.
+get bool AutoCGetCancelAtStart=2111(,)
+
+# Define a set of characters that when typed will cause the autocompletion to
+# choose the selected item.
+set void AutoCSetFillUps=2112(, string characterSet)
+
+# Should a single item auto-completion list automatically choose the item.
+set void AutoCSetChooseSingle=2113(bool chooseSingle,)
+
+# Retrieve whether a single item auto-completion list automatically choose the item.
+get bool AutoCGetChooseSingle=2114(,)
+
+# Set whether case is significant when performing auto-completion searches.
+set void AutoCSetIgnoreCase=2115(bool ignoreCase,)
+
+# Retrieve state of ignore case flag.
+get bool AutoCGetIgnoreCase=2116(,)
+
+# Display a list of strings and send notification when user chooses one.
+fun void UserListShow=2117(int listType, string itemList)
+
+# Set whether or not autocompletion is hidden automatically when nothing matches.
+set void AutoCSetAutoHide=2118(bool autoHide,)
+
+# Retrieve whether or not autocompletion is hidden automatically when nothing matches.
+get bool AutoCGetAutoHide=2119(,)
+
+# Set whether or not autocompletion deletes any word characters
+# after the inserted text upon completion.
+set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,)
+
+# Retrieve whether or not autocompletion deletes any word characters
+# after the inserted text upon completion.
+get bool AutoCGetDropRestOfWord=2271(,)
+
+# Register an XPM image for use in autocompletion lists.
+fun void RegisterImage=2405(int type, string xpmData)
+
+# Clear all the registered XPM images.
+fun void ClearRegisteredImages=2408(,)
+
+# Retrieve the auto-completion list type-separator character.
+get int AutoCGetTypeSeparator=2285(,)
+
+# Change the type-separator character in the string setting up an auto-completion list.
+# 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,)
+
+# Retrieve indentation size.
+get int GetIndent=2123(,)
+
+# Indentation will only use space characters if useTabs is false, otherwise
+# it will use a combination of tabs and spaces.
+set void SetUseTabs=2124(bool useTabs,)
+
+# Retrieve whether tabs will be used in indentation.
+get bool GetUseTabs=2125(,)
+
+# Change the indentation of a line to a number of columns.
+set void SetLineIndentation=2126(int line, int indentSize)
+
+# Retrieve the number of columns that a line is indented.
+get int GetLineIndentation=2127(int line,)
+
+# Retrieve the position before the first non indentation character on a line.
+get position GetLineIndentPosition=2128(int line,)
+
+# Retrieve the column number of a position, taking tab width into account.
+get int GetColumn=2129(position pos,)
+
+# Show or hide the horizontal scroll bar.
+set void SetHScrollBar=2130(bool show,)
+
+# Is the horizontal scroll bar visible?
+get bool GetHScrollBar=2131(,)
+
+enu IndentView=SC_IV_
+val SC_IV_NONE=0
+val SC_IV_REAL=1
+val SC_IV_LOOKFORWARD=2
+val SC_IV_LOOKBOTH=3
+
+# Show or hide indentation guides.
+set void SetIndentationGuides=2132(int indentView,)
+
+# Are the indentation guides visible?
+get int GetIndentationGuides=2133(,)
+
+# Set the highlighted indentation guide column.
+# 0 = no highlighted guide.
+set void SetHighlightGuide=2134(int column,)
+
+# Get the highlighted indentation guide column.
+get int GetHighlightGuide=2135(,)
+
+# Get the position after the last visible characters on a line.
+get int GetLineEndPosition=2136(int line,)
+
+# Get the code page used to interpret the bytes of the document as characters.
+get int GetCodePage=2137(,)
+
+# Get the foreground colour of the caret.
+get colour GetCaretFore=2138(,)
+
+# In palette mode?
+get bool GetUsePalette=2139(,)
+
+# In read-only mode?
+get bool GetReadOnly=2140(,)
+
+# Sets the position of the caret.
+set void SetCurrentPos=2141(position pos,)
+
+# Sets the position that starts the selection - this becomes the anchor.
+set void SetSelectionStart=2142(position pos,)
+
+# Returns the position at the start of the selection.
+get position GetSelectionStart=2143(,)
+
+# Sets the position that ends the selection - this becomes the currentPosition.
+set void SetSelectionEnd=2144(position pos,)
+
+# Returns the position at the end of the selection.
+get position GetSelectionEnd=2145(,)
+
+# Sets the print magnification added to the point size of each style for printing.
+set void SetPrintMagnification=2146(int magnification,)
+
+# Returns the print magnification.
+get int GetPrintMagnification=2147(,)
+
+enu PrintOption=SC_PRINT_
+# PrintColourMode - use same colours as screen.
+val SC_PRINT_NORMAL=0
+# PrintColourMode - invert the light value of each style for printing.
+val SC_PRINT_INVERTLIGHT=1
+# PrintColourMode - force black text on white background for printing.
+val SC_PRINT_BLACKONWHITE=2
+# PrintColourMode - text stays coloured, but all background is forced to be white for printing.
+val SC_PRINT_COLOURONWHITE=3
+# PrintColourMode - only the default-background is forced to be white for printing.
+val SC_PRINT_COLOURONWHITEDEFAULTBG=4
+
+# Modify colours when printing for clearer printed text.
+set void SetPrintColourMode=2148(int mode,)
+
+# Returns the print colour mode.
+get int GetPrintColourMode=2149(,)
+
+enu FindOption=SCFIND_
+val SCFIND_WHOLEWORD=2
+val SCFIND_MATCHCASE=4
+val SCFIND_WORDSTART=0x00100000
+val SCFIND_REGEXP=0x00200000
+val SCFIND_POSIX=0x00400000
+
+# Find some text in the document.
+fun position FindText=2150(int flags, findtext ft)
+
+# On Windows, will draw the document into a display context such as a printer.
+fun position FormatRange=2151(bool draw, formatrange fr)
+
+# Retrieve the display line at the top of the display.
+get int GetFirstVisibleLine=2152(,)
+
+# Retrieve the contents of a line.
+# Returns the length of the line.
+fun int GetLine=2153(int line, stringresult text)
+
+# Returns the number of lines in the document. There is always at least one.
+get int GetLineCount=2154(,)
+
+# Sets the size in pixels of the left margin.
+set void SetMarginLeft=2155(, int pixelWidth)
+
+# Returns the size in pixels of the left margin.
+get int GetMarginLeft=2156(,)
+
+# Sets the size in pixels of the right margin.
+set void SetMarginRight=2157(, int pixelWidth)
+
+# Returns the size in pixels of the right margin.
+get int GetMarginRight=2158(,)
+
+# Is the document different from when it was last saved?
+get bool GetModify=2159(,)
+
+# Select a range of text.
+fun void SetSel=2160(position start, position end)
+
+# Retrieve the selected text.
+# Return the length of the text.
+fun int GetSelText=2161(, stringresult text)
+
+# Retrieve a range of text.
+# Return the length of the text.
+fun int GetTextRange=2162(, textrange tr)
+
+# Draw the selection in normal style or with selection highlighted.
+fun void HideSelection=2163(bool normal,)
+
+# Retrieve the x value of the point in the window where a position is displayed.
+fun int PointXFromPosition=2164(, position pos)
+
+# Retrieve the y value of the point in the window where a position is displayed.
+fun int PointYFromPosition=2165(, position pos)
+
+# Retrieve the line containing a position.
+fun int LineFromPosition=2166(position pos,)
+
+# Retrieve the position at the start of a line.
+fun position PositionFromLine=2167(int line,)
+
+# Scroll horizontally and vertically.
+fun void LineScroll=2168(int columns, int lines)
+
+# Ensure the caret is visible.
+fun void ScrollCaret=2169(,)
+
+# Replace the selected text with the argument text.
+fun void ReplaceSel=2170(, string text)
+
+# Set to read only or read write.
+set void SetReadOnly=2171(bool readOnly,)
+
+# Null operation.
+fun void Null=2172(,)
+
+# Will a paste succeed?
+fun bool CanPaste=2173(,)
+
+# Are there any undoable actions in the undo history?
+fun bool CanUndo=2174(,)
+
+# Delete the undo history.
+fun void EmptyUndoBuffer=2175(,)
+
+# Undo one action in the undo history.
+fun void Undo=2176(,)
+
+# Cut the selection to the clipboard.
+fun void Cut=2177(,)
+
+# Copy the selection to the clipboard.
+fun void Copy=2178(,)
+
+# Paste the contents of the clipboard into the document replacing the selection.
+fun void Paste=2179(,)
+
+# Clear the selection.
+fun void Clear=2180(,)
+
+# Replace the contents of the document with the argument text.
+fun void SetText=2181(, string text)
+
+# Retrieve all the text in the document.
+# Returns number of characters retrieved.
+fun int GetText=2182(int length, stringresult text)
+
+# Retrieve the number of characters in the document.
+get int GetTextLength=2183(,)
+
+# Retrieve a pointer to a function that processes messages for this Scintilla.
+get int GetDirectFunction=2184(,)
+
+# Retrieve a pointer value to use as the first argument when calling
+# the function returned by GetDirectFunction.
+get int GetDirectPointer=2185(,)
+
+# Set to overtype (true) or insert mode.
+set void SetOvertype=2186(bool overtype,)
+
+# Returns true if overtype mode is active otherwise false is returned.
+get bool GetOvertype=2187(,)
+
+# Set the width of the insert mode caret.
+set void SetCaretWidth=2188(int pixelWidth,)
+
+# Returns the width of the insert mode caret.
+get int GetCaretWidth=2189(,)
+
+# Sets the position that starts the target which is used for updating the
+# document without affecting the scroll position.
+set void SetTargetStart=2190(position pos,)
+
+# Get the position that starts the target.
+get position GetTargetStart=2191(,)
+
+# Sets the position that ends the target which is used for updating the
+# document without affecting the scroll position.
+set void SetTargetEnd=2192(position pos,)
+
+# Get the position that ends the target.
+get position GetTargetEnd=2193(,)
+
+# Replace the target text with the argument text.
+# Text is counted so it can contain NULs.
+# Returns the length of the replacement text.
+fun int ReplaceTarget=2194(int length, string text)
+
+# Replace the target text with the argument text after \d processing.
+# Text is counted so it can contain NULs.
+# Looks for \d where d is between 1 and 9 and replaces these with the strings
+# matched in the last search operation which were surrounded by \( and \).
+# Returns the length of the replacement text including any change
+# caused by processing the \d patterns.
+fun int ReplaceTargetRE=2195(int length, string text)
+
+# Search for a counted string in the target and set the target to the found
+# range. Text is counted so it can contain NULs.
+# Returns length of range or -1 for failure in which case target is not moved.
+fun int SearchInTarget=2197(int length, string text)
+
+# Set the search flags used by SearchInTarget.
+set void SetSearchFlags=2198(int flags,)
+
+# Get the search flags used by SearchInTarget.
+get int GetSearchFlags=2199(,)
+
+# Show a call tip containing a definition near position pos.
+fun void CallTipShow=2200(position pos, string definition)
+
+# Remove the call tip from the screen.
+fun void CallTipCancel=2201(,)
+
+# Is there an active call tip?
+fun bool CallTipActive=2202(,)
+
+# Retrieve the position where the caret was before displaying the call tip.
+fun position CallTipPosStart=2203(,)
+
+# Highlight a segment of the definition.
+fun void CallTipSetHlt=2204(int start, int end)
+
+# Set the background colour for the call tip.
+set void CallTipSetBack=2205(colour back,)
+
+# Set the foreground colour for the call tip.
+set void CallTipSetFore=2206(colour fore,)
+
+# Set the foreground colour for the highlighted part of the call tip.
+set void CallTipSetForeHlt=2207(colour fore,)
+
+# Enable use of STYLE_CALLTIP and set call tip tab size in pixels.
+set void CallTipUseStyle=2212(int tabSize,)
+
+# Find the display line of a document line taking hidden lines into account.
+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
+val SC_FOLDLEVELHEADERFLAG=0x2000
+val SC_FOLDLEVELNUMBERMASK=0x0FFF
+
+# 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.
+set void SetFoldLevel=2222(int line, int level)
+
+# Retrieve the fold level of a line.
+get int GetFoldLevel=2223(int line,)
+
+# Find the last child line of a header line.
+get int GetLastChild=2224(int line, int level)
+
+# Find the parent line of a child line.
+get int GetFoldParent=2225(int line,)
+
+# Make a range of lines visible.
+fun void ShowLines=2226(int lineStart, int lineEnd)
+
+# Make a range of lines invisible.
+fun void HideLines=2227(int lineStart, int lineEnd)
+
+# Is a line visible?
+get bool GetLineVisible=2228(int line,)
+
+# Show the children of a header line.
+set void SetFoldExpanded=2229(int line, bool expanded)
+
+# Is a header line expanded?
+get bool GetFoldExpanded=2230(int line,)
+
+# Switch a header line between expanded and contracted.
+fun void ToggleFold=2231(int line,)
+
+# Ensure a particular line is visible by expanding any header line hiding it.
+fun void EnsureVisible=2232(int line,)
+
+enu FoldFlag=SC_FOLDFLAG_
+val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002
+val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004
+val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008
+val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010
+val SC_FOLDFLAG_LEVELNUMBERS=0x0040
+
+# Set some style options for folding.
+fun void SetFoldFlags=2233(int flags,)
+
+# Ensure a particular line is visible by expanding any header line hiding it.
+# Use the currently set visibility policy to determine which range to display.
+fun void EnsureVisibleEnforcePolicy=2234(int line,)
+
+# Sets whether a tab pressed when caret is within indentation indents.
+set void SetTabIndents=2260(bool tabIndents,)
+
+# Does a tab pressed when caret is within indentation indent?
+get bool GetTabIndents=2261(,)
+
+# Sets whether a backspace pressed when caret is within indentation unindents.
+set void SetBackSpaceUnIndents=2262(bool bsUnIndents,)
+
+# Does a backspace pressed when caret is within indentation unindent?
+get bool GetBackSpaceUnIndents=2263(,)
+
+val SC_TIME_FOREVER=10000000
+
+# Sets the time the mouse must sit still to generate a mouse dwell event.
+set void SetMouseDwellTime=2264(int periodMilliseconds,)
+
+# Retrieve the time the mouse must sit still to generate a mouse dwell event.
+get int GetMouseDwellTime=2265(,)
+
+# Get position of start of word.
+fun int WordStartPosition=2266(position pos, bool onlyWordCharacters)
+
+# Get position of end of word.
+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,)
+
+# Retrieve whether text is word wrapped.
+get int GetWrapMode=2269(,)
+
+enu WrapVisualFlag=SC_WRAPVISUALFLAG_
+val SC_WRAPVISUALFLAG_NONE=0x0000
+val SC_WRAPVISUALFLAG_END=0x0001
+val SC_WRAPVISUALFLAG_START=0x0002
+
+# Set the display mode of visual flags for wrapped lines.
+set void SetWrapVisualFlags=2460(int wrapVisualFlags,)
+
+# Retrive the display mode of visual flags for wrapped lines.
+get int GetWrapVisualFlags=2461(,)
+
+enu WrapVisualLocation=SC_WRAPVISUALFLAGLOC_
+val SC_WRAPVISUALFLAGLOC_DEFAULT=0x0000
+val SC_WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001
+val SC_WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002
+
+# Set the location of visual flags for wrapped lines.
+set void SetWrapVisualFlagsLocation=2462(int wrapVisualFlagsLocation,)
+
+# Retrive the location of visual flags for wrapped lines.
+get int GetWrapVisualFlagsLocation=2463(,)
+
+# Set the start indent for wrapped lines.
+set void SetWrapStartIndent=2464(int indent,)
+
+# Retrive the start indent for wrapped lines.
+get int GetWrapStartIndent=2465(,)
+
+enu WrapIndentMode=SC_WRAPINDENT_
+val SC_WRAPINDENT_FIXED=0
+val SC_WRAPINDENT_SAME=1
+val SC_WRAPINDENT_INDENT=2
+
+# Sets how wrapped sublines are placed. Default is fixed.
+set void SetWrapIndentMode=2472(int mode,)
+
+# Retrieve how wrapped sublines are placed. Default is fixed.
+get int GetWrapIndentMode=2473(,)
+
+enu LineCache=SC_CACHE_
+val SC_CACHE_NONE=0
+val SC_CACHE_CARET=1
+val SC_CACHE_PAGE=2
+val SC_CACHE_DOCUMENT=3
+
+# Sets the degree of caching of layout information.
+set void SetLayoutCache=2272(int mode,)
+
+# Retrieve the degree of caching of layout information.
+get int GetLayoutCache=2273(,)
+
+# Sets the document width assumed for scrolling.
+set void SetScrollWidth=2274(int pixelWidth,)
+
+# Retrieve the document width assumed for scrolling.
+get int GetScrollWidth=2275(,)
+
+# Sets whether the maximum width line displayed is used to set scroll width.
+set void SetScrollWidthTracking=2516(bool tracking,)
+
+# Retrieve whether the scroll width tracks wide lines.
+get bool GetScrollWidthTracking=2517(,)
+
+# Measure the pixel width of some text in a particular style.
+# NUL terminated text argument.
+# Does not handle tab or control characters.
+fun int TextWidth=2276(int style, string text)
+
+# Sets the scroll range so that maximum scroll position has
+# the last line at the bottom of the view (default).
+# Setting this to false allows scrolling one page below the last line.
+set void SetEndAtLastLine=2277(bool endAtLastLine,)
+
+# Retrieve whether the maximum scroll position has the last
+# line at the bottom of the view.
+get bool GetEndAtLastLine=2278(,)
+
+# Retrieve the height of a particular line of text in pixels.
+fun int TextHeight=2279(int line,)
+
+# Show or hide the vertical scroll bar.
+set void SetVScrollBar=2280(bool show,)
+
+# Is the vertical scroll bar visible?
+get bool GetVScrollBar=2281(,)
+
+# Append a string to the end of the document without changing the selection.
+fun void AppendText=2282(int length, string text)
+
+# Is drawing done in two phases with backgrounds drawn before faoregrounds?
+get bool GetTwoPhaseDraw=2283(,)
+
+# In twoPhaseDraw mode, drawing is performed in two phases, first the background
+# and then the foreground. This avoids chopping off characters that overlap the next run.
+set void SetTwoPhaseDraw=2284(bool twoPhase,)
+
+# Control font anti-aliasing.
+
+enu FontQuality=SC_EFF_
+val SC_EFF_QUALITY_MASK=0xF
+val SC_EFF_QUALITY_DEFAULT=0
+val SC_EFF_QUALITY_NON_ANTIALIASED=1
+val SC_EFF_QUALITY_ANTIALIASED=2
+val SC_EFF_QUALITY_LCD_OPTIMIZED=3
+
+# Choose the quality level for text from the FontQuality enumeration.
+set void SetFontQuality=2611(int fontQuality,)
+
+# Retrieve the quality level for text.
+get int GetFontQuality=2612(,)
+
+# Scroll so that a display line is at the top of the display.
+set void SetFirstVisibleLine=2613(int lineDisplay,)
+
+enu MultiPaste=SC_MULTIPASTE_
+val SC_MULTIPASTE_ONCE=0
+val SC_MULTIPASTE_EACH=1
+
+# Change the effect of pasting when there are multiple selections.
+set void SetMultiPaste=2614(int multiPaste,)
+
+# Retrieve the effect of pasting when there are multiple selections..
+get int GetMultiPaste=2615(,)
+
+# Retrieve the value of a tag from a regular expression search.
+fun int GetTag=2616(int tagNumber, stringresult tagValue)
+
+# Make the target range start and end be the same as the selection range start and end.
+fun void TargetFromSelection=2287(,)
+
+# Join the lines in the target.
+fun void LinesJoin=2288(,)
+
+# Split the lines in the target into lines that are less wide than pixelWidth
+# where possible.
+fun void LinesSplit=2289(int pixelWidth,)
+
+# Set the colours used as a chequerboard pattern in the fold margin
+fun void SetFoldMarginColour=2290(bool useSetting, colour back)
+fun void SetFoldMarginHiColour=2291(bool useSetting, colour fore)
+
+## New messages go here
+
+## Start of key messages
+# Move caret down one line.
+fun void LineDown=2300(,)
+
+# Move caret down one line extending selection to new caret position.
+fun void LineDownExtend=2301(,)
+
+# Move caret up one line.
+fun void LineUp=2302(,)
+
+# Move caret up one line extending selection to new caret position.
+fun void LineUpExtend=2303(,)
+
+# Move caret left one character.
+fun void CharLeft=2304(,)
+
+# Move caret left one character extending selection to new caret position.
+fun void CharLeftExtend=2305(,)
+
+# Move caret right one character.
+fun void CharRight=2306(,)
+
+# Move caret right one character extending selection to new caret position.
+fun void CharRightExtend=2307(,)
+
+# Move caret left one word.
+fun void WordLeft=2308(,)
+
+# Move caret left one word extending selection to new caret position.
+fun void WordLeftExtend=2309(,)
+
+# Move caret right one word.
+fun void WordRight=2310(,)
+
+# Move caret right one word extending selection to new caret position.
+fun void WordRightExtend=2311(,)
+
+# Move caret to first position on line.
+fun void Home=2312(,)
+
+# Move caret to first position on line extending selection to new caret position.
+fun void HomeExtend=2313(,)
+
+# Move caret to last position on line.
+fun void LineEnd=2314(,)
+
+# Move caret to last position on line extending selection to new caret position.
+fun void LineEndExtend=2315(,)
+
+# Move caret to first position in document.
+fun void DocumentStart=2316(,)
+
+# Move caret to first position in document extending selection to new caret position.
+fun void DocumentStartExtend=2317(,)
+
+# Move caret to last position in document.
+fun void DocumentEnd=2318(,)
+
+# Move caret to last position in document extending selection to new caret position.
+fun void DocumentEndExtend=2319(,)
+
+# Move caret one page up.
+fun void PageUp=2320(,)
+
+# Move caret one page up extending selection to new caret position.
+fun void PageUpExtend=2321(,)
+
+# Move caret one page down.
+fun void PageDown=2322(,)
+
+# Move caret one page down extending selection to new caret position.
+fun void PageDownExtend=2323(,)
+
+# Switch from insert to overtype mode or the reverse.
+fun void EditToggleOvertype=2324(,)
+
+# Cancel any modes such as call tip or auto-completion list display.
+fun void Cancel=2325(,)
+
+# Delete the selection or if no selection, the character before the caret.
+fun void DeleteBack=2326(,)
+
+# If selection is empty or all on one line replace the selection with a tab character.
+# If more than one line selected, indent the lines.
+fun void Tab=2327(,)
+
+# Dedent the selected lines.
+fun void BackTab=2328(,)
+
+# Insert a new line, may use a CRLF, CR or LF depending on EOL mode.
+fun void NewLine=2329(,)
+
+# Insert a Form Feed character.
+fun void FormFeed=2330(,)
+
+# Move caret to before first visible character on line.
+# If already there move to first character on line.
+fun void VCHome=2331(,)
+
+# Like VCHome but extending selection to new caret position.
+fun void VCHomeExtend=2332(,)
+
+# Magnify the displayed text by increasing the sizes by 1 point.
+fun void ZoomIn=2333(,)
+
+# Make the displayed text smaller by decreasing the sizes by 1 point.
+fun void ZoomOut=2334(,)
+
+# Delete the word to the left of the caret.
+fun void DelWordLeft=2335(,)
+
+# Delete the word to the right of the caret.
+fun void DelWordRight=2336(,)
+
+# Delete the word to the right of the caret, but not the trailing non-word characters.
+fun void DelWordRightEnd=2518(,)
+
+# Cut the line containing the caret.
+fun void LineCut=2337(,)
+
+# Delete the line containing the caret.
+fun void LineDelete=2338(,)
+
+# Switch the current line with the previous.
+fun void LineTranspose=2339(,)
+
+# Duplicate the current line.
+fun void LineDuplicate=2404(,)
+
+# Transform the selection to lower case.
+fun void LowerCase=2340(,)
+
+# Transform the selection to upper case.
+fun void UpperCase=2341(,)
+
+# Scroll the document down, keeping the caret visible.
+fun void LineScrollDown=2342(,)
+
+# Scroll the document up, keeping the caret visible.
+fun void LineScrollUp=2343(,)
+
+# Delete the selection or if no selection, the character before the caret.
+# Will not delete the character before at the start of a line.
+fun void DeleteBackNotLine=2344(,)
+
+# Move caret to first position on display line.
+fun void HomeDisplay=2345(,)
+
+# Move caret to first position on display line extending selection to
+# new caret position.
+fun void HomeDisplayExtend=2346(,)
+
+# Move caret to last position on display line.
+fun void LineEndDisplay=2347(,)
+
+# Move caret to last position on display line extending selection to new
+# caret position.
+fun void LineEndDisplayExtend=2348(,)
+
+# These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)?
+# except they behave differently when word-wrap is enabled:
+# They go first to the start / end of the display line, like (Home|LineEnd)Display
+# The difference is that, the cursor is already at the point, it goes on to the start
+# or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.
+
+fun void HomeWrap=2349(,)
+fun void HomeWrapExtend=2450(,)
+fun void LineEndWrap=2451(,)
+fun void LineEndWrapExtend=2452(,)
+fun void VCHomeWrap=2453(,)
+fun void VCHomeWrapExtend=2454(,)
+
+# Copy the line containing the caret.
+fun void LineCopy=2455(,)
+
+# Move the caret inside current view if it's not there already.
+fun void MoveCaretInsideView=2401(,)
+
+# How many characters are on a line, including end of line characters?
+fun int LineLength=2350(int line,)
+
+# Highlight the characters at two positions.
+fun void BraceHighlight=2351(position pos1, position pos2)
+
+# Highlight the character at a position indicating there is no matching brace.
+fun void BraceBadLight=2352(position pos,)
+
+# Find the position of a matching brace or INVALID_POSITION if no match.
+fun position BraceMatch=2353(position pos,)
+
+# Are the end of line characters visible?
+get bool GetViewEOL=2355(,)
+
+# Make the end of line characters visible or invisible.
+set void SetViewEOL=2356(bool visible,)
+
+# Retrieve a pointer to the document object.
+get int GetDocPointer=2357(,)
+
+# Change the document object used.
+set void SetDocPointer=2358(, int pointer)
+
+# Set which document modification events are sent to the container.
+set void SetModEventMask=2359(int mask,)
+
+enu EdgeVisualStyle=EDGE_
+val EDGE_NONE=0
+val EDGE_LINE=1
+val EDGE_BACKGROUND=2
+
+# Retrieve the column number which text should be kept within.
+get int GetEdgeColumn=2360(,)
+
+# Set the column number of the edge.
+# If text goes past the edge then it is highlighted.
+set void SetEdgeColumn=2361(int column,)
+
+# Retrieve the edge highlight mode.
+get int GetEdgeMode=2362(,)
+
+# The edge may be displayed by a line (EDGE_LINE) or by highlighting text that
+# goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE).
+set void SetEdgeMode=2363(int mode,)
+
+# Retrieve the colour used in edge indication.
+get colour GetEdgeColour=2364(,)
+
+# Change the colour used in edge indication.
+set void SetEdgeColour=2365(colour edgeColour,)
+
+# Sets the current caret position to be the search anchor.
+fun void SearchAnchor=2366(,)
+
+# Find some text starting at the search anchor.
+# Does not ensure the selection is visible.
+fun int SearchNext=2367(int flags, string text)
+
+# Find some text starting at the search anchor and moving backwards.
+# Does not ensure the selection is visible.
+fun int SearchPrev=2368(int flags, string text)
+
+# Retrieves the number of lines completely visible.
+get int LinesOnScreen=2370(,)
+
+# Set whether a pop up menu is displayed automatically when the user presses
+# the wrong mouse button.
+fun void UsePopUp=2371(bool allowPopUp,)
+
+# Is the selection rectangular? The alternative is the more common stream selection.
+get bool SelectionIsRectangle=2372(,)
+
+# Set the zoom level. This number of points is added to the size of all fonts.
+# It may be positive to magnify or negative to reduce.
+set void SetZoom=2373(int zoom,)
+# Retrieve the zoom level.
+get int GetZoom=2374(,)
+
+# Create a new document object.
+# Starts with reference count of 1 and not selected into editor.
+fun int CreateDocument=2375(,)
+# Extend life of document.
+fun void AddRefDocument=2376(, int doc)
+# Release a reference to the document, deleting document if it fades to black.
+fun void ReleaseDocument=2377(, int doc)
+
+# Get which document modification events are sent to the container.
+get int GetModEventMask=2378(,)
+
+# Change internal focus flag.
+set void SetFocus=2380(bool focus,)
+# Get internal focus flag.
+get bool GetFocus=2381(,)
+
+enu Status=SC_STATUS_
+val SC_STATUS_OK=0
+val SC_STATUS_FAILURE=1
+val SC_STATUS_BADALLOC=2
+
+# Change error status - 0 = OK.
+set void SetStatus=2382(int statusCode,)
+# Get error status.
+get int GetStatus=2383(,)
+
+# Set whether the mouse is captured when its button is pressed.
+set void SetMouseDownCaptures=2384(bool captures,)
+# Get whether mouse gets captured.
+get bool GetMouseDownCaptures=2385(,)
+
+enu CursorShape=SC_CURSOR
+val SC_CURSORNORMAL=-1
+val SC_CURSORWAIT=4
+# Sets the cursor to one of the SC_CURSOR* values.
+set void SetCursor=2386(int cursorType,)
+# Get cursor type.
+get int GetCursor=2387(,)
+
+# Change the way control characters are displayed:
+# If symbol is < 32, keep the drawn way, else, use the given character.
+set void SetControlCharSymbol=2388(int symbol,)
+# Get the way control characters are displayed.
+get int GetControlCharSymbol=2389(,)
+
+# Move to the previous change in capitalisation.
+fun void WordPartLeft=2390(,)
+# Move to the previous change in capitalisation extending selection
+# to new caret position.
+fun void WordPartLeftExtend=2391(,)
+# Move to the change next in capitalisation.
+fun void WordPartRight=2392(,)
+# Move to the next change in capitalisation extending selection
+# to new caret position.
+fun void WordPartRightExtend=2393(,)
+
+# Constants for use with SetVisiblePolicy, similar to SetCaretPolicy.
+val VISIBLE_SLOP=0x01
+val VISIBLE_STRICT=0x04
+# Set the way the display area is determined when a particular line
+# is to be moved to by Find, FindNext, GotoLine, etc.
+fun void SetVisiblePolicy=2394(int visiblePolicy, int visibleSlop)
+
+# Delete back from the current position to the start of the line.
+fun void DelLineLeft=2395(,)
+
+# Delete forwards from the current position to the end of the line.
+fun void DelLineRight=2396(,)
+
+# Get and Set the xOffset (ie, horizonal scroll position).
+set void SetXOffset=2397(int newOffset,)
+get int GetXOffset=2398(,)
+
+# Set the last x chosen value to be the caret x position.
+fun void ChooseCaretX=2399(,)
+
+# Set the focus to this Scintilla widget.
+fun void GrabFocus=2400(,)
+
+enu CaretPolicy=CARET_
+# Caret policy, used by SetXCaretPolicy and SetYCaretPolicy.
+# If CARET_SLOP is set, we can define a slop value: caretSlop.
+# This value defines an unwanted zone (UZ) where the caret is... unwanted.
+# This zone is defined as a number of pixels near the vertical margins,
+# and as a number of lines near the horizontal margins.
+# By keeping the caret away from the edges, it is seen within its context,
+# so it is likely that the identifier that the caret is on can be completely seen,
+# and that the current line is seen with some of the lines following it which are
+# often dependent on that line.
+val CARET_SLOP=0x01
+# If CARET_STRICT is set, the policy is enforced... strictly.
+# The caret is centred on the display if slop is not set,
+# and cannot go in the UZ if slop is set.
+val CARET_STRICT=0x04
+# If CARET_JUMPS is set, the display is moved more energetically
+# so the caret can move in the same direction longer before the policy is applied again.
+val CARET_JUMPS=0x10
+# If CARET_EVEN is not set, instead of having symmetrical UZs,
+# the left and bottom UZs are extended up to right and top UZs respectively.
+# This way, we favour the displaying of useful information: the begining of lines,
+# where most code reside, and the lines after the caret, eg. the body of a function.
+val CARET_EVEN=0x08
+
+# Set the way the caret is kept visible when going sideway.
+# The exclusion zone is given in pixels.
+fun void SetXCaretPolicy=2402(int caretPolicy, int caretSlop)
+
+# Set the way the line the caret is on is kept visible.
+# The exclusion zone is given in lines.
+fun void SetYCaretPolicy=2403(int caretPolicy, int caretSlop)
+
+# Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE).
+set void SetPrintWrapMode=2406(int mode,)
+
+# Is printing line wrapped?
+get int GetPrintWrapMode=2407(,)
+
+# Set a fore colour for active hotspots.
+set void SetHotspotActiveFore=2410(bool useSetting, colour fore)
+
+# Get the fore colour for active hotspots.
+get colour GetHotspotActiveFore=2494(,)
+
+# Set a back colour for active hotspots.
+set void SetHotspotActiveBack=2411(bool useSetting, colour back)
+
+# Get the back colour for active hotspots.
+get colour GetHotspotActiveBack=2495(,)
+
+# Enable / Disable underlining active hotspots.
+set void SetHotspotActiveUnderline=2412(bool underline,)
+
+# Get whether underlining for active hotspots.
+get bool GetHotspotActiveUnderline=2496(,)
+
+# Limit hotspots to single line so hotspots on two lines don't merge.
+set void SetHotspotSingleLine=2421(bool singleLine,)
+
+# Get the HotspotSingleLine property
+get bool GetHotspotSingleLine=2497(,)
+
+# Move caret between paragraphs (delimited by empty lines).
+fun void ParaDown=2413(,)
+fun void ParaDownExtend=2414(,)
+fun void ParaUp=2415(,)
+fun void ParaUpExtend=2416(,)
+
+# Given a valid document position, return the previous position taking code
+# page into account. Returns 0 if passed 0.
+fun position PositionBefore=2417(position pos,)
+
+# Given a valid document position, return the next position taking code
+# page into account. Maximum value returned is the last position in the document.
+fun position PositionAfter=2418(position pos,)
+
+# Copy a range of text to the clipboard. Positions are clipped into the document.
+fun void CopyRange=2419(position start, position end)
+
+# Copy argument text to the clipboard.
+fun void CopyText=2420(int length, string text)
+
+enu SelectionMode=SC_SEL_
+val SC_SEL_STREAM=0
+val SC_SEL_RECTANGLE=1
+val SC_SEL_LINES=2
+val SC_SEL_THIN=3
+
+# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or
+# by lines (SC_SEL_LINES).
+set void SetSelectionMode=2422(int mode,)
+
+# Get the mode of the current selection.
+get int GetSelectionMode=2423(,)
+
+# Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line).
+fun position GetLineSelStartPosition=2424(int line,)
+
+# Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line).
+fun position GetLineSelEndPosition=2425(int line,)
+
+## RectExtended rectangular selection moves
+# Move caret down one line, extending rectangular selection to new caret position.
+fun void LineDownRectExtend=2426(,)
+
+# Move caret up one line, extending rectangular selection to new caret position.
+fun void LineUpRectExtend=2427(,)
+
+# Move caret left one character, extending rectangular selection to new caret position.
+fun void CharLeftRectExtend=2428(,)
+
+# Move caret right one character, extending rectangular selection to new caret position.
+fun void CharRightRectExtend=2429(,)
+
+# Move caret to first position on line, extending rectangular selection to new caret position.
+fun void HomeRectExtend=2430(,)
+
+# Move caret to before first visible character on line.
+# If already there move to first character on line.
+# In either case, extend rectangular selection to new caret position.
+fun void VCHomeRectExtend=2431(,)
+
+# Move caret to last position on line, extending rectangular selection to new caret position.
+fun void LineEndRectExtend=2432(,)
+
+# Move caret one page up, extending rectangular selection to new caret position.
+fun void PageUpRectExtend=2433(,)
+
+# Move caret one page down, extending rectangular selection to new caret position.
+fun void PageDownRectExtend=2434(,)
+
+
+# Move caret to top of page, or one page up if already at top of page.
+fun void StutteredPageUp=2435(,)
+
+# Move caret to top of page, or one page up if already at top of page, extending selection to new caret position.
+fun void StutteredPageUpExtend=2436(,)
+
+# Move caret to bottom of page, or one page down if already at bottom of page.
+fun void StutteredPageDown=2437(,)
+
+# Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position.
+fun void StutteredPageDownExtend=2438(,)
+
+
+# Move caret left one word, position cursor at end of word.
+fun void WordLeftEnd=2439(,)
+
+# Move caret left one word, position cursor at end of word, extending selection to new caret position.
+fun void WordLeftEndExtend=2440(,)
+
+# Move caret right one word, position cursor at end of word.
+fun void WordRightEnd=2441(,)
+
+# Move caret right one word, position cursor at end of word, extending selection to new caret position.
+fun void WordRightEndExtend=2442(,)
+
+# Set the set of characters making up whitespace for when moving or selecting by word.
+# Should be called after SetWordChars.
+set void SetWhitespaceChars=2443(, string characters)
+
+# Reset the set of characters for whitespace and word characters to the defaults.
+fun void SetCharsDefault=2444(,)
+
+# Get currently selected item position in the auto-completion list
+fun int AutoCGetCurrent=2445(,)
+
+# Get currently selected item text in the auto-completion list
+# Returns the length of the item text
+fun int AutoCGetCurrentText=2610(, stringresult s)
+
+# Enlarge the document to a particular size of text bytes.
+fun void Allocate=2446(int bytes,)
+
+# Returns the target converted to UTF8.
+# Return the length in bytes.
+fun int TargetAsUTF8=2447(, stringresult s)
+
+# Set the length of the utf8 argument for calling EncodedFromUTF8.
+# 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.
+# Return the length of the result in 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
+# 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(,)
+
+val SC_ALPHA_TRANSPARENT=0
+val SC_ALPHA_OPAQUE=255
+val SC_ALPHA_NOALPHA=256
+
+# Set background alpha of the caret line.
+set void SetCaretLineBackAlpha=2470(int alpha,)
+
+# Get the background alpha of the caret line.
+get int GetCaretLineBackAlpha=2471(,)
+
+enu CaretStyle=CARETSTYLE_
+val CARETSTYLE_INVISIBLE=0
+val CARETSTYLE_LINE=1
+val CARETSTYLE_BLOCK=2
+
+# Set the style of the caret to be drawn.
+set void SetCaretStyle=2512(int caretStyle,)
+
+# Returns the current style of the caret.
+get int GetCaretStyle=2513(,)
+
+# Set the indicator used for IndicatorFillRange and IndicatorClearRange
+set void SetIndicatorCurrent=2500(int indicator,)
+
+# Get the current indicator
+get int GetIndicatorCurrent=2501(,)
+
+# Set the value used for IndicatorFillRange
+set void SetIndicatorValue=2502(int value,)
+
+# Get the current indicator vaue
+get int GetIndicatorValue=2503(,)
+
+# Turn a indicator on over a range.
+fun void IndicatorFillRange=2504(int position, int fillLength)
+
+# Turn a indicator off over a range.
+fun void IndicatorClearRange=2505(int position, int clearLength)
+
+# Are any indicators present at position?
+fun int IndicatorAllOnFor=2506(int position,)
+
+# What value does a particular indicator have at at a position?
+fun int IndicatorValueAt=2507(int indicator, int position)
+
+# Where does a particular indicator start?
+fun int IndicatorStart=2508(int indicator, int position)
+
+# Where does a particular indicator end?
+fun int IndicatorEnd=2509(int indicator, int position)
+
+# Set number of entries in position cache
+set void SetPositionCache=2514(int size,)
+
+# How many entries are allocated to the position cache?
+get int GetPositionCache=2515(,)
+
+# Copy the selection, if selection empty copy the line with the caret
+fun void CopyAllowLine=2519(,)
+
+# Compact the document buffer and return a read-only pointer to the
+# characters in the document.
+get int GetCharacterPointer=2520(,)
+
+# Always interpret keyboard input as Unicode
+set void SetKeysUnicode=2521(bool keysUnicode,)
+
+# Are keys always interpreted as Unicode?
+get bool GetKeysUnicode=2522(,)
+
+# Set the alpha fill colour of the given indicator.
+set void IndicSetAlpha=2523(int indicator, int alpha)
+
+# Get the alpha fill colour of the given indicator.
+get int IndicGetAlpha=2524(int indicator,)
+
+# Set extra ascent for each line
+set void SetExtraAscent=2525(int extraAscent,)
+
+# Get extra ascent for each line
+get int GetExtraAscent=2526(,)
+
+# Set extra descent for each line
+set void SetExtraDescent=2527(int extraDescent,)
+
+# Get extra descent for each line
+get int GetExtraDescent=2528(,)
+
+# Which symbol was defined for markerNumber with MarkerDefine
+fun int MarkerSymbolDefined=2529(int markerNumber,)
+
+# Set the text in the text margin for a line
+set void MarginSetText=2530(int line, string text)
+
+# Get the text in the text margin for a line
+get int MarginGetText=2531(int line, stringresult text)
+
+# Set the style number for the text margin for a line
+set void MarginSetStyle=2532(int line, int style)
+
+# Get the style number for the text margin for a line
+get int MarginGetStyle=2533(int line,)
+
+# Set the style in the text margin for a line
+set void MarginSetStyles=2534(int line, string styles)
+
+# Get the styles in the text margin for a line
+get int MarginGetStyles=2535(int line, stringresult styles)
+
+# Clear the margin text on all lines
+fun void MarginTextClearAll=2536(,)
+
+# Get the start of the range of style numbers used for margin text
+set void MarginSetStyleOffset=2537(int style,)
+
+# Get the start of the range of style numbers used for margin text
+get int MarginGetStyleOffset=2538(,)
+
+# Set the annotation text for a line
+set void AnnotationSetText=2540(int line, string text)
+
+# Get the annotation text for a line
+get int AnnotationGetText=2541(int line, stringresult text)
+
+# Set the style number for the annotations for a line
+set void AnnotationSetStyle=2542(int line, int style)
+
+# Get the style number for the annotations for a line
+get int AnnotationGetStyle=2543(int line,)
+
+# Set the annotation styles for a line
+set void AnnotationSetStyles=2544(int line, string styles)
+
+# Get the annotation styles for a line
+get int AnnotationGetStyles=2545(int line, stringresult styles)
+
+# Get the number of annotation lines for a line
+get int AnnotationGetLines=2546(int line,)
+
+# Clear the annotations from all lines
+fun void AnnotationClearAll=2547(,)
+
+enu AnnotationVisible=ANNOTATION_
+val ANNOTATION_HIDDEN=0
+val ANNOTATION_STANDARD=1
+val ANNOTATION_BOXED=2
+
+# Set the visibility for the annotations for a view
+set void AnnotationSetVisible=2548(int visible,)
+
+# Get the visibility for the annotations for a view
+get int AnnotationGetVisible=2549(,)
+
+# Get the start of the range of style numbers used for annotations
+set void AnnotationSetStyleOffset=2550(int style,)
+
+# Get the start of the range of style numbers used for annotations
+get int AnnotationGetStyleOffset=2551(,)
+
+val UNDO_MAY_COALESCE=1
+
+# Add a container action to the undo stack
+fun void AddUndoAction=2560(int token, int flags)
+
+# Find the position of a character from a point within the window.
+fun position CharPositionFromPoint=2561(int x, int y)
+
+# Find the position of a character from a point within the window.
+# Return INVALID_POSITION if not close to text.
+fun position CharPositionFromPointClose=2562(int x, int y)
+
+# Set whether multiple selections can be made
+set void SetMultipleSelection=2563(bool multipleSelection,)
+
+# Whether multiple selections can be made
+get bool GetMultipleSelection=2564(,)
+
+# Set whether typing can be performed into multiple selections
+set void SetAdditionalSelectionTyping=2565(bool additionalSelectionTyping,)
+
+# Whether typing can be performed into multiple selections
+get bool GetAdditionalSelectionTyping=2566(,)
+
+# Set whether additional carets will blink
+set void SetAdditionalCaretsBlink=2567(bool additionalCaretsBlink,)
+
+# Whether additional carets will blink
+get bool GetAdditionalCaretsBlink=2568(,)
+
+# Set whether additional carets are visible
+set void SetAdditionalCaretsVisible=2608(bool additionalCaretsBlink,)
+
+# Whether additional carets are visible
+get bool GetAdditionalCaretsVisible=2609(,)
+
+# How many selections are there?
+get int GetSelections=2570(,)
+
+# Clear selections to a single empty stream selection
+fun void ClearSelections=2571(,)
+
+# Set a simple selection
+fun int SetSelection=2572(int caret,int anchor)
+
+# Add a selection
+fun int AddSelection=2573(int caret,int anchor)
+
+# Set the main selection
+set void SetMainSelection=2574(int selection,)
+
+# Which selection is the main selection
+get int GetMainSelection=2575(,)
+
+set void SetSelectionNCaret=2576(int selection, position pos)
+get position GetSelectionNCaret=2577(int selection,)
+set void SetSelectionNAnchor=2578(int selection, position posAnchor)
+get position GetSelectionNAnchor=2579(int selection,)
+set void SetSelectionNCaretVirtualSpace=2580(int selection, int space)
+get int GetSelectionNCaretVirtualSpace=2581(int selection,)
+set void SetSelectionNAnchorVirtualSpace=2582(int selection, int space)
+get int GetSelectionNAnchorVirtualSpace=2583(int selection,)
+
+# Sets the position that starts the selection - this becomes the anchor.
+set void SetSelectionNStart=2584(int selection, position pos)
+
+# Returns the position at the start of the selection.
+get position GetSelectionNStart=2585(int selection,)
+
+# Sets the position that ends the selection - this becomes the currentPosition.
+set void SetSelectionNEnd=2586(int selection, position pos,)
+
+# Returns the position at the end of the selection.
+get position GetSelectionNEnd=2587(int selection,)
+
+set void SetRectangularSelectionCaret=2588(position pos,)
+get position GetRectangularSelectionCaret=2589(,)
+set void SetRectangularSelectionAnchor=2590(position posAnchor,)
+get position GetRectangularSelectionAnchor=2591(,)
+set void SetRectangularSelectionCaretVirtualSpace=2592(int space,)
+get int GetRectangularSelectionCaretVirtualSpace=2593(,)
+set void SetRectangularSelectionAnchorVirtualSpace=2594(int space,)
+get int GetRectangularSelectionAnchorVirtualSpace=2595(,)
+
+enu VirtualSpace=SCVS_
+val SCVS_NONE=0
+val SCVS_RECTANGULARSELECTION=1
+val SCVS_USERACCESSIBLE=2
+
+set void SetVirtualSpaceOptions=2596(int virtualSpaceOptions,)
+get int GetVirtualSpaceOptions=2597(,)
+
+# On GTK+, allow selecting the modifier key to use for mouse-based
+# rectangular selection. Often the window manager requires Alt+Mouse Drag
+# for moving windows.
+# Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER.
+
+set void SetRectangularSelectionModifier=2598(int modifier,)
+
+# Get the modifier key used for rectangular selection.
+get int GetRectangularSelectionModifier=2599(,)
+
+# Set the foreground colour of additional selections.
+# Must have previously called SetSelFore with non-zero first argument for this to have an effect.
+set void SetAdditionalSelFore=2600(colour fore,)
+
+# Set the background colour of additional selections.
+# Must have previously called SetSelBack with non-zero first argument for this to have an effect.
+set void SetAdditionalSelBack=2601(colour back,)
+
+# Set the alpha of the selection.
+set void SetAdditionalSelAlpha=2602(int alpha,)
+
+# Get the alpha of the selection.
+get int GetAdditionalSelAlpha=2603(,)
+
+# Set the foreground colour of additional carets.
+set void SetAdditionalCaretFore=2604(colour fore,)
+
+# Get the foreground colour of additional carets.
+get colour GetAdditionalCaretFore=2605(,)
+
+# Set the main selection to the next selection.
+fun void RotateSelection=2606(,)
+
+# Swap that caret and anchor of the main selection.
+fun void SwapMainAnchorCaret=2607(,)
+
+# Start notifying the container of all key presses and commands.
+fun void StartRecord=3001(,)
+
+# Stop notifying the container of all key presses and commands.
+fun void StopRecord=3002(,)
+
+# Set the lexing language of the document.
+set void SetLexer=4001(int lexer,)
+
+# Retrieve the lexing language of the document.
+get int GetLexer=4002(,)
+
+# Colourise a segment of the document using the current lexing language.
+fun void Colourise=4003(position start, position end)
+
+# Set up a value that may be used by a lexer for some optional feature.
+set void SetProperty=4004(string key, string value)
+
+# Maximum value of keywordSet parameter of SetKeyWords.
+val KEYWORDSET_MAX=8
+
+# Set up the key words used by the lexer.
+set void SetKeyWords=4005(int keywordSet, string keyWords)
+
+# Set the lexing language of the document based on string name.
+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(,)
+
+# Retrieve the name of the lexer.
+# Return the length of the text.
+get int GetLexerLanguage=4012(, stringresult text)
+
+# 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.
+# One bit is set from each of SC_MOD_* and SC_PERFORMED_*.
+enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_LAST
+val SC_MOD_INSERTTEXT=0x1
+val SC_MOD_DELETETEXT=0x2
+val SC_MOD_CHANGESTYLE=0x4
+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_MULTILINEUNDOREDO=0x1000
+val SC_STARTACTION=0x2000
+val SC_MOD_CHANGEINDICATOR=0x4000
+val SC_MOD_CHANGELINESTATE=0x8000
+val SC_MOD_CHANGEMARGIN=0x10000
+val SC_MOD_CHANGEANNOTATION=0x20000
+val SC_MOD_CONTAINER=0x40000
+val SC_MODEVENTMASKALL=0x7FFFF
+
+# For compatibility, these go through the COMMAND notification rather than NOTIFY
+# and should have had exactly the same values as the EN_* constants.
+# Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_*
+# As clients depend on these constants, this will not be changed.
+val SCEN_CHANGE=768
+val SCEN_SETFOCUS=512
+val SCEN_KILLFOCUS=256
+
+# Symbolic key codes and modifier flags.
+# ASCII and other printable characters below 256.
+# Extended keys above 300.
+
+enu Keys=SCK_
+val SCK_DOWN=300
+val SCK_UP=301
+val SCK_LEFT=302
+val SCK_RIGHT=303
+val SCK_HOME=304
+val SCK_END=305
+val SCK_PRIOR=306
+val SCK_NEXT=307
+val SCK_DELETE=308
+val SCK_INSERT=309
+val SCK_ESCAPE=7
+val SCK_BACK=8
+val SCK_TAB=9
+val SCK_RETURN=13
+val SCK_ADD=310
+val SCK_SUBTRACT=311
+val SCK_DIVIDE=312
+val SCK_WIN=313
+val SCK_RWIN=314
+val SCK_MENU=315
+
+enu KeyMod=SCMOD_
+val SCMOD_NORM=0
+val SCMOD_SHIFT=1
+val SCMOD_CTRL=2
+val SCMOD_ALT=4
+val SCMOD_SUPER=8
+
+################################################
+# For SciLexer.h
+enu Lexer=SCLEX_
+val SCLEX_CONTAINER=0
+val SCLEX_NULL=1
+val SCLEX_PYTHON=2
+val SCLEX_CPP=3
+val SCLEX_HTML=4
+val SCLEX_XML=5
+val SCLEX_PERL=6
+val SCLEX_SQL=7
+val SCLEX_VB=8
+val SCLEX_PROPERTIES=9
+val SCLEX_ERRORLIST=10
+val SCLEX_MAKEFILE=11
+val SCLEX_BATCH=12
+val SCLEX_XCODE=13
+val SCLEX_LATEX=14
+val SCLEX_LUA=15
+val SCLEX_DIFF=16
+val SCLEX_CONF=17
+val SCLEX_PASCAL=18
+val SCLEX_AVE=19
+val SCLEX_ADA=20
+val SCLEX_LISP=21
+val SCLEX_RUBY=22
+val SCLEX_EIFFEL=23
+val SCLEX_EIFFELKW=24
+val SCLEX_TCL=25
+val SCLEX_NNCRONTAB=26
+val SCLEX_BULLANT=27
+val SCLEX_VBSCRIPT=28
+val SCLEX_BAAN=31
+val SCLEX_MATLAB=32
+val SCLEX_SCRIPTOL=33
+val SCLEX_ASM=34
+val SCLEX_CPPNOCASE=35
+val SCLEX_FORTRAN=36
+val SCLEX_F77=37
+val SCLEX_CSS=38
+val SCLEX_POV=39
+val SCLEX_LOUT=40
+val SCLEX_ESCRIPT=41
+val SCLEX_PS=42
+val SCLEX_NSIS=43
+val SCLEX_MMIXAL=44
+val SCLEX_CLW=45
+val SCLEX_CLWNOCASE=46
+val SCLEX_LOT=47
+val SCLEX_YAML=48
+val SCLEX_TEX=49
+val SCLEX_METAPOST=50
+val SCLEX_POWERBASIC=51
+val SCLEX_FORTH=52
+val SCLEX_ERLANG=53
+val SCLEX_OCTAVE=54
+val SCLEX_MSSQL=55
+val SCLEX_VERILOG=56
+val SCLEX_KIX=57
+val SCLEX_GUI4CLI=58
+val SCLEX_SPECMAN=59
+val SCLEX_AU3=60
+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
+val SCLEX_INNOSETUP=76
+val SCLEX_OPAL=77
+val SCLEX_SPICE=78
+val SCLEX_D=79
+val SCLEX_CMAKE=80
+val SCLEX_GAP=81
+val SCLEX_PLM=82
+val SCLEX_PROGRESS=83
+val SCLEX_ABAQUS=84
+val SCLEX_ASYMPTOTE=85
+val SCLEX_R=86
+val SCLEX_MAGIK=87
+val SCLEX_POWERSHELL=88
+val SCLEX_MYSQL=89
+val SCLEX_PO=90
+val SCLEX_TAL=91
+val SCLEX_COBOL=92
+val SCLEX_TACL=93
+val SCLEX_SORCUS=94
+val SCLEX_POWERPRO=95
+val SCLEX_NIMROD=96
+val SCLEX_SML=97
+val SCLEX_MARKDOWN=98
+
+# 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 Nimrod=SCLEX_NIMROD SCE_P_
+val SCE_P_DEFAULT=0
+val SCE_P_COMMENTLINE=1
+val SCE_P_NUMBER=2
+val SCE_P_STRING=3
+val SCE_P_CHARACTER=4
+val SCE_P_WORD=5
+val SCE_P_TRIPLE=6
+val SCE_P_TRIPLEDOUBLE=7
+val SCE_P_CLASSNAME=8
+val SCE_P_DEFNAME=9
+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 BullAnt=SCLEX_BULLANT SCE_C_
+val SCE_C_DEFAULT=0
+val SCE_C_COMMENT=1
+val SCE_C_COMMENTLINE=2
+val SCE_C_COMMENTDOC=3
+val SCE_C_NUMBER=4
+val SCE_C_WORD=5
+val SCE_C_STRING=6
+val SCE_C_CHARACTER=7
+val SCE_C_UUID=8
+val SCE_C_PREPROCESSOR=9
+val SCE_C_OPERATOR=10
+val SCE_C_IDENTIFIER=11
+val SCE_C_STRINGEOL=12
+val SCE_C_VERBATIM=13
+val SCE_C_REGEX=14
+val SCE_C_COMMENTLINEDOC=15
+val SCE_C_WORD2=16
+val SCE_C_COMMENTDOCKEYWORD=17
+val SCE_C_COMMENTDOCKEYWORDERROR=18
+val SCE_C_GLOBALCLASS=19
+# Lexical states for SCLEX_D
+lex D=SCLEX_D SCE_D_
+val SCE_D_DEFAULT=0
+val SCE_D_COMMENT=1
+val SCE_D_COMMENTLINE=2
+val SCE_D_COMMENTDOC=3
+val SCE_D_COMMENTNESTED=4
+val SCE_D_NUMBER=5
+val SCE_D_WORD=6
+val SCE_D_WORD2=7
+val SCE_D_WORD3=8
+val SCE_D_TYPEDEF=9
+val SCE_D_STRING=10
+val SCE_D_STRINGEOL=11
+val SCE_D_CHARACTER=12
+val SCE_D_OPERATOR=13
+val SCE_D_IDENTIFIER=14
+val SCE_D_COMMENTLINEDOC=15
+val SCE_D_COMMENTDOCKEYWORD=16
+val SCE_D_COMMENTDOCKEYWORDERROR=17
+val SCE_D_STRINGB=18
+val SCE_D_STRINGR=19
+val SCE_D_WORD5=20
+val SCE_D_WORD6=21
+val SCE_D_WORD7=22
+# Lexical states for SCLEX_TCL
+lex TCL=SCLEX_TCL SCE_TCL_
+val SCE_TCL_DEFAULT=0
+val SCE_TCL_COMMENT=1
+val SCE_TCL_COMMENTLINE=2
+val SCE_TCL_NUMBER=3
+val SCE_TCL_WORD_IN_QUOTE=4
+val SCE_TCL_IN_QUOTE=5
+val SCE_TCL_OPERATOR=6
+val SCE_TCL_IDENTIFIER=7
+val SCE_TCL_SUBSTITUTION=8
+val SCE_TCL_SUB_BRACE=9
+val SCE_TCL_MODIFIER=10
+val SCE_TCL_EXPAND=11
+val SCE_TCL_WORD=12
+val SCE_TCL_WORD2=13
+val SCE_TCL_WORD3=14
+val SCE_TCL_WORD4=15
+val SCE_TCL_WORD5=16
+val SCE_TCL_WORD6=17
+val SCE_TCL_WORD7=18
+val SCE_TCL_WORD8=19
+val SCE_TCL_COMMENT_BOX=20
+val SCE_TCL_BLOCK_COMMENT=21
+# Lexical states for SCLEX_HTML, SCLEX_XML
+lex HTML=SCLEX_HTML SCE_H
+lex XML=SCLEX_XML SCE_H
+lex ASP=SCLEX_ASP SCE_H
+lex PHP=SCLEX_PHP SCE_H
+val SCE_H_DEFAULT=0
+val SCE_H_TAG=1
+val SCE_H_TAGUNKNOWN=2
+val SCE_H_ATTRIBUTE=3
+val SCE_H_ATTRIBUTEUNKNOWN=4
+val SCE_H_NUMBER=5
+val SCE_H_DOUBLESTRING=6
+val SCE_H_SINGLESTRING=7
+val SCE_H_OTHER=8
+val SCE_H_COMMENT=9
+val SCE_H_ENTITY=10
+# XML and ASP
+val SCE_H_TAGEND=11
+val SCE_H_XMLSTART=12
+val SCE_H_XMLEND=13
+val SCE_H_SCRIPT=14
+val SCE_H_ASP=15
+val SCE_H_ASPAT=16
+val SCE_H_CDATA=17
+val SCE_H_QUESTION=18
+# More HTML
+val SCE_H_VALUE=19
+# X-Code
+val SCE_H_XCCOMMENT=20
+# SGML
+val SCE_H_SGML_DEFAULT=21
+val SCE_H_SGML_COMMAND=22
+val SCE_H_SGML_1ST_PARAM=23
+val SCE_H_SGML_DOUBLESTRING=24
+val SCE_H_SGML_SIMPLESTRING=25
+val SCE_H_SGML_ERROR=26
+val SCE_H_SGML_SPECIAL=27
+val SCE_H_SGML_ENTITY=28
+val SCE_H_SGML_COMMENT=29
+val SCE_H_SGML_1ST_PARAM_COMMENT=30
+val SCE_H_SGML_BLOCK_DEFAULT=31
+# Embedded Javascript
+val SCE_HJ_START=40
+val SCE_HJ_DEFAULT=41
+val SCE_HJ_COMMENT=42
+val SCE_HJ_COMMENTLINE=43
+val SCE_HJ_COMMENTDOC=44
+val SCE_HJ_NUMBER=45
+val SCE_HJ_WORD=46
+val SCE_HJ_KEYWORD=47
+val SCE_HJ_DOUBLESTRING=48
+val SCE_HJ_SINGLESTRING=49
+val SCE_HJ_SYMBOLS=50
+val SCE_HJ_STRINGEOL=51
+val SCE_HJ_REGEX=52
+# ASP Javascript
+val SCE_HJA_START=55
+val SCE_HJA_DEFAULT=56
+val SCE_HJA_COMMENT=57
+val SCE_HJA_COMMENTLINE=58
+val SCE_HJA_COMMENTDOC=59
+val SCE_HJA_NUMBER=60
+val SCE_HJA_WORD=61
+val SCE_HJA_KEYWORD=62
+val SCE_HJA_DOUBLESTRING=63
+val SCE_HJA_SINGLESTRING=64
+val SCE_HJA_SYMBOLS=65
+val SCE_HJA_STRINGEOL=66
+val SCE_HJA_REGEX=67
+# Embedded VBScript
+val SCE_HB_START=70
+val SCE_HB_DEFAULT=71
+val SCE_HB_COMMENTLINE=72
+val SCE_HB_NUMBER=73
+val SCE_HB_WORD=74
+val SCE_HB_STRING=75
+val SCE_HB_IDENTIFIER=76
+val SCE_HB_STRINGEOL=77
+# ASP VBScript
+val SCE_HBA_START=80
+val SCE_HBA_DEFAULT=81
+val SCE_HBA_COMMENTLINE=82
+val SCE_HBA_NUMBER=83
+val SCE_HBA_WORD=84
+val SCE_HBA_STRING=85
+val SCE_HBA_IDENTIFIER=86
+val SCE_HBA_STRINGEOL=87
+# Embedded Python
+val SCE_HP_START=90
+val SCE_HP_DEFAULT=91
+val SCE_HP_COMMENTLINE=92
+val SCE_HP_NUMBER=93
+val SCE_HP_STRING=94
+val SCE_HP_CHARACTER=95
+val SCE_HP_WORD=96
+val SCE_HP_TRIPLE=97
+val SCE_HP_TRIPLEDOUBLE=98
+val SCE_HP_CLASSNAME=99
+val SCE_HP_DEFNAME=100
+val SCE_HP_OPERATOR=101
+val SCE_HP_IDENTIFIER=102
+# PHP
+val SCE_HPHP_COMPLEX_VARIABLE=104
+# ASP Python
+val SCE_HPA_START=105
+val SCE_HPA_DEFAULT=106
+val SCE_HPA_COMMENTLINE=107
+val SCE_HPA_NUMBER=108
+val SCE_HPA_STRING=109
+val SCE_HPA_CHARACTER=110
+val SCE_HPA_WORD=111
+val SCE_HPA_TRIPLE=112
+val SCE_HPA_TRIPLEDOUBLE=113
+val SCE_HPA_CLASSNAME=114
+val SCE_HPA_DEFNAME=115
+val SCE_HPA_OPERATOR=116
+val SCE_HPA_IDENTIFIER=117
+# PHP
+val SCE_HPHP_DEFAULT=118
+val SCE_HPHP_HSTRING=119
+val SCE_HPHP_SIMPLESTRING=120
+val SCE_HPHP_WORD=121
+val SCE_HPHP_NUMBER=122
+val SCE_HPHP_VARIABLE=123
+val SCE_HPHP_COMMENT=124
+val SCE_HPHP_COMMENTLINE=125
+val SCE_HPHP_HSTRING_VARIABLE=126
+val SCE_HPHP_OPERATOR=127
+# Lexical states for SCLEX_PERL
+lex Perl=SCLEX_PERL SCE_PL_
+val SCE_PL_DEFAULT=0
+val SCE_PL_ERROR=1
+val SCE_PL_COMMENTLINE=2
+val SCE_PL_POD=3
+val SCE_PL_NUMBER=4
+val SCE_PL_WORD=5
+val SCE_PL_STRING=6
+val SCE_PL_CHARACTER=7
+val SCE_PL_PUNCTUATION=8
+val SCE_PL_PREPROCESSOR=9
+val SCE_PL_OPERATOR=10
+val SCE_PL_IDENTIFIER=11
+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
+val SCE_PL_BACKTICKS=20
+val SCE_PL_DATASECTION=21
+val SCE_PL_HERE_DELIM=22
+val SCE_PL_HERE_Q=23
+val SCE_PL_HERE_QQ=24
+val SCE_PL_HERE_QX=25
+val SCE_PL_STRING_Q=26
+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
+val SCE_PL_SUB_PROTOTYPE=40
+val SCE_PL_FORMAT_IDENT=41
+val SCE_PL_FORMAT=42
+# 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_
+lex PowerBasic=SCLEX_POWERBASIC SCE_B_
+val SCE_B_DEFAULT=0
+val SCE_B_COMMENT=1
+val SCE_B_NUMBER=2
+val SCE_B_KEYWORD=3
+val SCE_B_STRING=4
+val SCE_B_PREPROCESSOR=5
+val SCE_B_OPERATOR=6
+val SCE_B_IDENTIFIER=7
+val SCE_B_DATE=8
+val SCE_B_STRINGEOL=9
+val SCE_B_KEYWORD2=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
+val SCE_PROPS_COMMENT=1
+val SCE_PROPS_SECTION=2
+val SCE_PROPS_ASSIGNMENT=3
+val SCE_PROPS_DEFVAL=4
+val SCE_PROPS_KEY=5
+# Lexical states for SCLEX_LATEX
+lex LaTeX=SCLEX_LATEX SCE_L_
+val SCE_L_DEFAULT=0
+val SCE_L_COMMAND=1
+val SCE_L_TAG=2
+val SCE_L_MATH=3
+val SCE_L_COMMENT=4
+# Lexical states for SCLEX_LUA
+lex Lua=SCLEX_LUA SCE_LUA_
+val SCE_LUA_DEFAULT=0
+val SCE_LUA_COMMENT=1
+val SCE_LUA_COMMENTLINE=2
+val SCE_LUA_COMMENTDOC=3
+val SCE_LUA_NUMBER=4
+val SCE_LUA_WORD=5
+val SCE_LUA_STRING=6
+val SCE_LUA_CHARACTER=7
+val SCE_LUA_LITERALSTRING=8
+val SCE_LUA_PREPROCESSOR=9
+val SCE_LUA_OPERATOR=10
+val SCE_LUA_IDENTIFIER=11
+val SCE_LUA_STRINGEOL=12
+val SCE_LUA_WORD2=13
+val SCE_LUA_WORD3=14
+val SCE_LUA_WORD4=15
+val SCE_LUA_WORD5=16
+val SCE_LUA_WORD6=17
+val SCE_LUA_WORD7=18
+val SCE_LUA_WORD8=19
+# Lexical states for SCLEX_ERRORLIST
+lex ErrorList=SCLEX_ERRORLIST SCE_ERR_
+val SCE_ERR_DEFAULT=0
+val SCE_ERR_PYTHON=1
+val SCE_ERR_GCC=2
+val SCE_ERR_MS=3
+val SCE_ERR_CMD=4
+val SCE_ERR_BORLAND=5
+val SCE_ERR_PERL=6
+val SCE_ERR_NET=7
+val SCE_ERR_LUA=8
+val SCE_ERR_CTAG=9
+val SCE_ERR_DIFF_CHANGED=10
+val SCE_ERR_DIFF_ADDITION=11
+val SCE_ERR_DIFF_DELETION=12
+val SCE_ERR_DIFF_MESSAGE=13
+val SCE_ERR_PHP=14
+val SCE_ERR_ELF=15
+val SCE_ERR_IFC=16
+val SCE_ERR_IFORT=17
+val SCE_ERR_ABSF=18
+val SCE_ERR_TIDY=19
+val SCE_ERR_JAVA_STACK=20
+val SCE_ERR_VALUE=21
+# Lexical states for SCLEX_BATCH
+lex Batch=SCLEX_BATCH SCE_BAT_
+val SCE_BAT_DEFAULT=0
+val SCE_BAT_COMMENT=1
+val SCE_BAT_WORD=2
+val SCE_BAT_LABEL=3
+val SCE_BAT_HIDE=4
+val SCE_BAT_COMMAND=5
+val SCE_BAT_IDENTIFIER=6
+val SCE_BAT_OPERATOR=7
+# Lexical states for SCLEX_MAKEFILE
+lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_
+val SCE_MAKE_DEFAULT=0
+val SCE_MAKE_COMMENT=1
+val SCE_MAKE_PREPROCESSOR=2
+val SCE_MAKE_IDENTIFIER=3
+val SCE_MAKE_OPERATOR=4
+val SCE_MAKE_TARGET=5
+val SCE_MAKE_IDEOL=9
+# Lexical states for SCLEX_DIFF
+lex Diff=SCLEX_DIFF SCE_DIFF_
+val SCE_DIFF_DEFAULT=0
+val SCE_DIFF_COMMENT=1
+val SCE_DIFF_COMMAND=2
+val SCE_DIFF_HEADER=3
+val SCE_DIFF_POSITION=4
+val SCE_DIFF_DELETED=5
+val SCE_DIFF_ADDED=6
+val SCE_DIFF_CHANGED=7
+# Lexical states for SCLEX_CONF (Apache Configuration Files Lexer)
+lex Conf=SCLEX_CONF SCE_CONF_
+val SCE_CONF_DEFAULT=0
+val SCE_CONF_COMMENT=1
+val SCE_CONF_NUMBER=2
+val SCE_CONF_IDENTIFIER=3
+val SCE_CONF_EXTENSION=4
+val SCE_CONF_PARAMETER=5
+val SCE_CONF_STRING=6
+val SCE_CONF_OPERATOR=7
+val SCE_CONF_IP=8
+val SCE_CONF_DIRECTIVE=9
+# Lexical states for SCLEX_AVE, Avenue
+lex Avenue=SCLEX_AVE SCE_AVE_
+val SCE_AVE_DEFAULT=0
+val SCE_AVE_COMMENT=1
+val SCE_AVE_NUMBER=2
+val SCE_AVE_WORD=3
+val SCE_AVE_STRING=6
+val SCE_AVE_ENUM=7
+val SCE_AVE_STRINGEOL=8
+val SCE_AVE_IDENTIFIER=9
+val SCE_AVE_OPERATOR=10
+val SCE_AVE_WORD1=11
+val SCE_AVE_WORD2=12
+val SCE_AVE_WORD3=13
+val SCE_AVE_WORD4=14
+val SCE_AVE_WORD5=15
+val SCE_AVE_WORD6=16
+# Lexical states for SCLEX_ADA
+lex Ada=SCLEX_ADA SCE_ADA_
+val SCE_ADA_DEFAULT=0
+val SCE_ADA_WORD=1
+val SCE_ADA_IDENTIFIER=2
+val SCE_ADA_NUMBER=3
+val SCE_ADA_DELIMITER=4
+val SCE_ADA_CHARACTER=5
+val SCE_ADA_CHARACTEREOL=6
+val SCE_ADA_STRING=7
+val SCE_ADA_STRINGEOL=8
+val SCE_ADA_LABEL=9
+val SCE_ADA_COMMENTLINE=10
+val SCE_ADA_ILLEGAL=11
+# Lexical states for SCLEX_BAAN
+lex Baan=SCLEX_BAAN SCE_BAAN_
+val SCE_BAAN_DEFAULT=0
+val SCE_BAAN_COMMENT=1
+val SCE_BAAN_COMMENTDOC=2
+val SCE_BAAN_NUMBER=3
+val SCE_BAAN_WORD=4
+val SCE_BAAN_STRING=5
+val SCE_BAAN_PREPROCESSOR=6
+val SCE_BAAN_OPERATOR=7
+val SCE_BAAN_IDENTIFIER=8
+val SCE_BAAN_STRINGEOL=9
+val SCE_BAAN_WORD2=10
+# Lexical states for SCLEX_LISP
+lex Lisp=SCLEX_LISP SCE_LISP_
+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_
+val SCE_EIFFEL_DEFAULT=0
+val SCE_EIFFEL_COMMENTLINE=1
+val SCE_EIFFEL_NUMBER=2
+val SCE_EIFFEL_WORD=3
+val SCE_EIFFEL_STRING=4
+val SCE_EIFFEL_CHARACTER=5
+val SCE_EIFFEL_OPERATOR=6
+val SCE_EIFFEL_IDENTIFIER=7
+val SCE_EIFFEL_STRINGEOL=8
+# Lexical states for SCLEX_NNCRONTAB (nnCron crontab Lexer)
+lex NNCronTab=SCLEX_NNCRONTAB SCE_NNCRONTAB_
+val SCE_NNCRONTAB_DEFAULT=0
+val SCE_NNCRONTAB_COMMENT=1
+val SCE_NNCRONTAB_TASK=2
+val SCE_NNCRONTAB_SECTION=3
+val SCE_NNCRONTAB_KEYWORD=4
+val SCE_NNCRONTAB_MODIFIER=5
+val SCE_NNCRONTAB_ASTERISK=6
+val SCE_NNCRONTAB_NUMBER=7
+val SCE_NNCRONTAB_STRING=8
+val SCE_NNCRONTAB_ENVIRONMENT=9
+val SCE_NNCRONTAB_IDENTIFIER=10
+# Lexical states for SCLEX_FORTH (Forth Lexer)
+lex Forth=SCLEX_FORTH SCE_FORTH_
+val SCE_FORTH_DEFAULT=0
+val SCE_FORTH_COMMENT=1
+val SCE_FORTH_COMMENT_ML=2
+val SCE_FORTH_IDENTIFIER=3
+val SCE_FORTH_CONTROL=4
+val SCE_FORTH_KEYWORD=5
+val SCE_FORTH_DEFWORD=6
+val SCE_FORTH_PREWORD1=7
+val SCE_FORTH_PREWORD2=8
+val SCE_FORTH_NUMBER=9
+val SCE_FORTH_STRING=10
+val SCE_FORTH_LOCALE=11
+# Lexical states for SCLEX_MATLAB
+lex MatLab=SCLEX_MATLAB SCE_MATLAB_
+val SCE_MATLAB_DEFAULT=0
+val SCE_MATLAB_COMMENT=1
+val SCE_MATLAB_COMMAND=2
+val SCE_MATLAB_NUMBER=3
+val SCE_MATLAB_KEYWORD=4
+# single quoted string
+val SCE_MATLAB_STRING=5
+val SCE_MATLAB_OPERATOR=6
+val SCE_MATLAB_IDENTIFIER=7
+val SCE_MATLAB_DOUBLEQUOTESTRING=8
+# Lexical states for SCLEX_SCRIPTOL
+lex Sol=SCLEX_SCRIPTOL SCE_SCRIPTOL_
+val SCE_SCRIPTOL_DEFAULT=0
+val SCE_SCRIPTOL_WHITE=1
+val SCE_SCRIPTOL_COMMENTLINE=2
+val SCE_SCRIPTOL_PERSISTENT=3
+val SCE_SCRIPTOL_CSTYLE=4
+val SCE_SCRIPTOL_COMMENTBLOCK=5
+val SCE_SCRIPTOL_NUMBER=6
+val SCE_SCRIPTOL_STRING=7
+val SCE_SCRIPTOL_CHARACTER=8
+val SCE_SCRIPTOL_STRINGEOL=9
+val SCE_SCRIPTOL_KEYWORD=10
+val SCE_SCRIPTOL_OPERATOR=11
+val SCE_SCRIPTOL_IDENTIFIER=12
+val SCE_SCRIPTOL_TRIPLE=13
+val SCE_SCRIPTOL_CLASSNAME=14
+val SCE_SCRIPTOL_PREPROCESSOR=15
+# Lexical states for SCLEX_ASM
+lex Asm=SCLEX_ASM SCE_ASM_
+val SCE_ASM_DEFAULT=0
+val SCE_ASM_COMMENT=1
+val SCE_ASM_NUMBER=2
+val SCE_ASM_STRING=3
+val SCE_ASM_OPERATOR=4
+val SCE_ASM_IDENTIFIER=5
+val SCE_ASM_CPUINSTRUCTION=6
+val SCE_ASM_MATHINSTRUCTION=7
+val SCE_ASM_REGISTER=8
+val SCE_ASM_DIRECTIVE=9
+val SCE_ASM_DIRECTIVEOPERAND=10
+val SCE_ASM_COMMENTBLOCK=11
+val SCE_ASM_CHARACTER=12
+val SCE_ASM_STRINGEOL=13
+val SCE_ASM_EXTINSTRUCTION=14
+# Lexical states for SCLEX_FORTRAN
+lex Fortran=SCLEX_FORTRAN SCE_F_
+lex F77=SCLEX_F77 SCE_F_
+val SCE_F_DEFAULT=0
+val SCE_F_COMMENT=1
+val SCE_F_NUMBER=2
+val SCE_F_STRING1=3
+val SCE_F_STRING2=4
+val SCE_F_STRINGEOL=5
+val SCE_F_OPERATOR=6
+val SCE_F_IDENTIFIER=7
+val SCE_F_WORD=8
+val SCE_F_WORD2=9
+val SCE_F_WORD3=10
+val SCE_F_PREPROCESSOR=11
+val SCE_F_OPERATOR2=12
+val SCE_F_LABEL=13
+val SCE_F_CONTINUATION=14
+# Lexical states for SCLEX_CSS
+lex CSS=SCLEX_CSS SCE_CSS_
+val SCE_CSS_DEFAULT=0
+val SCE_CSS_TAG=1
+val SCE_CSS_CLASS=2
+val SCE_CSS_PSEUDOCLASS=3
+val SCE_CSS_UNKNOWN_PSEUDOCLASS=4
+val SCE_CSS_OPERATOR=5
+val SCE_CSS_IDENTIFIER=6
+val SCE_CSS_UNKNOWN_IDENTIFIER=7
+val SCE_CSS_VALUE=8
+val SCE_CSS_COMMENT=9
+val SCE_CSS_ID=10
+val SCE_CSS_IMPORTANT=11
+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
+val SCE_CSS_IDENTIFIER3=17
+val SCE_CSS_PSEUDOELEMENT=18
+val SCE_CSS_EXTENDED_IDENTIFIER=19
+val SCE_CSS_EXTENDED_PSEUDOCLASS=20
+val SCE_CSS_EXTENDED_PSEUDOELEMENT=21
+val SCE_CSS_MEDIA=22
+# Lexical states for SCLEX_POV
+lex POV=SCLEX_POV SCE_POV_
+val SCE_POV_DEFAULT=0
+val SCE_POV_COMMENT=1
+val SCE_POV_COMMENTLINE=2
+val SCE_POV_NUMBER=3
+val SCE_POV_OPERATOR=4
+val SCE_POV_IDENTIFIER=5
+val SCE_POV_STRING=6
+val SCE_POV_STRINGEOL=7
+val SCE_POV_DIRECTIVE=8
+val SCE_POV_BADDIRECTIVE=9
+val SCE_POV_WORD2=10
+val SCE_POV_WORD3=11
+val SCE_POV_WORD4=12
+val SCE_POV_WORD5=13
+val SCE_POV_WORD6=14
+val SCE_POV_WORD7=15
+val SCE_POV_WORD8=16
+# Lexical states for SCLEX_LOUT
+lex LOUT=SCLEX_LOUT SCE_LOUT_
+val SCE_LOUT_DEFAULT=0
+val SCE_LOUT_COMMENT=1
+val SCE_LOUT_NUMBER=2
+val SCE_LOUT_WORD=3
+val SCE_LOUT_WORD2=4
+val SCE_LOUT_WORD3=5
+val SCE_LOUT_WORD4=6
+val SCE_LOUT_STRING=7
+val SCE_LOUT_OPERATOR=8
+val SCE_LOUT_IDENTIFIER=9
+val SCE_LOUT_STRINGEOL=10
+# Lexical states for SCLEX_ESCRIPT
+lex ESCRIPT=SCLEX_ESCRIPT SCE_ESCRIPT_
+val SCE_ESCRIPT_DEFAULT=0
+val SCE_ESCRIPT_COMMENT=1
+val SCE_ESCRIPT_COMMENTLINE=2
+val SCE_ESCRIPT_COMMENTDOC=3
+val SCE_ESCRIPT_NUMBER=4
+val SCE_ESCRIPT_WORD=5
+val SCE_ESCRIPT_STRING=6
+val SCE_ESCRIPT_OPERATOR=7
+val SCE_ESCRIPT_IDENTIFIER=8
+val SCE_ESCRIPT_BRACE=9
+val SCE_ESCRIPT_WORD2=10
+val SCE_ESCRIPT_WORD3=11
+# Lexical states for SCLEX_PS
+lex PS=SCLEX_PS SCE_PS_
+val SCE_PS_DEFAULT=0
+val SCE_PS_COMMENT=1
+val SCE_PS_DSC_COMMENT=2
+val SCE_PS_DSC_VALUE=3
+val SCE_PS_NUMBER=4
+val SCE_PS_NAME=5
+val SCE_PS_KEYWORD=6
+val SCE_PS_LITERAL=7
+val SCE_PS_IMMEVAL=8
+val SCE_PS_PAREN_ARRAY=9
+val SCE_PS_PAREN_DICT=10
+val SCE_PS_PAREN_PROC=11
+val SCE_PS_TEXT=12
+val SCE_PS_HEXSTRING=13
+val SCE_PS_BASE85STRING=14
+val SCE_PS_BADSTRINGCHAR=15
+# Lexical states for SCLEX_NSIS
+lex NSIS=SCLEX_NSIS SCE_NSIS_
+val SCE_NSIS_DEFAULT=0
+val SCE_NSIS_COMMENT=1
+val SCE_NSIS_STRINGDQ=2
+val SCE_NSIS_STRINGLQ=3
+val SCE_NSIS_STRINGRQ=4
+val SCE_NSIS_FUNCTION=5
+val SCE_NSIS_VARIABLE=6
+val SCE_NSIS_LABEL=7
+val SCE_NSIS_USERDEFINED=8
+val SCE_NSIS_SECTIONDEF=9
+val SCE_NSIS_SUBSECTIONDEF=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
+val SCE_MMIXAL_COMMENT=1
+val SCE_MMIXAL_LABEL=2
+val SCE_MMIXAL_OPCODE=3
+val SCE_MMIXAL_OPCODE_PRE=4
+val SCE_MMIXAL_OPCODE_VALID=5
+val SCE_MMIXAL_OPCODE_UNKNOWN=6
+val SCE_MMIXAL_OPCODE_POST=7
+val SCE_MMIXAL_OPERANDS=8
+val SCE_MMIXAL_NUMBER=9
+val SCE_MMIXAL_REF=10
+val SCE_MMIXAL_CHAR=11
+val SCE_MMIXAL_STRING=12
+val SCE_MMIXAL_REGISTER=13
+val SCE_MMIXAL_HEX=14
+val SCE_MMIXAL_OPERATOR=15
+val SCE_MMIXAL_SYMBOL=16
+val SCE_MMIXAL_INCLUDE=17
+# Lexical states for SCLEX_CLW
+lex Clarion=SCLEX_CLW SCE_CLW_
+val SCE_CLW_DEFAULT=0
+val SCE_CLW_LABEL=1
+val SCE_CLW_COMMENT=2
+val SCE_CLW_STRING=3
+val SCE_CLW_USER_IDENTIFIER=4
+val SCE_CLW_INTEGER_CONSTANT=5
+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_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
+val SCE_LOT_HEADER=1
+val SCE_LOT_BREAK=2
+val SCE_LOT_SET=3
+val SCE_LOT_PASS=4
+val SCE_LOT_FAIL=5
+val SCE_LOT_ABORT=6
+# Lexical states for SCLEX_YAML
+lex YAML=SCLEX_YAML SCE_YAML_
+val SCE_YAML_DEFAULT=0
+val SCE_YAML_COMMENT=1
+val SCE_YAML_IDENTIFIER=2
+val SCE_YAML_KEYWORD=3
+val SCE_YAML_NUMBER=4
+val SCE_YAML_REFERENCE=5
+val SCE_YAML_DOCUMENT=6
+val SCE_YAML_TEXT=7
+val SCE_YAML_ERROR=8
+val SCE_YAML_OPERATOR=9
+# Lexical states for SCLEX_TEX
+lex TeX=SCLEX_TEX SCE_TEX_
+val SCE_TEX_DEFAULT=0
+val SCE_TEX_SPECIAL=1
+val SCE_TEX_GROUP=2
+val SCE_TEX_SYMBOL=3
+val SCE_TEX_COMMAND=4
+val SCE_TEX_TEXT=5
+lex Metapost=SCLEX_METAPOST SCE_METAPOST_
+val SCE_METAPOST_DEFAULT=0
+val SCE_METAPOST_SPECIAL=1
+val SCE_METAPOST_GROUP=2
+val SCE_METAPOST_SYMBOL=3
+val SCE_METAPOST_COMMAND=4
+val SCE_METAPOST_TEXT=5
+val SCE_METAPOST_EXTRA=6
+# Lexical states for SCLEX_ERLANG
+lex Erlang=SCLEX_ERLANG SCE_ERLANG_
+val SCE_ERLANG_DEFAULT=0
+val SCE_ERLANG_COMMENT=1
+val SCE_ERLANG_VARIABLE=2
+val SCE_ERLANG_NUMBER=3
+val SCE_ERLANG_KEYWORD=4
+val SCE_ERLANG_STRING=5
+val SCE_ERLANG_OPERATOR=6
+val SCE_ERLANG_ATOM=7
+val SCE_ERLANG_FUNCTION_NAME=8
+val SCE_ERLANG_CHARACTER=9
+val SCE_ERLANG_MACRO=10
+val SCE_ERLANG_RECORD=11
+val SCE_ERLANG_PREPROC=12
+val SCE_ERLANG_NODE_NAME=13
+val SCE_ERLANG_COMMENT_FUNCTION=14
+val SCE_ERLANG_COMMENT_MODULE=15
+val SCE_ERLANG_COMMENT_DOC=16
+val SCE_ERLANG_COMMENT_DOC_MACRO=17
+val SCE_ERLANG_ATOM_QUOTED=18
+val SCE_ERLANG_MACRO_QUOTED=19
+val SCE_ERLANG_RECORD_QUOTED=20
+val SCE_ERLANG_NODE_NAME_QUOTED=21
+val SCE_ERLANG_BIFS=22
+val SCE_ERLANG_MODULES=23
+val SCE_ERLANG_MODULES_ATT=24
+val SCE_ERLANG_UNKNOWN=31
+# Lexical states for SCLEX_OCTAVE are identical to MatLab
+lex Octave=SCLEX_OCTAVE SCE_MATLAB_
+# Lexical states for SCLEX_MSSQL
+lex MSSQL=SCLEX_MSSQL SCE_MSSQL_
+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
+# Lexical states for SCLEX_VERILOG
+lex Verilog=SCLEX_VERILOG SCE_V_
+val SCE_V_DEFAULT=0
+val SCE_V_COMMENT=1
+val SCE_V_COMMENTLINE=2
+val SCE_V_COMMENTLINEBANG=3
+val SCE_V_NUMBER=4
+val SCE_V_WORD=5
+val SCE_V_STRING=6
+val SCE_V_WORD2=7
+val SCE_V_WORD3=8
+val SCE_V_PREPROCESSOR=9
+val SCE_V_OPERATOR=10
+val SCE_V_IDENTIFIER=11
+val SCE_V_STRINGEOL=12
+val SCE_V_USER=19
+# Lexical states for SCLEX_KIX
+lex Kix=SCLEX_KIX SCE_KIX_
+val SCE_KIX_DEFAULT=0
+val SCE_KIX_COMMENT=1
+val SCE_KIX_STRING1=2
+val SCE_KIX_STRING2=3
+val SCE_KIX_NUMBER=4
+val SCE_KIX_VAR=5
+val SCE_KIX_MACRO=6
+val SCE_KIX_KEYWORD=7
+val SCE_KIX_FUNCTIONS=8
+val SCE_KIX_OPERATOR=9
+val SCE_KIX_IDENTIFIER=31
+# Lexical states for SCLEX_GUI4CLI
+val SCE_GC_DEFAULT=0
+val SCE_GC_COMMENTLINE=1
+val SCE_GC_COMMENTBLOCK=2
+val SCE_GC_GLOBAL=3
+val SCE_GC_EVENT=4
+val SCE_GC_ATTRIBUTE=5
+val SCE_GC_CONTROL=6
+val SCE_GC_COMMAND=7
+val SCE_GC_STRING=8
+val SCE_GC_OPERATOR=9
+# Lexical states for SCLEX_SPECMAN
+lex Specman=SCLEX_SPECMAN SCE_SN_
+val SCE_SN_DEFAULT=0
+val SCE_SN_CODE=1
+val SCE_SN_COMMENTLINE=2
+val SCE_SN_COMMENTLINEBANG=3
+val SCE_SN_NUMBER=4
+val SCE_SN_WORD=5
+val SCE_SN_STRING=6
+val SCE_SN_WORD2=7
+val SCE_SN_WORD3=8
+val SCE_SN_PREPROCESSOR=9
+val SCE_SN_OPERATOR=10
+val SCE_SN_IDENTIFIER=11
+val SCE_SN_STRINGEOL=12
+val SCE_SN_REGEXTAG=13
+val SCE_SN_SIGNAL=14
+val SCE_SN_USER=19
+# Lexical states for SCLEX_AU3
+lex Au3=SCLEX_AU3 SCE_AU3_
+val SCE_AU3_DEFAULT=0
+val SCE_AU3_COMMENT=1
+val SCE_AU3_COMMENTBLOCK=2
+val SCE_AU3_NUMBER=3
+val SCE_AU3_FUNCTION=4
+val SCE_AU3_KEYWORD=5
+val SCE_AU3_MACRO=6
+val SCE_AU3_STRING=7
+val SCE_AU3_OPERATOR=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
+val SCE_AU3_UDF=15
+# Lexical states for SCLEX_APDL
+lex APDL=SCLEX_APDL SCE_APDL_
+val SCE_APDL_DEFAULT=0
+val SCE_APDL_COMMENT=1
+val SCE_APDL_COMMENTBLOCK=2
+val SCE_APDL_NUMBER=3
+val SCE_APDL_STRING=4
+val SCE_APDL_OPERATOR=5
+val SCE_APDL_WORD=6
+val SCE_APDL_PROCESSOR=7
+val SCE_APDL_COMMAND=8
+val SCE_APDL_SLASHCOMMAND=9
+val SCE_APDL_STARCOMMAND=10
+val SCE_APDL_ARGUMENT=11
+val SCE_APDL_FUNCTION=12
+# Lexical states for SCLEX_BASH
+lex Bash=SCLEX_BASH SCE_SH_
+val SCE_SH_DEFAULT=0
+val SCE_SH_ERROR=1
+val SCE_SH_COMMENTLINE=2
+val SCE_SH_NUMBER=3
+val SCE_SH_WORD=4
+val SCE_SH_STRING=5
+val SCE_SH_CHARACTER=6
+val SCE_SH_OPERATOR=7
+val SCE_SH_IDENTIFIER=8
+val SCE_SH_SCALAR=9
+val SCE_SH_PARAM=10
+val SCE_SH_BACKTICKS=11
+val SCE_SH_HERE_DELIM=12
+val SCE_SH_HERE_Q=13
+# Lexical states for SCLEX_ASN1
+lex Asn1=SCLEX_ASN1 SCE_ASN1_
+val SCE_ASN1_DEFAULT=0
+val SCE_ASN1_COMMENT=1
+val SCE_ASN1_IDENTIFIER=2
+val SCE_ASN1_STRING=3
+val SCE_ASN1_OID=4
+val SCE_ASN1_SCALAR=5
+val SCE_ASN1_KEYWORD=6
+val SCE_ASN1_ATTRIBUTE=7
+val SCE_ASN1_DESCRIPTOR=8
+val SCE_ASN1_TYPE=9
+val SCE_ASN1_OPERATOR=10
+# Lexical states for SCLEX_VHDL
+lex VHDL=SCLEX_VHDL SCE_VHDL_
+val SCE_VHDL_DEFAULT=0
+val SCE_VHDL_COMMENT=1
+val SCE_VHDL_COMMENTLINEBANG=2
+val SCE_VHDL_NUMBER=3
+val SCE_VHDL_STRING=4
+val SCE_VHDL_OPERATOR=5
+val SCE_VHDL_IDENTIFIER=6
+val SCE_VHDL_STRINGEOL=7
+val SCE_VHDL_KEYWORD=8
+val SCE_VHDL_STDOPERATOR=9
+val SCE_VHDL_ATTRIBUTE=10
+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_WHITE=10
+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
+val SCE_T3_BRACE=20
+# 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_FS_
+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_WORDOPERATOR=19
+val SCE_FS_DISABLEDCODE=20
+val SCE_FS_DEFAULT_C=21
+val SCE_FS_COMMENTDOC_C=22
+val SCE_FS_COMMENTLINEDOC_C=23
+val SCE_FS_KEYWORD_C=24
+val SCE_FS_KEYWORD2_C=25
+val SCE_FS_NUMBER_C=26
+val SCE_FS_STRING_C=27
+val SCE_FS_PREPROCESSOR_C=28
+val SCE_FS_OPERATOR_C=29
+val SCE_FS_IDENTIFIER_C=30
+val SCE_FS_STRINGEOL_C=31
+# 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
+# Lexical states for SCLEX_INNOSETUP
+lex Inno=SCLEX_INNOSETUP SCE_INNO_
+val SCE_INNO_DEFAULT=0
+val SCE_INNO_COMMENT=1
+val SCE_INNO_KEYWORD=2
+val SCE_INNO_PARAMETER=3
+val SCE_INNO_SECTION=4
+val SCE_INNO_PREPROC=5
+val SCE_INNO_INLINE_EXPANSION=6
+val SCE_INNO_COMMENT_PASCAL=7
+val SCE_INNO_KEYWORD_PASCAL=8
+val SCE_INNO_KEYWORD_USER=9
+val SCE_INNO_STRING_DOUBLE=10
+val SCE_INNO_STRING_SINGLE=11
+val SCE_INNO_IDENTIFIER=12
+# Lexical states for SCLEX_OPAL
+lex Opal=SCLEX_OPAL SCE_OPAL_
+val SCE_OPAL_SPACE=0
+val SCE_OPAL_COMMENT_BLOCK=1
+val SCE_OPAL_COMMENT_LINE=2
+val SCE_OPAL_INTEGER=3
+val SCE_OPAL_KEYWORD=4
+val SCE_OPAL_SORT=5
+val SCE_OPAL_STRING=6
+val SCE_OPAL_PAR=7
+val SCE_OPAL_BOOL_CONST=8
+val SCE_OPAL_DEFAULT=32
+# Lexical states for SCLEX_SPICE
+lex Spice=SCLEX_SPICE SCE_SPICE_
+val SCE_SPICE_DEFAULT=0
+val SCE_SPICE_IDENTIFIER=1
+val SCE_SPICE_KEYWORD=2
+val SCE_SPICE_KEYWORD2=3
+val SCE_SPICE_KEYWORD3=4
+val SCE_SPICE_NUMBER=5
+val SCE_SPICE_DELIMITER=6
+val SCE_SPICE_VALUE=7
+val SCE_SPICE_COMMENTLINE=8
+# Lexical states for SCLEX_CMAKE
+lex CMAKE=SCLEX_CMAKE SCE_CMAKE_
+val SCE_CMAKE_DEFAULT=0
+val SCE_CMAKE_COMMENT=1
+val SCE_CMAKE_STRINGDQ=2
+val SCE_CMAKE_STRINGLQ=3
+val SCE_CMAKE_STRINGRQ=4
+val SCE_CMAKE_COMMANDS=5
+val SCE_CMAKE_PARAMETERS=6
+val SCE_CMAKE_VARIABLE=7
+val SCE_CMAKE_USERDEFINED=8
+val SCE_CMAKE_WHILEDEF=9
+val SCE_CMAKE_FOREACHDEF=10
+val SCE_CMAKE_IFDEFINEDEF=11
+val SCE_CMAKE_MACRODEF=12
+val SCE_CMAKE_STRINGVAR=13
+val SCE_CMAKE_NUMBER=14
+# Lexical states for SCLEX_GAP
+lex Gap=SCLEX_GAP SCE_GAP_
+val SCE_GAP_DEFAULT=0
+val SCE_GAP_IDENTIFIER=1
+val SCE_GAP_KEYWORD=2
+val SCE_GAP_KEYWORD2=3
+val SCE_GAP_KEYWORD3=4
+val SCE_GAP_KEYWORD4=5
+val SCE_GAP_STRING=6
+val SCE_GAP_CHAR=7
+val SCE_GAP_OPERATOR=8
+val SCE_GAP_COMMENT=9
+val SCE_GAP_NUMBER=10
+val SCE_GAP_STRINGEOL=11
+# Lexical state for SCLEX_PLM
+lex PLM=SCLEX_PLM SCE_PLM_
+val SCE_PLM_DEFAULT=0
+val SCE_PLM_COMMENT=1
+val SCE_PLM_STRING=2
+val SCE_PLM_NUMBER=3
+val SCE_PLM_IDENTIFIER=4
+val SCE_PLM_OPERATOR=5
+val SCE_PLM_CONTROL=6
+val SCE_PLM_KEYWORD=7
+# Lexical state for SCLEX_PROGRESS
+lex Progress=SCLEX_PROGRESS SCE_4GL_
+val SCE_4GL_DEFAULT=0
+val SCE_4GL_NUMBER=1
+val SCE_4GL_WORD=2
+val SCE_4GL_STRING=3
+val SCE_4GL_CHARACTER=4
+val SCE_4GL_PREPROCESSOR=5
+val SCE_4GL_OPERATOR=6
+val SCE_4GL_IDENTIFIER=7
+val SCE_4GL_BLOCK=8
+val SCE_4GL_END=9
+val SCE_4GL_COMMENT1=10
+val SCE_4GL_COMMENT2=11
+val SCE_4GL_COMMENT3=12
+val SCE_4GL_COMMENT4=13
+val SCE_4GL_COMMENT5=14
+val SCE_4GL_COMMENT6=15
+val SCE_4GL_DEFAULT_=16
+val SCE_4GL_NUMBER_=17
+val SCE_4GL_WORD_=18
+val SCE_4GL_STRING_=19
+val SCE_4GL_CHARACTER_=20
+val SCE_4GL_PREPROCESSOR_=21
+val SCE_4GL_OPERATOR_=22
+val SCE_4GL_IDENTIFIER_=23
+val SCE_4GL_BLOCK_=24
+val SCE_4GL_END_=25
+val SCE_4GL_COMMENT1_=26
+val SCE_4GL_COMMENT2_=27
+val SCE_4GL_COMMENT3_=28
+val SCE_4GL_COMMENT4_=29
+val SCE_4GL_COMMENT5_=30
+val SCE_4GL_COMMENT6_=31
+# Lexical states for SCLEX_ABAQUS
+lex ABAQUS=SCLEX_ABAQUS SCE_ABAQUS_
+val SCE_ABAQUS_DEFAULT=0
+val SCE_ABAQUS_COMMENT=1
+val SCE_ABAQUS_COMMENTBLOCK=2
+val SCE_ABAQUS_NUMBER=3
+val SCE_ABAQUS_STRING=4
+val SCE_ABAQUS_OPERATOR=5
+val SCE_ABAQUS_WORD=6
+val SCE_ABAQUS_PROCESSOR=7
+val SCE_ABAQUS_COMMAND=8
+val SCE_ABAQUS_SLASHCOMMAND=9
+val SCE_ABAQUS_STARCOMMAND=10
+val SCE_ABAQUS_ARGUMENT=11
+val SCE_ABAQUS_FUNCTION=12
+# Lexical states for SCLEX_ASYMPTOTE
+lex Asymptote=SCLEX_ASYMPTOTE SCE_ASY_
+val SCE_ASY_DEFAULT=0
+val SCE_ASY_COMMENT=1
+val SCE_ASY_COMMENTLINE=2
+val SCE_ASY_NUMBER=3
+val SCE_ASY_WORD=4
+val SCE_ASY_STRING=5
+val SCE_ASY_CHARACTER=6
+val SCE_ASY_OPERATOR=7
+val SCE_ASY_IDENTIFIER=8
+val SCE_ASY_STRINGEOL=9
+val SCE_ASY_COMMENTLINEDOC=10
+val SCE_ASY_WORD2=11
+# Lexical states for SCLEX_R
+lex R=SCLEX_R SCE_R_
+val SCE_R_DEFAULT=0
+val SCE_R_COMMENT=1
+val SCE_R_KWORD=2
+val SCE_R_BASEKWORD=3
+val SCE_R_OTHERKWORD=4
+val SCE_R_NUMBER=5
+val SCE_R_STRING=6
+val SCE_R_STRING2=7
+val SCE_R_OPERATOR=8
+val SCE_R_IDENTIFIER=9
+val SCE_R_INFIX=10
+val SCE_R_INFIXEOL=11
+# Lexical state for SCLEX_MAGIKSF
+lex MagikSF=SCLEX_MAGIKSF SCE_MAGIK_
+val SCE_MAGIK_DEFAULT=0
+val SCE_MAGIK_COMMENT=1
+val SCE_MAGIK_HYPER_COMMENT=16
+val SCE_MAGIK_STRING=2
+val SCE_MAGIK_CHARACTER=3
+val SCE_MAGIK_NUMBER=4
+val SCE_MAGIK_IDENTIFIER=5
+val SCE_MAGIK_OPERATOR=6
+val SCE_MAGIK_FLOW=7
+val SCE_MAGIK_CONTAINER=8
+val SCE_MAGIK_BRACKET_BLOCK=9
+val SCE_MAGIK_BRACE_BLOCK=10
+val SCE_MAGIK_SQBRACKET_BLOCK=11
+val SCE_MAGIK_UNKNOWN_KEYWORD=12
+val SCE_MAGIK_KEYWORD=13
+val SCE_MAGIK_PRAGMA=14
+val SCE_MAGIK_SYMBOL=15
+# Lexical state for SCLEX_POWERSHELL
+lex PowerShell=SCLEX_POWERSHELL SCE_POWERSHELL_
+val SCE_POWERSHELL_DEFAULT=0
+val SCE_POWERSHELL_COMMENT=1
+val SCE_POWERSHELL_STRING=2
+val SCE_POWERSHELL_CHARACTER=3
+val SCE_POWERSHELL_NUMBER=4
+val SCE_POWERSHELL_VARIABLE=5
+val SCE_POWERSHELL_OPERATOR=6
+val SCE_POWERSHELL_IDENTIFIER=7
+val SCE_POWERSHELL_KEYWORD=8
+val SCE_POWERSHELL_CMDLET=9
+val SCE_POWERSHELL_ALIAS=10
+# Lexical state for SCLEX_MYSQL
+lex MySQL=SCLEX_MYSQL SCE_MYSQL_
+val SCE_MYSQL_DEFAULT=0
+val SCE_MYSQL_COMMENT=1
+val SCE_MYSQL_COMMENTLINE=2
+val SCE_MYSQL_VARIABLE=3
+val SCE_MYSQL_SYSTEMVARIABLE=4
+val SCE_MYSQL_KNOWNSYSTEMVARIABLE=5
+val SCE_MYSQL_NUMBER=6
+val SCE_MYSQL_MAJORKEYWORD=7
+val SCE_MYSQL_KEYWORD=8
+val SCE_MYSQL_DATABASEOBJECT=9
+val SCE_MYSQL_PROCEDUREKEYWORD=10
+val SCE_MYSQL_STRING=11
+val SCE_MYSQL_SQSTRING=12
+val SCE_MYSQL_DQSTRING=13
+val SCE_MYSQL_OPERATOR=14
+val SCE_MYSQL_FUNCTION=15
+val SCE_MYSQL_IDENTIFIER=16
+val SCE_MYSQL_QUOTEDIDENTIFIER=17
+val SCE_MYSQL_USER1=18
+val SCE_MYSQL_USER2=19
+val SCE_MYSQL_USER3=20
+val SCE_MYSQL_HIDDENCOMMAND=21
+# Lexical state for SCLEX_PO
+lex Po=SCLEX_PO SCE_PO_
+val SCE_PO_DEFAULT=0
+val SCE_PO_COMMENT=1
+val SCE_PO_MSGID=2
+val SCE_PO_MSGID_TEXT=3
+val SCE_PO_MSGSTR=4
+val SCE_PO_MSGSTR_TEXT=5
+val SCE_PO_MSGCTXT=6
+val SCE_PO_MSGCTXT_TEXT=7
+val SCE_PO_FUZZY=8
+# Lexical states for SCLEX_PASCAL
+lex Pascal=SCLEX_PASCAL SCE_PAS_
+val SCE_PAS_DEFAULT=0
+val SCE_PAS_IDENTIFIER=1
+val SCE_PAS_COMMENT=2
+val SCE_PAS_COMMENT2=3
+val SCE_PAS_COMMENTLINE=4
+val SCE_PAS_PREPROCESSOR=5
+val SCE_PAS_PREPROCESSOR2=6
+val SCE_PAS_NUMBER=7
+val SCE_PAS_HEXNUMBER=8
+val SCE_PAS_WORD=9
+val SCE_PAS_STRING=10
+val SCE_PAS_STRINGEOL=11
+val SCE_PAS_CHARACTER=12
+val SCE_PAS_OPERATOR=13
+val SCE_PAS_ASM=14
+# Lexical state for SCLEX_SORCUS
+lex SORCUS=SCLEX_SORCUS SCE_SORCUS_
+val SCE_SORCUS_DEFAULT=0
+val SCE_SORCUS_COMMAND=1
+val SCE_SORCUS_PARAMETER=2
+val SCE_SORCUS_COMMENTLINE=3
+val SCE_SORCUS_STRING=4
+val SCE_SORCUS_STRINGEOL=5
+val SCE_SORCUS_IDENTIFIER=6
+val SCE_SORCUS_OPERATOR=7
+val SCE_SORCUS_NUMBER=8
+val SCE_SORCUS_CONSTANT=9
+# Lexical state for SCLEX_POWERPRO
+lex PowerPro=SCLEX_POWERPRO SCE_POWERPRO_
+val SCE_POWERPRO_DEFAULT=0
+val SCE_POWERPRO_COMMENTBLOCK=1
+val SCE_POWERPRO_COMMENTLINE=2
+val SCE_POWERPRO_NUMBER=3
+val SCE_POWERPRO_WORD=4
+val SCE_POWERPRO_WORD2=5
+val SCE_POWERPRO_WORD3=6
+val SCE_POWERPRO_WORD4=7
+val SCE_POWERPRO_DOUBLEQUOTEDSTRING=8
+val SCE_POWERPRO_SINGLEQUOTEDSTRING=9
+val SCE_POWERPRO_LINECONTINUE=10
+val SCE_POWERPRO_OPERATOR=11
+val SCE_POWERPRO_IDENTIFIER=12
+val SCE_POWERPRO_STRINGEOL=13
+val SCE_POWERPRO_VERBATIM=14
+val SCE_POWERPRO_ALTQUOTE=15
+val SCE_POWERPRO_FUNCTION=16
+# Lexical states for SCLEX_SML
+lex SML=SCLEX_SML SCE_SML_
+val SCE_SML_DEFAULT=0
+val SCE_SML_IDENTIFIER=1
+val SCE_SML_TAGNAME=2
+val SCE_SML_KEYWORD=3
+val SCE_SML_KEYWORD2=4
+val SCE_SML_KEYWORD3=5
+val SCE_SML_LINENUM=6
+val SCE_SML_OPERATOR=7
+val SCE_SML_NUMBER=8
+val SCE_SML_CHAR=9
+val SCE_SML_STRING=11
+val SCE_SML_COMMENT=12
+val SCE_SML_COMMENT1=13
+val SCE_SML_COMMENT2=14
+val SCE_SML_COMMENT3=15
+# Lexical state for SCLEX_MARKDOWN
+lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_
+val SCE_MARKDOWN_DEFAULT=0
+val SCE_MARKDOWN_LINE_BEGIN=1
+val SCE_MARKDOWN_STRONG1=2
+val SCE_MARKDOWN_STRONG2=3
+val SCE_MARKDOWN_EM1=4
+val SCE_MARKDOWN_EM2=5
+val SCE_MARKDOWN_HEADER1=6
+val SCE_MARKDOWN_HEADER2=7
+val SCE_MARKDOWN_HEADER3=8
+val SCE_MARKDOWN_HEADER4=9
+val SCE_MARKDOWN_HEADER5=10
+val SCE_MARKDOWN_HEADER6=11
+val SCE_MARKDOWN_PRECHAR=12
+val SCE_MARKDOWN_ULIST_ITEM=13
+val SCE_MARKDOWN_OLIST_ITEM=14
+val SCE_MARKDOWN_BLOCKQUOTE=15
+val SCE_MARKDOWN_STRIKEOUT=16
+val SCE_MARKDOWN_HRULE=17
+val SCE_MARKDOWN_LINK=18
+val SCE_MARKDOWN_CODE=19
+val SCE_MARKDOWN_CODE2=20
+val SCE_MARKDOWN_CODEBK=21
+
+# Events
+
+evt void StyleNeeded=2000(int position)
+evt void CharAdded=2001(int ch)
+evt void SavePointReached=2002(void)
+evt void SavePointLeft=2003(void)
+evt void ModifyAttemptRO=2004(void)
+# GTK+ Specific to work around focus and accelerator problems:
+evt void Key=2005(int ch, int modifiers)
+evt void DoubleClick=2006(void)
+evt void UpdateUI=2007(void)
+evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev)
+evt void MacroRecord=2009(int message, int wParam, int lParam)
+evt void MarginClick=2010(int modifiers, int position, int margin)
+evt void NeedShown=2011(int position, int length)
+evt void Painted=2013(void)
+evt void UserListSelection=2014(int listType, string text)
+evt void URIDropped=2015(string text)
+evt void DwellStart=2016(int position)
+evt void DwellEnd=2017(int position)
+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)
+evt void IndicatorClick=2023(int modifiers, int position)
+evt void IndicatorRelease=2024(int modifiers, int position)
+evt void AutoCCancelled=2025(void)
+evt void AutoCCharDeleted=2026(void)
diff --git a/scintilla/include/ScintillaWidget.h b/scintilla/include/ScintillaWidget.h
new file mode 100644
index 0000000..44cff60
--- /dev/null
+++ b/scintilla/include/ScintillaWidget.h
@@ -0,0 +1,51 @@
+/* Scintilla source code edit control */
+/** @file ScintillaWidget.h
+ ** Definition of Scintilla widget for GTK+.
+ ** Only needed by GTK+ code but is harmless on other platforms.
+ **/
+/* Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+ * The License.txt file describes the conditions under which this software may be distributed. */
+
+#ifndef SCINTILLAWIDGET_H
+#define SCINTILLAWIDGET_H
+
+#if defined(GTK)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SCINTILLA(obj) GTK_CHECK_CAST (obj, scintilla_get_type (), ScintillaObject)
+#define SCINTILLA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass)
+#define IS_SCINTILLA(obj) GTK_CHECK_TYPE (obj, scintilla_get_type ())
+
+typedef struct _ScintillaObject ScintillaObject;
+typedef struct _ScintillaClass ScintillaClass;
+
+struct _ScintillaObject {
+ GtkContainer cont;
+ void *pscin;
+};
+
+struct _ScintillaClass {
+ GtkContainerClass parent_class;
+
+ void (* command) (ScintillaObject *ttt);
+ void (* notify) (ScintillaObject *ttt);
+};
+
+GType scintilla_get_type (void);
+GtkWidget* scintilla_new (void);
+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);
+
+#define SCINTILLA_NOTIFY "sci-notify"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif
diff --git a/scintilla/include/WindowAccessor.h b/scintilla/include/WindowAccessor.h
new file mode 100644
index 0000000..ed67e29
--- /dev/null
+++ b/scintilla/include/WindowAccessor.h
@@ -0,0 +1,67 @@
+// Scintilla source code edit control
+/** @file WindowAccessor.h
+ ** Implementation of BufferAccess and StylingAccess on a Scintilla
+ ** rapid easy access to contents of a Scintilla.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+
+class WindowAccessor : public Accessor {
+ // Private so WindowAccessor objects can not be copied
+ WindowAccessor(const WindowAccessor &source) : Accessor(), props(source.props) {}
+ WindowAccessor &operator=(const WindowAccessor &) { return *this; }
+protected:
+ WindowID id;
+ PropertyGet &props;
+ int lenDoc;
+
+ char styleBuf[bufferSize];
+ int validLen;
+ char chFlags;
+ char chWhile;
+ unsigned int startSeg;
+
+ bool InternalIsLeadByte(char ch);
+ void Fill(int position);
+public:
+ WindowAccessor(WindowID id_, PropertyGet &props_) :
+ Accessor(), id(id_), props(props_),
+ lenDoc(-1), validLen(0), chFlags(0), chWhile(0) {
+ }
+ ~WindowAccessor();
+ bool Match(int pos, const char *s);
+ char StyleAt(int position);
+ int GetLine(int position);
+ int LineStart(int line);
+ int LevelAt(int line);
+ int Length();
+ void Flush();
+ int GetLineState(int line);
+ int SetLineState(int line, int state);
+ int GetPropertyInt(const char *key, int defaultValue=0) {
+ return props.GetInt(key, defaultValue);
+ }
+ char *GetProperties() {
+ return props.ToString();
+ }
+
+ void StartAt(unsigned int start, char chMask=31);
+ void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }
+ unsigned int GetStartSegment() { return startSeg; }
+ void StartSegment(unsigned int pos);
+ void ColourTo(unsigned int pos, int chAttr);
+ void SetLevel(int line, int level);
+ int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
+ void IndicatorFill(int start, int end, int indicator, int value);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
diff --git a/scintilla/macosx/ExtInput.cxx b/scintilla/macosx/ExtInput.cxx
new file mode 100644
index 0000000..a26b487
--- /dev/null
+++ b/scintilla/macosx/ExtInput.cxx
@@ -0,0 +1,608 @@
+/*******************************************************************************
+
+Copyright (c) 2007 Adobe Systems Incorporated
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+********************************************************************************/
+
+#include "ScintillaMacOSX.h"
+#include "ExtInput.h"
+
+using namespace Scintilla;
+
+// uncomment this for a log to /dev/console
+// #define LOG_TSM 1
+
+#if LOG_TSM
+FILE* logFile = NULL;
+#endif
+
+static EventHandlerUPP tsmHandler;
+
+static EventTypeSpec tsmSpecs[] = {
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
+// { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ { kEventClassTextInput, kEventTextInputOffsetToPos },
+ { kEventClassTextInput, kEventTextInputPosToOffset },
+ { kEventClassTextInput, kEventTextInputGetSelectedText }
+};
+
+#define kScintillaTSM 'ScTs'
+
+// The following structure is attached to the HIViewRef as property kScintillaTSM
+
+struct TSMData
+{
+ HIViewRef view; // this view
+ TSMDocumentID docid; // the TSM document ID
+ EventHandlerRef handler; // the event handler
+ ScintillaMacOSX* scintilla; // the Scintilla pointer
+ int styleMask; // the document style mask
+ int indicStyle [3]; // indicator styles save
+ int indicColor [3]; // indicator colors save
+ int selStart; // starting position of selection (Scintilla offset)
+ int selLength; // UTF-8 number of characters
+ int selCur; // current position (Scintilla offset)
+ int inhibitRecursion; // true to stop recursion
+ bool active; // true if this is active
+};
+
+static const int numSpecs = 5;
+
+
+// Fetch a range of text as UTF-16; delete the buffer after use
+
+static char* getTextPortion (TSMData* data, UInt32 start, UInt32 size)
+{
+ Scintilla::TextRange range;
+ range.chrg.cpMin = start;
+ range.chrg.cpMax = start + size;
+ range.lpstrText = new char [size + 1];
+ range.lpstrText [size] = 0;
+ data->scintilla->WndProc (SCI_GETTEXTRANGE, 0, (uptr_t) &range);
+ return range.lpstrText;
+}
+
+static pascal OSStatus doHandleTSM (EventHandlerCallRef, EventRef inEvent, void* userData);
+
+void ExtInput::attach (HIViewRef viewRef)
+{
+ if (NULL == tsmHandler)
+ tsmHandler = NewEventHandlerUPP (doHandleTSM);
+ ::UseInputWindow (NULL, FALSE);
+
+#ifdef LOG_TSM
+ if (NULL == logFile)
+ logFile = fopen ("/dev/console", "a");
+#endif
+
+ // create and attach the TSM data
+ TSMData* data = new TSMData;
+
+ data->view = viewRef;
+ data->active = false;
+ data->inhibitRecursion = 0;
+
+ ::GetControlProperty (viewRef, scintillaMacOSType, 0, sizeof( data->scintilla ), NULL, &data->scintilla);
+
+ if (NULL != data->scintilla)
+ {
+ // create the TSM document ref
+ InterfaceTypeList interfaceTypes;
+ interfaceTypes[0] = kUnicodeDocumentInterfaceType;
+ ::NewTSMDocument (1, interfaceTypes, &data->docid, (long) viewRef);
+ // install my event handler
+ ::InstallControlEventHandler (viewRef, tsmHandler, numSpecs, tsmSpecs, data, &data->handler);
+
+ ::SetControlProperty (viewRef, kScintillaTSM, 0, sizeof (data), &data);
+ }
+ else
+ delete data;
+}
+
+static TSMData* getTSMData (HIViewRef viewRef)
+{
+ TSMData* data = NULL;
+ UInt32 n;
+ ::GetControlProperty (viewRef, kScintillaTSM, 0, sizeof (data), &n, (UInt32*) &data);
+ return data;
+}
+
+void ExtInput::detach (HIViewRef viewRef)
+{
+ TSMData* data = getTSMData (viewRef);
+ if (NULL != data)
+ {
+ ::DeleteTSMDocument (data->docid);
+ ::RemoveEventHandler (data->handler);
+ delete data;
+ }
+}
+
+void ExtInput::activate (HIViewRef viewRef, bool on)
+{
+ TSMData* data = getTSMData (viewRef);
+ if (NULL == data)
+ return;
+
+ if (on)
+ {
+ ::ActivateTSMDocument (data->docid);
+ HIRect bounds;
+ ::HIViewGetBounds (viewRef, &bounds);
+ ::HIViewConvertRect (&bounds, viewRef, NULL);
+ RgnHandle hRgn = ::NewRgn();
+ ::SetRectRgn (hRgn, (short) bounds.origin.x, (short) bounds.origin.y,
+ (short) (bounds.origin.x + bounds.size.width),
+ (short) (bounds.origin.y + bounds.size.height));
+#if LOG_TSM
+ fprintf (logFile, "TSMSetInlineInputRegion (%08lX, %ld:%ld-%ld:%ld)\n",
+ (long) data->docid, (long) bounds.origin.x, (long) bounds.origin.y,
+ (long) (bounds.origin.x + bounds.size.width), (long) (bounds.origin.y + bounds.size.height));
+ fflush (logFile);
+#endif
+ ::TSMSetInlineInputRegion (data->docid, HIViewGetWindow (data->view), hRgn);
+ ::DisposeRgn (hRgn);
+ ::UseInputWindow (NULL, FALSE);
+ }
+ else
+ {
+#if LOG_TSM
+ fprintf (logFile, "DeactivateTSMDocument (%08lX)\n", (long) data->docid);
+ fflush (logFile);
+#endif
+ ::DeactivateTSMDocument (data->docid);
+ }
+}
+
+static void startInput (TSMData* data, bool delSelection = true)
+{
+ if (!data->active && 0 == data->inhibitRecursion)
+ {
+ data->active = true;
+
+ // Delete any selection
+ if( delSelection )
+ data->scintilla->WndProc (SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(""));
+
+ // need all style bits because we do indicators
+ data->styleMask = data->scintilla->WndProc (SCI_GETSTYLEBITS, 0, 0);
+ data->scintilla->WndProc (SCI_SETSTYLEBITS, 5, 0);
+
+ // Set the target range for successive replacements
+ data->selStart =
+ data->selCur = data->scintilla->WndProc (SCI_GETCURRENTPOS, 0, 0);
+ data->selLength = 0;
+
+ // save needed styles
+ for (int i = 0; i < 2; i++)
+ {
+ data->indicStyle [i] = data->scintilla->WndProc (SCI_INDICGETSTYLE, i, 0);
+ data->indicColor [i] = data->scintilla->WndProc (SCI_INDICGETFORE, i, 0);
+ }
+ // set styles and colors
+ data->scintilla->WndProc (SCI_INDICSETSTYLE, 0, INDIC_SQUIGGLE);
+ data->scintilla->WndProc (SCI_INDICSETFORE, 0, 0x808080);
+ data->scintilla->WndProc (SCI_INDICSETSTYLE, 1, INDIC_PLAIN); // selected converted
+ data->scintilla->WndProc (SCI_INDICSETFORE, 1, 0x808080);
+ data->scintilla->WndProc (SCI_INDICSETSTYLE, 2, INDIC_PLAIN); // selected raw
+ data->scintilla->WndProc (SCI_INDICSETFORE, 2, 0x0000FF);
+ // stop Undo
+ data->scintilla->WndProc (SCI_BEGINUNDOACTION, 0, 0);
+ }
+}
+
+static void stopInput (TSMData* data, int pos)
+{
+ if (data->active && 0 == data->inhibitRecursion)
+ {
+ // First fix the doc - this may cause more messages
+ // but do not fall into recursion
+ data->inhibitRecursion++;
+ ::FixTSMDocument (data->docid);
+ data->inhibitRecursion--;
+ data->active = false;
+
+ // Remove indicator styles
+ data->scintilla->WndProc (SCI_STARTSTYLING, data->selStart, INDICS_MASK);
+ data->scintilla->WndProc (SCI_SETSTYLING, pos - data->selStart, 0);
+ // Restore old indicator styles and colors
+ data->scintilla->WndProc (SCI_SETSTYLEBITS, data->styleMask, 0);
+ for (int i = 0; i < 2; i++)
+ {
+ data->scintilla->WndProc (SCI_INDICSETSTYLE, i, data->indicStyle [i]);
+ data->scintilla->WndProc (SCI_INDICSETFORE, i, data->indicColor [i]);
+ }
+
+ // remove selection and re-allow selections to display
+ data->scintilla->WndProc (SCI_SETSEL, pos, pos);
+ data->scintilla->WndProc (SCI_TARGETFROMSELECTION, 0, 0);
+ data->scintilla->WndProc (SCI_HIDESELECTION, 0, 0);
+
+ // move the caret behind the current area
+ data->scintilla->WndProc (SCI_SETCURRENTPOS, pos, 0);
+ // re-enable Undo
+ data->scintilla->WndProc (SCI_ENDUNDOACTION, 0, 0);
+ // re-colorize
+ int32_t startLine = data->scintilla->WndProc (SCI_LINEFROMPOSITION, data->selStart, 0);
+ int32_t startPos = data->scintilla->WndProc (SCI_POSITIONFROMLINE, startLine, 0);
+ int32_t endLine = data->scintilla->WndProc (SCI_LINEFROMPOSITION, pos, 0);
+ if (endLine == startLine)
+ endLine++;
+ int32_t endPos = data->scintilla->WndProc (SCI_POSITIONFROMLINE, endLine, 0);
+
+ data->scintilla->WndProc (SCI_COLOURISE, startPos, endPos);
+ }
+}
+
+void ExtInput::stop (HIViewRef viewRef)
+{
+ TSMData* data = getTSMData (viewRef);
+ if (NULL != data)
+ stopInput (data, data->selStart + data->selLength);
+}
+
+static char* UTF16toUTF8 (const UniChar* buf, int len, int& utf8len)
+{
+ CFStringRef str = CFStringCreateWithCharactersNoCopy (NULL, buf, (UInt32) len, kCFAllocatorNull);
+ CFRange range = { 0, len };
+ CFIndex bufLen;
+ CFStringGetBytes (str, range, kCFStringEncodingUTF8, '?', false, NULL, 0, &bufLen);
+ UInt8* utf8buf = new UInt8 [bufLen+1];
+ CFStringGetBytes (str, range, kCFStringEncodingUTF8, '?', false, utf8buf, bufLen, NULL);
+ utf8buf [bufLen] = 0;
+ CFRelease (str);
+ utf8len = (int) bufLen;
+ return (char*) utf8buf;
+}
+
+static int UCS2Length (const char* buf, int len)
+{
+ int n = 0;
+ while (len > 0)
+ {
+ int bytes = 0;
+ char ch = *buf;
+ while (ch & 0x80)
+ bytes++, ch <<= 1;
+ len -= bytes;
+ n += bytes;
+ }
+ return n;
+}
+
+static int UTF8Length (const UniChar* buf, int len)
+{
+ int n = 0;
+ while (len > 0)
+ {
+ UInt32 uch = *buf++;
+ len--;
+ if (uch >= 0xD800 && uch <= 0xDBFF && len > 0)
+ {
+ UInt32 uch2 = *buf;
+ if (uch2 >= 0xDC00 && uch2 <= 0xDFFF)
+ {
+ buf++;
+ len--;
+ uch = ((uch & 0x3FF) << 10) + (uch2 & 0x3FF);
+ }
+ }
+ n++;
+ if (uch > 0x7F)
+ n++;
+ if (uch > 0x7FF)
+ n++;
+ if (uch > 0xFFFF)
+ n++;
+ if (uch > 0x1FFFFF)
+ n++;
+ if (uch > 0x3FFFFFF)
+ n++;
+ }
+ return n;
+}
+
+static OSStatus handleTSMUpdateActiveInputArea (TSMData* data, EventRef inEvent)
+{
+ UInt32 fixLength;
+ int caretPos = -1;
+ UInt32 actualSize;
+ ::TextRangeArray* hiliteRanges = NULL;
+ char* hiliteBuffer = NULL;
+ bool done;
+
+ // extract the text
+ UniChar* buffer = NULL;
+ UniChar temp [128];
+ UniChar* text = temp;
+
+ // get the fix length (in bytes)
+ OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendFixLen,
+ typeLongInteger, NULL, sizeof (long), NULL, &fixLength);
+ // need the size (in bytes)
+ if (noErr == err)
+ err = ::GetEventParameter (inEvent, kEventParamTextInputSendText,
+ typeUnicodeText, NULL, 256, &actualSize, temp);
+
+ // then allocate and fetch if necessary
+ UInt32 textLength = actualSize / sizeof (UniChar);
+ fixLength /= sizeof (UniChar);
+
+ if (noErr == err)
+ {
+ // this indicates that we are completely done
+ done = (fixLength == textLength || fixLength < 0);
+ if (textLength >= 128)
+ {
+ buffer = text = new UniChar [textLength];
+ err = ::GetEventParameter (inEvent, kEventParamTextInputSendText,
+ typeUnicodeText, NULL, actualSize, NULL, (void*) text);
+ }
+
+ // set the text now, but convert it to UTF-8 first
+ int utf8len;
+ char* utf8 = UTF16toUTF8 (text, textLength, utf8len);
+ data->scintilla->WndProc (SCI_SETTARGETSTART, data->selStart, 0);
+ data->scintilla->WndProc (SCI_SETTARGETEND, data->selStart + data->selLength, 0);
+ data->scintilla->WndProc (SCI_HIDESELECTION, 1, 0);
+ data->scintilla->WndProc (SCI_REPLACETARGET, utf8len, (sptr_t) utf8);
+ data->selLength = utf8len;
+ delete [] utf8;
+ }
+
+ // attempt to extract the array of hilite ranges
+ if (noErr == err)
+ {
+ ::TextRangeArray tempTextRangeArray;
+ OSStatus tempErr = ::GetEventParameter (inEvent, kEventParamTextInputSendHiliteRng,
+ typeTextRangeArray, NULL, sizeof (::TextRangeArray), &actualSize, &tempTextRangeArray);
+ if (noErr == tempErr)
+ {
+ // allocate memory and get the stuff!
+ hiliteBuffer = new char [actualSize];
+ hiliteRanges = (::TextRangeArray*) hiliteBuffer;
+ err = ::GetEventParameter (inEvent, kEventParamTextInputSendHiliteRng,
+ typeTextRangeArray, NULL, actualSize, NULL, hiliteRanges);
+ if (noErr != err)
+ {
+ delete [] hiliteBuffer;
+ hiliteBuffer = NULL;
+ hiliteRanges = NULL;
+ }
+ }
+ }
+#if LOG_TSM
+ fprintf (logFile, "kEventTextInputUpdateActiveInputArea:\n"
+ " TextLength = %ld\n"
+ " FixLength = %ld\n",
+ (long) textLength, (long) fixLength);
+ fflush (logFile);
+#endif
+
+ if (NULL != hiliteRanges)
+ {
+ for (int i = 0; i < hiliteRanges->fNumOfRanges; i++)
+ {
+#if LOG_TSM
+ fprintf (logFile, " Range #%d: %ld-%ld (%d)\n",
+ i+1,
+ hiliteRanges->fRange[i].fStart,
+ hiliteRanges->fRange[i].fEnd,
+ hiliteRanges->fRange[i].fHiliteStyle);
+ fflush (logFile);
+#endif
+ // start and end of range, zero based
+ long bgn = long (hiliteRanges->fRange[i].fStart) / sizeof (UniChar);
+ long end = long (hiliteRanges->fRange[i].fEnd) / sizeof (UniChar);
+ if (bgn >= 0 && end >= 0)
+ {
+ // move the caret if this is requested
+ if (hiliteRanges->fRange[i].fHiliteStyle == kTSMHiliteCaretPosition)
+ caretPos = bgn;
+ else
+ {
+ // determine which style to use
+ int style;
+ switch (hiliteRanges->fRange[i].fHiliteStyle)
+ {
+ case kTSMHiliteRawText: style = INDIC0_MASK; break;
+ case kTSMHiliteSelectedRawText: style = INDIC0_MASK; break;
+ case kTSMHiliteConvertedText: style = INDIC1_MASK; break;
+ case kTSMHiliteSelectedConvertedText: style = INDIC2_MASK; break;
+ default: style = INDIC0_MASK;
+ }
+ // bgn and end are Unicode offsets from the starting pos
+ // use the text buffer to determine the UTF-8 offsets
+ long utf8bgn = data->selStart + UTF8Length (text, bgn);
+ long utf8size = UTF8Length (text + bgn, end - bgn);
+ // set indicators
+ int oldEnd = data->scintilla->WndProc (SCI_GETENDSTYLED, 0, 0);
+ data->scintilla->WndProc (SCI_STARTSTYLING, utf8bgn, INDICS_MASK);
+ data->scintilla->WndProc (SCI_SETSTYLING, utf8size, style & ~1);
+ data->scintilla->WndProc (SCI_STARTSTYLING, oldEnd, 31);
+ }
+ }
+ }
+ }
+ if (noErr == err)
+ {
+ // if the fixed length is == to the new text, we are done
+ if (done)
+ stopInput (data, data->selStart + UTF8Length (text, textLength));
+ else if (caretPos >= 0)
+ {
+ data->selCur = data->selStart + UTF8Length (text, caretPos);
+ data->scintilla->WndProc (SCI_SETCURRENTPOS, data->selCur, 0);
+ }
+ }
+
+ delete [] hiliteBuffer;
+ delete [] buffer;
+ return err;
+}
+
+struct MacPoint {
+ short v;
+ short h;
+};
+
+static OSErr handleTSMOffset2Pos (TSMData* data, EventRef inEvent)
+{
+ long offset;
+
+ // get the offfset to convert
+ OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendTextOffset,
+ typeLongInteger, NULL, sizeof (long), NULL, &offset);
+ if (noErr == err)
+ {
+ // where is the caret now?
+ HIPoint where;
+
+ int line = (int) data->scintilla->WndProc (SCI_LINEFROMPOSITION, data->selCur, 0);
+ where.x = data->scintilla->WndProc (SCI_POINTXFROMPOSITION, 0, data->selCur);
+ where.y = data->scintilla->WndProc (SCI_POINTYFROMPOSITION, 0, data->selCur)
+ + data->scintilla->WndProc (SCI_TEXTHEIGHT, line, 0);
+ // convert to window coords
+ ::HIViewConvertPoint (&where, data->view, NULL);
+ // convert to screen coords
+ Rect global;
+ GetWindowBounds (HIViewGetWindow (data->view), kWindowStructureRgn, &global);
+ MacPoint pt;
+ pt.h = (short) where.x + global.left;
+ pt.v = (short) where.y + global.top;
+
+ // set the result
+ err = ::SetEventParameter (inEvent, kEventParamTextInputReplyPoint, typeQDPoint, sizeof (MacPoint), &pt);
+#if LOG_TSM
+ fprintf (logFile, "kEventTextInputOffsetToPos:\n"
+ " Offset: %ld\n"
+ " Pos: %ld:%ld (orig = %ld:%ld)\n", offset,
+ (long) pt.h, (long) pt.v,
+ (long) where.x, (long) where.y);
+ fflush (logFile);
+#endif
+ }
+ return err;
+}
+
+static OSErr handleTSMPos2Offset (TSMData* data, EventRef inEvent)
+{
+ MacPoint qdPosition;
+ long offset;
+ short regionClass;
+
+ // retrieve the global point to convert
+ OSStatus err = ::GetEventParameter (inEvent, kEventParamTextInputSendCurrentPoint,
+ typeQDPoint, NULL, sizeof (MacPoint), NULL, &qdPosition);
+ if (noErr == err)
+ {
+#if LOG_TSM
+ fprintf (logFile, "kEventTextInputPosToOffset:\n"
+ " Pos: %ld:%ld\n", (long) qdPosition.v, (long) qdPosition.h);
+ fflush (logFile);
+#endif
+ // convert to local coordinates
+ HIRect rect;
+ rect.origin.x = qdPosition.h;
+ rect.origin.y = qdPosition.v;
+ rect.size.width =
+ rect.size.height = 1;
+ ::HIViewConvertRect (&rect, NULL, data->view);
+
+ // we always report the position to be within the composition;
+ // coords inside the same pane are clipped to the composition,
+ // and if the position is outside, then we deactivate this instance
+ // this leaves the edit open and active so we can edit multiple panes
+ regionClass = kTSMInsideOfActiveInputArea;
+
+ // compute the offset (relative value)
+ offset = data->scintilla->WndProc (SCI_POSITIONFROMPOINTCLOSE, (uptr_t) rect.origin.x, (sptr_t) rect.origin.y);
+ if (offset >= 0)
+ {
+ // convert to a UTF-16 offset (Brute Force)
+ char* buf = getTextPortion (data, 0, offset);
+ offset = UCS2Length (buf, offset);
+ delete [] buf;
+
+#if LOG_TSM
+ fprintf (logFile, " Offset: %ld (class %ld)\n", offset, (long) regionClass);
+ fflush (logFile);
+#endif
+ // store the offset
+ err = ::SetEventParameter (inEvent, kEventParamTextInputReplyTextOffset, typeLongInteger, sizeof (long), &offset);
+ if (noErr == err)
+ err = ::SetEventParameter (inEvent, kEventParamTextInputReplyRegionClass, typeShortInteger, sizeof (short), &regionClass);
+ }
+ else
+ {
+ // not this pane!
+ err = eventNotHandledErr;
+ ExtInput::activate (data->view, false);
+ }
+
+ }
+ return err;
+}
+
+static OSErr handleTSMGetText (TSMData* data, EventRef inEvent)
+{
+ char* buf = getTextPortion (data, data->selStart, data->selLength);
+
+#if LOG_TSM
+ fprintf (logFile, "kEventTextInputGetSelectedText:\n"
+ " Text: \"%s\"\n", buf);
+ fflush (logFile);
+#endif
+ OSStatus status = ::SetEventParameter (inEvent, kEventParamTextInputReplyText, typeUTF8Text, data->selLength, buf);
+ delete [] buf;
+ return status;
+}
+
+static pascal OSStatus doHandleTSM (EventHandlerCallRef, EventRef inEvent, void* userData)
+{
+ TSMData* data = (TSMData*) userData;
+
+ OSStatus err = eventNotHandledErr;
+
+ switch (::GetEventKind (inEvent))
+ {
+ case kEventTextInputUpdateActiveInputArea:
+ // Make sure that input has been started
+ startInput (data);
+ err = handleTSMUpdateActiveInputArea (data, inEvent);
+ break;
+// case kEventTextInputUnicodeForKeyEvent:
+// err = handleTSMUnicodeInput (inEvent);
+// break;
+ case kEventTextInputOffsetToPos:
+ err = handleTSMOffset2Pos (data, inEvent);
+ break;
+ case kEventTextInputPosToOffset:
+ err = handleTSMPos2Offset (data, inEvent);
+ break;
+ case kEventTextInputGetSelectedText:
+ // Make sure that input has been started
+ startInput (data, false);
+ err = handleTSMGetText (data, inEvent);
+ break;
+ }
+ return err;
+}
+
diff --git a/scintilla/macosx/ExtInput.h b/scintilla/macosx/ExtInput.h
new file mode 100644
index 0000000..2e97015
--- /dev/null
+++ b/scintilla/macosx/ExtInput.h
@@ -0,0 +1,64 @@
+/*******************************************************************************
+
+Copyright (c) 2007 Adobe Systems Incorporated
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+********************************************************************************/
+
+#ifndef _ExtInput_h
+#define _ExtInput_h
+
+#include <Carbon/Carbon.h>
+#include "Scintilla.h"
+
+namespace Scintilla
+{
+
+/**
+The ExtInput class provides TSM input services to Scintilla.
+It uses the indicators 0 and 1 (see SCI_INDICSETSTYLE) to apply
+underlines to partially converted text.
+*/
+
+class ExtInput
+{
+public:
+ /**
+ Attach extended input to a HIView with attached Scintilla. This installs the needed
+ event handlers etc.
+ */
+ static void attach (HIViewRef ref);
+ /**
+ Detach extended input from a HIViewwith attached Scintilla.
+ */
+ static void detach (HIViewRef ref);
+ /**
+ Activate or deactivate extended input. This method should be called whenever
+ the view gains or loses focus.
+ */
+ static void activate (HIViewRef ref, bool on);
+ /**
+ Terminate extended input.
+ */
+ static void stop (HIViewRef ref);
+};
+
+} // end namespace
+
+#endif
diff --git a/scintilla/macosx/PlatMacOSX.cxx b/scintilla/macosx/PlatMacOSX.cxx
new file mode 100644
index 0000000..50f3fa0
--- /dev/null
+++ b/scintilla/macosx/PlatMacOSX.cxx
@@ -0,0 +1,1852 @@
+// Scintilla source code edit control
+// PlatMacOSX.cxx - implementation of platform facilities on MacOS X/Carbon
+// Based on work by Evan Jones (c) 2002 <ejones@uwaterloo.ca>
+// Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+
+#include <assert.h>
+
+#include <sys/time.h>
+
+#include <Carbon/Carbon.h>
+#include "QuartzTextLayout.h"
+#include "TCarbonEvent.h"
+
+#include "Platform.h"
+#include "Scintilla.h"
+#include "PlatMacOSX.h"
+#include "XPM.h"
+
+using namespace Scintilla;
+
+#include "ScintillaWidget.h"
+
+
+extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+inline CGRect PRectangleToCGRect( PRectangle& rc ) {
+ return CGRectMake( rc.left, rc.top, rc.Width(), rc.Height() );
+}
+
+inline PRectangle CGRectToPRectangle( const CGRect& rect ) {
+ PRectangle rc;
+ rc.left = (int)( rect.origin.x + 0.5 );
+ rc.top = (int)( rect.origin.y + 0.5 );
+ rc.right = (int)( rect.origin.x + rect.size.width + 0.5 );
+ rc.bottom = (int)( rect.origin.y + rect.size.height + 0.5 );
+ return rc;
+}
+
+Scintilla::Point Scintilla::Point::FromLong(long lpoint) {
+ return Scintilla::Point(
+ Platform::LowShortFromLong(lpoint),
+ Platform::HighShortFromLong(lpoint));
+}
+
+// The Palette is just ignored on Mac OS X. OS X runs "Millions" or "Thousands" of colours.
+Scintilla::Palette::Palette() {
+}
+
+Scintilla::Palette::~Palette() {
+}
+
+void Scintilla::Palette::Release() {
+}
+
+// Do nothing if it "wants" a colour. Copy the colour from desired to allocated if it is "finding" a colour.
+void Scintilla::Palette::WantFind(ColourPair &cp, bool want) {
+ if (want) {
+ } else {
+ cp.allocated.Set(cp.desired.AsLong());
+ }
+}
+
+void Scintilla::Palette::Allocate(Window &/*w*/) {
+ // OS X always runs in thousands or millions of colours
+}
+
+Font::Font() : fid(0) {}
+
+Font::~Font() { Release(); }
+
+
+void Font::Create(const char *faceName, int /*characterSet*/,
+ int size, bool bold, bool italic, int /*extraFontFlag*/) {
+ // TODO: How should I handle the characterSet request?
+ Release();
+
+ fid = new QuartzTextStyle();
+
+ // Find the font
+ QuartzFont font( faceName, strlen( faceName ) );
+
+ // We set Font, Size, Bold, Italic
+ QuartzTextSize textSize( size );
+ QuartzTextBold isBold( bold );
+ QuartzTextItalic isItalic( italic );
+
+ // Actually set the attributes
+ QuartzTextStyleAttribute* attributes[] = { &font, &textSize, &isBold, &isItalic };
+ reinterpret_cast<QuartzTextStyle*>( fid )->setAttributes( attributes, sizeof( attributes ) / sizeof( *attributes ) );
+
+ //ATSStyleRenderingOptions rendering = kATSStyleNoAntiAliasing;
+ //reinterpret_cast<QuartzTextStyle*>( fid )->setAttribute( kATSUStyleRenderingOptionsTag, sizeof( rendering ), &rendering );
+
+ // TODO: Why do I have to manually set this?
+ reinterpret_cast<QuartzTextStyle*>( fid )->setFontFeature( kLigaturesType, kCommonLigaturesOffSelector );
+}
+
+void Font::Release() {
+ if (fid)
+ delete reinterpret_cast<QuartzTextStyle*>( fid );
+
+ fid = 0;
+}
+
+SurfaceImpl::SurfaceImpl() {
+ bitmapData = NULL; // Release will try and delete bitmapData if != NULL
+ gc = NULL;
+ textLayout = new QuartzTextLayout(NULL);
+ Release();
+}
+
+SurfaceImpl::~SurfaceImpl() {
+ Release();
+ delete textLayout;
+}
+
+void SurfaceImpl::Release() {
+ textLayout->setContext (NULL);
+ if ( bitmapData != NULL )
+ {
+ delete[] bitmapData;
+ // We only "own" the graphics context if we are a bitmap context
+ if ( gc != NULL ) CGContextRelease( gc );
+ }
+ bitmapData = NULL;
+ gc = NULL;
+
+ bitmapWidth = 0;
+ bitmapHeight = 0;
+ x = 0;
+ y = 0;
+ //inited = false;
+}
+
+bool SurfaceImpl::Initialised() {
+ // We are initalised if the graphics context is not null
+ return gc != NULL;// || port != NULL;
+}
+
+void SurfaceImpl::Init(WindowID /*wid*/) {
+ // To be able to draw, the surface must get a CGContext handle. We save the graphics port,
+ // then aquire/release the context on an as-need basis (see above).
+ // XXX Docs on QDBeginCGContext are light, a better way to do this would be good.
+ // AFAIK we should not hold onto a context retrieved this way, thus the need for
+ // aquire/release of the context.
+
+ Release();
+}
+
+void SurfaceImpl::Init(SurfaceID sid, WindowID /*wid*/) {
+ Release();
+ gc = reinterpret_cast<CGContextRef>( sid );
+ CGContextSetLineWidth( gc, 1.0 );
+ textLayout->setContext (gc);
+}
+
+void SurfaceImpl::InitPixMap(int width, int height, Surface* /*surface_*/, WindowID /*wid*/) {
+ Release();
+ // Create a new bitmap context, along with the RAM for the bitmap itself
+ bitmapWidth = width;
+ bitmapHeight = height;
+
+ const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL);
+ const int bitmapByteCount = (bitmapBytesPerRow * height);
+
+ // create an RGB color space
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ if( colorSpace == NULL )
+ return;
+
+ // create the bitmap
+ bitmapData = new uint8_t[ bitmapByteCount ];
+ if( bitmapData != NULL ) {
+ // create the context
+ gc = CGBitmapContextCreate( bitmapData,
+ width,
+ height,
+ BITS_PER_COMPONENT,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast);
+
+ if( gc == NULL ) {
+ // the context couldn't be created for some reason,
+ // and we have no use for the bitmap without the context
+ delete[] bitmapData;
+ bitmapData = NULL;
+ }
+ textLayout->setContext (gc);
+ }
+
+ // the context retains the color space, so we can release it
+ CGColorSpaceRelease( colorSpace );
+
+ if ( gc != NULL && bitmapData != NULL )
+ {
+ // "Erase" to white
+ CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) );
+ CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 );
+ CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) );
+ }
+}
+
+void SurfaceImpl::PenColour(ColourAllocated fore) {
+ if (gc) {
+ ColourDesired colour( fore.AsLong() );
+
+ // Set the Stroke color to match
+ CGContextSetRGBStrokeColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, 1.0 );
+ }
+}
+
+void SurfaceImpl::FillColour(const ColourAllocated& back) {
+ if (gc) {
+ ColourDesired colour( back.AsLong() );
+
+ // Set the Fill color to match
+ CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, 1.0 );
+ }
+}
+
+CGImageRef SurfaceImpl::GetImage() {
+ // For now, assume that GetImage can only be called on PixMap surfaces
+ if ( bitmapData == NULL ) return NULL;
+
+ CGContextFlush( gc );
+
+ // create an RGB color space
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ if( colorSpace == NULL )
+ return NULL;
+
+ const int bitmapBytesPerRow = ((int) bitmapWidth * BYTES_PER_PIXEL);
+ const int bitmapByteCount = (bitmapBytesPerRow * (int) bitmapHeight);
+
+ // Create a data provider
+ CGDataProviderRef dataProvider = CGDataProviderCreateWithData( NULL, bitmapData, bitmapByteCount, NULL );
+ CGImageRef image = NULL;
+ if ( dataProvider != NULL )
+ {
+ // create the CGImage
+ image = CGImageCreate( bitmapWidth,
+ bitmapHeight,
+ BITS_PER_COMPONENT,
+ BITS_PER_PIXEL,
+ bitmapBytesPerRow,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast,
+ dataProvider,
+ NULL,
+ 0,
+ kCGRenderingIntentDefault );
+ }
+
+ // the image retains the color space, so we can release it
+ CGColorSpaceRelease( colorSpace );
+ colorSpace = NULL;
+
+ // Done with the data provider
+ CGDataProviderRelease( dataProvider );
+ dataProvider = NULL;
+
+ return image;
+}
+
+int SurfaceImpl::LogPixelsY() {
+ return 72;
+}
+
+int SurfaceImpl::DeviceHeightFont(int points) {
+ int logPix = LogPixelsY();
+ return (points * logPix + logPix / 2) / 72;
+}
+
+void SurfaceImpl::MoveTo(int x_, int y_) {
+ x = x_;
+ y = y_;
+}
+
+void SurfaceImpl::LineTo(int x_, int y_) {
+ CGContextBeginPath( gc );
+ // Because Quartz is based on floating point, lines are drawn with half their colour
+ // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel
+ // divison lines. If you specify exact pixel values, you get a line that
+ // is twice as thick but half as intense. To get pixel aligned rendering,
+ // we render the "middle" of the pixels by adding 0.5 to the coordinates.
+ CGContextMoveToPoint( gc, x + 0.5, y + 0.5 );
+ CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 );
+ CGContextStrokePath( gc );
+ x = x_;
+ y = y_;
+}
+
+void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore,
+ ColourAllocated back) {
+ // Allocate memory for the array of points
+ CGPoint *points = new CGPoint[ npts ];
+
+ for (int i = 0;i < npts;i++) {
+ // Quartz floating point issues: plot the MIDDLE of the pixels
+ points[i].x = pts[i].x + 0.5;
+ points[i].y = pts[i].y + 0.5;
+ }
+
+ CGContextBeginPath( gc );
+
+ // Set colours
+ FillColour(back);
+ PenColour(fore);
+
+ // Draw the polygon
+ CGContextAddLines( gc, points, npts );
+ // TODO: Should the path be automatically closed, or is that the caller's responsability?
+ // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only)
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+
+ // Deallocate memory
+ delete [] points;
+ points = NULL;
+}
+
+void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ if ( gc ) {
+ CGContextBeginPath( gc );
+ FillColour(back);
+ PenColour(fore);
+
+ // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo)
+ // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined
+ // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom.
+ // TODO: Create some version of PRectangleToCGRect to do this conversion for us?
+ CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+ }
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
+ if ( gc ) {
+ //CGContextBeginPath( gc );
+ FillColour(back);
+
+ CGRect rect = PRectangleToCGRect( rc );
+
+ CGContextFillRect( gc, rect );
+ //CGContextDrawPath( gc, kCGPathFill );
+ }
+}
+
+void drawImageRefCallback( CGImageRef pattern, CGContextRef gc )
+{
+ CGContextDrawImage( gc, CGRectMake( 0, 0, CGImageGetWidth( pattern ), CGImageGetHeight( pattern ) ), pattern );
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ SurfaceImpl& patternSurface = static_cast<SurfaceImpl &>(surfacePattern);
+
+ // For now, assume that copy can only be called on PixMap surfaces
+ // Shows up black
+ CGImageRef image = patternSurface.GetImage();
+ if ( image == NULL )
+ {
+ FillRectangle(rc, ColourAllocated(0));
+ return;
+ }
+
+ const CGPatternCallbacks drawImageCallbacks = { 0, reinterpret_cast<CGPatternDrawPatternCallback>( drawImageRefCallback ), NULL };
+
+ CGPatternRef pattern = CGPatternCreate( image,
+ CGRectMake( 0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight ),
+ CGAffineTransformIdentity,
+ patternSurface.bitmapWidth,
+ patternSurface.bitmapHeight,
+ kCGPatternTilingNoDistortion,
+ true,
+ &drawImageCallbacks
+ );
+ if( pattern != NULL ) {
+
+ // Create a pattern color space
+ CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL );
+ if( colorSpace != NULL ) {
+
+ CGContextSaveGState( gc );
+ CGContextSetFillColorSpace( gc, colorSpace );
+
+ // Unlike the documentation, you MUST pass in a "components" parameter:
+ // For coloured patterns it is the alpha value.
+ const float alpha = 1.0;
+ CGContextSetFillPattern( gc, pattern, &alpha );
+ CGContextFillRect( gc, PRectangleToCGRect( rc ) );
+ CGContextRestoreGState( gc );
+ // Free the color space, the pattern and image
+ CGColorSpaceRelease( colorSpace );
+ } /* colorSpace != NULL */
+ colorSpace = NULL;
+ CGPatternRelease( pattern );
+ pattern = NULL;
+ CGImageRelease( image );
+ image = NULL;
+ } /* pattern != NULL */
+}
+
+void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ // TODO: Look at the Win32 API to determine what this is supposed to do:
+ // ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 );
+
+ // Create a rectangle with semicircles at the corners
+ const int MAX_RADIUS = 4;
+ int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 );
+ radius = Platform::Minimum( radius, rc.Width()/2 );
+
+ // Points go clockwise, starting from just below the top left
+ // Corners are kept together, so we can easily create arcs to connect them
+ CGPoint corners[4][3] =
+ {
+ {
+ { rc.left, rc.top + radius },
+ { rc.left, rc.top },
+ { rc.left + radius, rc.top },
+ },
+ {
+ { rc.right - radius - 1, rc.top },
+ { rc.right - 1, rc.top },
+ { rc.right - 1, rc.top + radius },
+ },
+ {
+ { rc.right - 1, rc.bottom - radius - 1 },
+ { rc.right - 1, rc.bottom - 1 },
+ { rc.right - radius - 1, rc.bottom - 1 },
+ },
+ {
+ { rc.left + radius, rc.bottom - 1 },
+ { rc.left, rc.bottom - 1 },
+ { rc.left, rc.bottom - radius - 1 },
+ },
+ };
+
+ // Align the points in the middle of the pixels
+ // TODO: Should I include these +0.5 in the array creation code above?
+ for( int i = 0; i < 4*3; ++ i )
+ {
+ CGPoint* c = (CGPoint*) corners;
+ c[i].x += 0.5;
+ c[i].y += 0.5;
+ }
+
+ PenColour( fore );
+ FillColour( back );
+
+ // Move to the last point to begin the path
+ CGContextBeginPath( gc );
+ CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y );
+
+ for ( int i = 0; i < 4; ++ i )
+ {
+ CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y );
+ CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius );
+ }
+
+ // Close the path to enclose it for stroking and for filling, then draw it
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+}
+
+void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourAllocated fill, int alphaFill,
+ ColourAllocated /*outline*/, int /*alphaOutline*/, int /*flags*/)
+{
+ if ( gc ) {
+ ColourDesired colour( fill.AsLong() );
+
+ // Set the Fill color to match
+ CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 100.0 );
+ CGRect rect = PRectangleToCGRect( rc );
+ CGContextFillRect( gc, rect );
+ }
+}
+
+void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ // Drawing an ellipse with bezier curves. Code modified from:
+ // http://www.codeguru.com/gdi/ellipse.shtml
+ // MAGICAL CONSTANT to map ellipse to beziers 2/3*(sqrt(2)-1)
+ const double EToBConst = 0.2761423749154;
+
+ CGSize offset = CGSizeMake((int)(rc.Width() * EToBConst), (int)(rc.Height() * EToBConst));
+ CGPoint centre = CGPointMake((rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2);
+
+ // The control point array
+ CGPoint cCtlPt[13];
+
+ // Assign values to all the control points
+ cCtlPt[0].x =
+ cCtlPt[1].x =
+ cCtlPt[11].x =
+ cCtlPt[12].x = rc.left + 0.5;
+ cCtlPt[5].x =
+ cCtlPt[6].x =
+ cCtlPt[7].x = rc.right - 0.5;
+ cCtlPt[2].x =
+ cCtlPt[10].x = centre.x - offset.width + 0.5;
+ cCtlPt[4].x =
+ cCtlPt[8].x = centre.x + offset.width + 0.5;
+ cCtlPt[3].x =
+ cCtlPt[9].x = centre.x + 0.5;
+
+ cCtlPt[2].y =
+ cCtlPt[3].y =
+ cCtlPt[4].y = rc.top + 0.5;
+ cCtlPt[8].y =
+ cCtlPt[9].y =
+ cCtlPt[10].y = rc.bottom - 0.5;
+ cCtlPt[7].y =
+ cCtlPt[11].y = centre.y + offset.height + 0.5;
+ cCtlPt[1].y =
+ cCtlPt[5].y = centre.y - offset.height + 0.5;
+ cCtlPt[0].y =
+ cCtlPt[12].y =
+ cCtlPt[6].y = centre.y + 0.5;
+
+ FillColour(back);
+ PenColour(fore);
+
+ CGContextBeginPath( gc );
+ CGContextMoveToPoint( gc, cCtlPt[0].x, cCtlPt[0].y );
+
+ for ( int i = 1; i < 13; i += 3 )
+ {
+ CGContextAddCurveToPoint( gc, cCtlPt[i].x, cCtlPt[i].y, cCtlPt[i+1].x, cCtlPt[i+1].y, cCtlPt[i+2].x, cCtlPt[i+2].y );
+ }
+
+ // Close the path to enclose it for stroking and for filling, then draw it
+ CGContextClosePath( gc );
+ CGContextDrawPath( gc, kCGPathFillStroke );
+}
+
+void SurfaceImpl::CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect)
+{
+ SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
+ CGImageRef image = source.GetImage();
+
+ CGRect src = PRectangleToCGRect(srcRect);
+ CGRect dst = PRectangleToCGRect(dstRect);
+
+ /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */
+ float w = (float) CGImageGetWidth(image);
+ float h = (float) CGImageGetHeight(image);
+ CGRect drawRect = CGRectMake (0, 0, w, h);
+ if (!CGRectEqualToRect (src, dst))
+ {
+ float sx = CGRectGetWidth(dst) / CGRectGetWidth(src);
+ float sy = CGRectGetHeight(dst) / CGRectGetHeight(src);
+ float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx);
+ float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy);
+ drawRect = CGRectMake (dx, dy, w*sx, h*sy);
+ }
+ CGContextSaveGState (gc);
+ CGContextClipToRect (gc, dst);
+ CGContextDrawImage (gc, drawRect, image);
+ CGContextRestoreGState (gc);
+}
+
+void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) {
+ // Maybe we have to make the Surface two contexts:
+ // a bitmap context which we do all the drawing on, and then a "real" context
+ // which we copy the output to when we call "Synchronize". Ugh! Gross and slow!
+
+ // For now, assume that copy can only be called on PixMap surfaces
+ SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
+
+ // Get the CGImageRef
+ CGImageRef image = source.GetImage();
+ // If we could not get an image reference, fill the rectangle black
+ if ( image == NULL )
+ {
+ FillRectangle( rc, ColourAllocated( 0 ) );
+ return;
+ }
+
+ // Now draw the image on the surface
+
+ // Some fancy clipping work is required here: draw only inside of rc
+ CGContextSaveGState( gc );
+ CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
+
+ //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight );
+ CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image );
+
+ // Undo the clipping fun
+ CGContextRestoreGState( gc );
+
+ // Done with the image
+ CGImageRelease( image );
+ image = NULL;
+}
+
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+
+ FillRectangle(rc, back);
+ DrawTextTransparent( rc, font_, ybase, s, len, fore );
+}
+
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+
+ CGContextSaveGState( gc );
+ CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
+ DrawTextNoClip( rc, font_, ybase, s, len, fore, back );
+ CGContextRestoreGState( gc );
+}
+
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) {
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // The Quartz RGB fill color influences the ATSUI color
+ FillColour(fore);
+ // Draw the text, with the Y axis flipped
+ textLayout->draw( rc.left, ybase, true );
+}
+
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+ // sample at http://developer.apple.com/samplecode/ATSUICurveAccessDemo/listing1.html
+ // sample includes use of ATSUGetGlyphInfo which would be better for older
+ // OSX systems. We should expand to using that on older systems as well.
+ for (int i = 0; i < len; i++)
+ positions [i] = 0;
+
+ // We need the right X coords, so we have to append a char to get the left coord of thast extra char
+ char* buf = (char*) malloc (len+1);
+ if (!buf)
+ return;
+
+ memcpy (buf, s, len);
+ buf [len] = '.';
+
+ textLayout->setText (reinterpret_cast<const UInt8*>(buf), len+1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+ ATSUGlyphInfoArray* theGlyphInfoArrayPtr;
+ ByteCount theArraySize;
+
+ // Get the GlyphInfoArray
+ ATSUTextLayout layout = textLayout->getLayout();
+ if ( noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, NULL))
+ {
+ theGlyphInfoArrayPtr = (ATSUGlyphInfoArray *) malloc (theArraySize + sizeof(ItemCount) + sizeof(ATSUTextLayout));
+ if (theGlyphInfoArrayPtr)
+ {
+ if (noErr == ATSUGetGlyphInfo (layout, 0, textLayout->getLength(), &theArraySize, theGlyphInfoArrayPtr))
+ {
+ // do not count the first item, which is at the beginning of the line
+ for ( UniCharCount unicodePosition = 1, i = 0; i < len && unicodePosition < theGlyphInfoArrayPtr->numGlyphs; unicodePosition ++ )
+ {
+ // The ideal position is the x coordinate of the glyph, relative to the beginning of the line
+ int position = (int)( theGlyphInfoArrayPtr->glyphs[unicodePosition].idealX + 0.5 ); // These older APIs return float values
+ unsigned char uch = s[i];
+ positions[i++] = position;
+
+ // If we are using unicode (UTF8), map the Unicode position back to the UTF8 characters,
+ // as 1 unicode character can map to multiple UTF8 characters.
+ // See: http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF
+ // Or: http://www.cl.cam.ac.uk/~mgk25/unicode.html
+ if ( unicodeMode )
+ {
+ unsigned char mask = 0xc0;
+ int count = 1;
+ // Add one additonal byte for each extra high order one in the byte
+ while ( uch >= mask && count < 8 )
+ {
+ positions[i++] = position;
+ count ++;
+ mask = mask >> 1 | 0x80; // add an additional one in the highest order position
+ }
+ }
+ }
+ }
+
+ // Free the GlyphInfoArray
+ free (theGlyphInfoArrayPtr);
+ }
+ }
+ free (buf);
+}
+
+int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+ if (font_.GetID())
+ {
+ textLayout->setText (reinterpret_cast<const UInt8*>(s), len, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
+ unsigned long actualNumberOfBounds = 0;
+ ATSTrapezoid glyphBounds;
+
+ // We get a single bound, since the text should only require one. If it requires more, there is an issue
+ if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
+ {
+ Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthText" );
+ return 0;
+ }
+
+ //Platform::DebugPrintf( "WidthText: \"%*s\" = %ld\n", len, s, Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ) );
+ return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ }
+ return 1;
+}
+
+int SurfaceImpl::WidthChar(Font &font_, char ch) {
+ char str[2] = { ch, '\0' };
+ if (font_.GetID())
+ {
+ textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
+
+ // TODO: Maybe I should add some sort of text measurement features to QuartzTextLayout?
+ unsigned long actualNumberOfBounds = 0;
+ ATSTrapezoid glyphBounds;
+
+ // We get a single bound, since the text should only require one. If it requires more, there is an issue
+ if ( ATSUGetGlyphBounds( textLayout->getLayout(), 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ) != noErr || actualNumberOfBounds != 1 )
+ {
+ Platform::DebugDisplay( "ATSUGetGlyphBounds failed in WidthChar" );
+ return 0;
+ }
+
+ return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ }
+ else
+ return 1;
+}
+
+// Three possible strategies for determining ascent and descent of font:
+// 1) Call ATSUGetGlyphBounds with string containing all letters, numbers and punctuation.
+// 2) Use the ascent and descent fields of the font.
+// 3) Call ATSUGetGlyphBounds with string as 1 but also including accented capitals.
+// Smallest values given by 1 and largest by 3 with 2 in between.
+// Techniques 1 and 2 sometimes chop off extreme portions of ascenders and
+// descenders but are mostly OK except for accented characters which are
+// rarely used in code.
+
+// This string contains a good range of characters to test for size.
+const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+int SurfaceImpl::Ascent(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUAscentTag );
+ return Fix2Long( ascent );
+}
+
+int SurfaceImpl::Descent(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSUDescentTag );
+ return Fix2Long( descent );
+}
+
+int SurfaceImpl::InternalLeading(Font &) {
+ // TODO: How do we get EM_Size?
+ // internal leading = ascent - descent - EM_size
+ return 0;
+}
+
+int SurfaceImpl::ExternalLeading(Font &font_) {
+ if (!font_.GetID())
+ return 1;
+
+ ATSUTextMeasurement lineGap = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAttribute<ATSUTextMeasurement>( kATSULeadingTag );
+ return Fix2Long( lineGap );
+}
+
+int SurfaceImpl::Height(Font &font_) {
+ return Ascent(font_) + Descent(font_);
+}
+
+int SurfaceImpl::AverageCharWidth(Font &font_) {
+
+ if (!font_.GetID())
+ return 1;
+
+ const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1);
+ int width = WidthText( font_, sizeString, sizeStringLength );
+
+ return (int) ((width / (float) sizeStringLength) + 0.5);
+
+ /*
+ ATSUStyle textStyle = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getATSUStyle();
+ ATSUFontID fontID;
+
+ ByteCount actualSize = 0;
+ if ( ATSUGetAttribute( textStyle, kATSUFontTag, sizeof( fontID ), &fontID, &actualSize ) != noErr )
+ {
+Platform::DebugDisplay( "ATSUGetAttribute failed" );
+ return 1;
+ }
+
+ ATSFontMetrics metrics;
+ memset( &metrics, 0, sizeof( metrics ) );
+ if ( ATSFontGetHorizontalMetrics( fontID, kATSOptionFlagsDefault, &metrics ) != noErr )
+ {
+ Platform::DebugDisplay( "ATSFontGetHorizontalMetrics failed in AverageCharWidth" );
+ return 1;
+ }
+
+ printf( "%f %f %f\n", metrics.avgAdvanceWidth * 32, metrics.ascent * 32, metrics.descent * 32 );
+
+ return (int) (metrics.avgAdvanceWidth + 0.5);*/
+}
+
+int SurfaceImpl::SetPalette(Scintilla::Palette *, bool) {
+ // Mac OS X is always true colour (I think) so this doesn't matter
+ return 0;
+}
+
+void SurfaceImpl::SetClip(PRectangle rc) {
+ CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
+}
+
+void SurfaceImpl::FlushCachedState() {
+ CGContextSynchronize( gc );
+}
+
+void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+ unicodeMode = unicodeMode_;
+}
+
+void SurfaceImpl::SetDBCSMode(int codePage) {
+ // TODO: Implement this for code pages != UTF-8
+}
+
+Surface *Surface::Allocate() {
+ return new SurfaceImpl( );
+}
+
+Window::~Window() {
+}
+
+void Window::Destroy() {
+ if (windowRef) {
+ DisposeWindow(reinterpret_cast<WindowRef>( windowRef ));
+ }
+ wid = 0;
+}
+
+bool Window::HasFocus() {
+ // TODO: Test this
+ return HIViewSubtreeContainsFocus( reinterpret_cast<HIViewRef>( wid ) );
+}
+
+PRectangle Window::GetPosition() {
+ // Before any size allocated pretend its 1000 wide so not scrolled
+ PRectangle rc(0, 0, 1000, 1000);
+
+ // The frame rectangle gives the position of this view inside the parent view
+ if (wid) {
+ HIRect controlFrame;
+ HIViewGetFrame( reinterpret_cast<HIViewRef>( wid ), &controlFrame );
+ rc = CGRectToPRectangle( controlFrame );
+ }
+
+ return rc;
+}
+
+void Window::SetPosition(PRectangle rc) {
+ // Moves this view inside the parent view
+ if ( wid )
+ {
+ // Set the frame on the view, the function handles the rest
+ CGRect r = PRectangleToCGRect( rc );
+ HIViewSetFrame( reinterpret_cast<HIViewRef>( wid ), &r );
+ }
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window window) {
+ // used to actually move child windows (ie. listbox/calltip) so we have to move
+ // the window, not the hiview
+ if (windowRef) {
+ // we go through some contortions here to get an accurate location for our
+ // child windows. This is necessary due to the multiple ways an embedding
+ // app may be setup. See SciTest/main.c (GOOD && BAD) for test case.
+ WindowRef relativeWindow = GetControlOwner(reinterpret_cast<HIViewRef>( window.GetID() ));
+ WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef );
+
+ Rect portBounds;
+ ::GetWindowBounds(relativeWindow, kWindowStructureRgn, &portBounds);
+ //fprintf(stderr, "portBounds %d %d %d %d\n", portBounds.left, portBounds.top, portBounds.right, portBounds.bottom);
+ PRectangle hbounds = window.GetPosition();
+ //fprintf(stderr, "hbounds %d %d %d %d\n", hbounds.left, hbounds.top, hbounds.right, hbounds.bottom);
+ HIViewRef parent = HIViewGetSuperview(reinterpret_cast<HIViewRef>( window.GetID() ));
+ Rect pbounds;
+ GetControlBounds(parent, &pbounds);
+ //fprintf(stderr, "pbounds %d %d %d %d\n", pbounds.left, pbounds.top, pbounds.right, pbounds.bottom);
+
+ PRectangle bounds;
+ bounds.top = portBounds.top + pbounds.top + hbounds.top + rc.top;
+ bounds.bottom = bounds.top + rc.Height();
+ bounds.left = portBounds.left + pbounds.left + hbounds.left + rc.left;
+ bounds.right = bounds.left + rc.Width();
+ //fprintf(stderr, "bounds %d %d %d %d\n", bounds.left, bounds.top, bounds.right, bounds.bottom);
+
+ MoveWindow(thisWindow, bounds.left, bounds.top, false);
+ SizeWindow(thisWindow, bounds.Width(), bounds.Height(), true);
+
+ SetPosition(PRectangle(0,0,rc.Width(),rc.Height()));
+ } else {
+ SetPosition(rc);
+ }
+}
+
+PRectangle Window::GetClientPosition() {
+ // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32.
+ return GetPosition();
+}
+
+void Window::Show(bool show) {
+ if ( wid ) {
+ HIViewSetVisible( reinterpret_cast<HIViewRef>( wid ), show );
+ }
+ // this is necessary for calltip/listbox
+ if (windowRef) {
+ WindowRef thisWindow = reinterpret_cast<WindowRef>( windowRef );
+ if (show) {
+ ShowWindow( thisWindow );
+ DrawControls( thisWindow );
+ } else
+ HideWindow( thisWindow );
+ }
+}
+
+void Window::InvalidateAll() {
+ if ( wid ) {
+ HIViewSetNeedsDisplay( reinterpret_cast<HIViewRef>( wid ), true );
+ }
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+ if (wid) {
+ // Create a rectangular region
+ RgnHandle region = NewRgn();
+ SetRectRgn( region, rc.left, rc.top, rc.right, rc.bottom );
+
+ // Make that region invalid
+ HIViewSetNeedsDisplayInRegion( reinterpret_cast<HIViewRef>( wid ), region, true );
+ DisposeRgn( region );
+ }
+}
+
+void Window::SetFont(Font &) {
+ // TODO: Do I need to implement this? MSDN: specifies the font that a control is to use when drawing text.
+}
+
+void Window::SetCursor(Cursor curs) {
+ if (wid) {
+ // TODO: This isn't really implemented correctly. I should be using
+ // mouse tracking rectangles to only set the mouse cursor when it is over the control
+ ThemeCursor cursor;
+
+ switch ( curs ) {
+ case cursorText:
+ cursor = kThemeIBeamCursor;
+ break;
+ case cursorArrow:
+ cursor = kThemeArrowCursor;
+ break;
+ case cursorWait:
+ cursor = kThemeWatchCursor;
+ break;
+ case cursorHoriz:
+ cursor = kThemeResizeLeftRightCursor;
+ break;
+ case cursorVert:
+ cursor = kThemeResizeUpDownCursor;
+ break;
+ case cursorReverseArrow:
+ case cursorUp:
+ default:
+ cursor = kThemeArrowCursor;
+ break;
+ }
+
+ SetThemeCursor( cursor );
+ }
+}
+
+void Window::SetTitle(const char *s) {
+ WindowRef window = GetControlOwner(reinterpret_cast<HIViewRef>( wid ));
+ CFStringRef title = CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingMacRoman);
+ SetWindowTitleWithCFString(window, title);
+ CFRelease(title);
+}
+
+PRectangle Window::GetMonitorRect(Point) {
+ return PRectangle();
+}
+
+ListBox::ListBox() {}
+
+ListBox::~ListBox() {}
+
+static const OSType scintillaListBoxType = 'sclb';
+
+enum {
+ kItemsPerContainer = 1,
+ kIconColumn = 'icon',
+ kTextColumn = 'text'
+};
+static SInt32 kScrollBarWidth = 0;
+
+class LineData {
+ int *types;
+ CFStringRef *strings;
+ int len;
+ int maximum;
+public:
+ LineData() :types(0), strings(0), len(0), maximum(0) {}
+ ~LineData() {
+ Clear();
+ }
+ void Clear() {
+ delete []types;
+ types = 0;
+ for (int i=0; i<maximum; i++) {
+ if (strings[i]) CFRelease(strings[i]);
+ }
+ delete []strings;
+ strings = 0;
+ len = 0;
+ maximum = 0;
+ }
+ void Add(int index, int type, CFStringRef str ) {
+ if (index >= maximum) {
+ if (index >= len) {
+ int lenNew = (index+1) * 2;
+ int *typesNew = new int[lenNew];
+ CFStringRef *stringsNew = new CFStringRef[lenNew];
+ for (int i=0; i<maximum; i++) {
+ typesNew[i] = types[i];
+ stringsNew[i] = strings[i];
+ }
+ delete []types;
+ delete []strings;
+ types = typesNew;
+ strings = stringsNew;
+ len = lenNew;
+ }
+ while (maximum < index) {
+ types[maximum] = 0;
+ strings[maximum] = 0;
+ maximum++;
+ }
+ }
+ types[index] = type;
+ strings[index] = str;
+ if (index == maximum) {
+ maximum++;
+ }
+ }
+ int GetType(int index) {
+ if (index < maximum) {
+ return types[index];
+ } else {
+ return 0;
+ }
+ }
+ CFStringRef GetString(int index) {
+ if (index < maximum) {
+ return strings[index];
+ } else {
+ return 0;
+ }
+ }
+};
+
+class ListBoxImpl : public ListBox {
+private:
+ ControlRef lb;
+ XPMSet xset;
+ int lineHeight;
+ bool unicodeMode;
+ int desiredVisibleRows;
+ unsigned int maxItemWidth;
+ unsigned int aveCharWidth;
+ Font font;
+ int maxWidth;
+
+ void InstallDataBrowserCustomCallbacks();
+ void ConfigureDataBrowser();
+
+ static pascal OSStatus WindowEventHandler(EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void *inUserData );
+ EventHandlerRef eventHandler;
+
+protected:
+ WindowRef windowRef;
+
+public:
+ LineData ld;
+ CallBackAction doubleClickAction;
+ void *doubleClickActionData;
+
+ ListBoxImpl() : lb(NULL), lineHeight(10), unicodeMode(false),
+ desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8),
+ doubleClickAction(NULL), doubleClickActionData(NULL)
+ {
+ if (kScrollBarWidth == 0)
+ GetThemeMetric(kThemeMetricScrollBarWidth, &kScrollBarWidth);
+ }
+
+ ~ListBoxImpl() {};
+ void SetFont(Font &font);
+ void Create(Window &parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_);
+ void SetAverageCharWidth(int width);
+ void SetVisibleRows(int rows);
+ int GetVisibleRows() const;
+ PRectangle GetDesiredRect();
+ int CaretFromEdge();
+ void Clear();
+ void Append(char *s, int type = -1);
+ int Length();
+ void Select(int n);
+ int GetSelection();
+ int Find(const char *prefix);
+ void GetValue(int n, char *value, int len);
+ void Sort();
+ void RegisterImage(int type, const char *xpm_data);
+ void ClearRegisteredImages();
+ void SetDoubleClickAction(CallBackAction action, void *data) {
+ doubleClickAction = action;
+ doubleClickActionData = data;
+ }
+
+ int IconWidth();
+ void ShowHideScrollbar();
+#ifdef DB_TABLE_ROW_HEIGHT
+ void SetRowHeight(DataBrowserItemID itemID);
+#endif
+
+ void DrawRow(DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect);
+
+ void SetList(const char* list, char separator, char typesep);
+};
+
+ListBox *ListBox::Allocate() {
+ ListBoxImpl *lb = new ListBoxImpl();
+ return lb;
+}
+
+void ListBoxImpl::Create(Window &/*parent*/, int /*ctrlID*/, Scintilla::Point /*pt*/,
+ int lineHeight_, bool unicodeMode_) {
+ lineHeight = lineHeight_;
+ unicodeMode = unicodeMode_;
+ maxWidth = 2000;
+
+ WindowClass windowClass = kHelpWindowClass;
+ WindowAttributes attributes = kWindowNoAttributes;
+ Rect contentBounds;
+ WindowRef outWindow;
+
+ contentBounds.top = contentBounds.left = 0;
+ contentBounds.right = 100;
+ contentBounds.bottom = lineHeight * desiredVisibleRows;
+
+ CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow);
+
+ InstallStandardEventHandler(GetWindowEventTarget(outWindow));
+
+ ControlRef root;
+ CreateRootControl(outWindow, &root);
+
+ CreateDataBrowserControl(outWindow, &contentBounds, kDataBrowserListView, &lb);
+
+#ifdef DB_TABLE_ROW_HEIGHT
+ // XXX does not seem to have any effect
+ SetDataBrowserTableViewRowHeight(lb, lineHeight);
+#endif
+
+ // get rid of the frame, forces databrowser to the full size
+ // of the window
+ Boolean frameAndFocus = false;
+ SetControlData(lb, kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag,
+ sizeof(frameAndFocus), &frameAndFocus);
+
+ ListBoxImpl* lbThis = this;
+ SetControlProperty( lb, scintillaListBoxType, 0, sizeof( this ), &lbThis );
+
+ ConfigureDataBrowser();
+ InstallDataBrowserCustomCallbacks();
+
+ // install event handlers
+ static const EventTypeSpec kWindowEvents[] =
+ {
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseMoved },
+ };
+
+ eventHandler = NULL;
+ InstallWindowEventHandler( outWindow, WindowEventHandler,
+ GetEventTypeCount( kWindowEvents ),
+ kWindowEvents, this, &eventHandler );
+
+ wid = lb;
+ SetControlVisibility(lb, true, true);
+ SetControl(lb);
+ SetWindow(outWindow);
+}
+
+pascal OSStatus ListBoxImpl::WindowEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+
+ switch (GetEventClass(inEvent)) {
+ case kEventClassMouse:
+ switch (GetEventKind(inEvent))
+ {
+ case kEventMouseMoved:
+ {
+ SetThemeCursor( kThemeArrowCursor );
+ break;
+ }
+ case kEventMouseDown:
+ {
+ // we cannot handle the double click from the databrowser notify callback as
+ // calling doubleClickAction causes the listbox to be destroyed. It is
+ // safe to do it from this event handler since the destroy event will be queued
+ // until we're done here.
+ TCarbonEvent event( inEvent );
+ EventMouseButton inMouseButton;
+ event.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton );
+
+ UInt32 inClickCount;
+ event.GetParameter( kEventParamClickCount, &inClickCount );
+ if (inMouseButton == kEventMouseButtonPrimary && inClickCount == 2) {
+ // handle our single mouse click now
+ ListBoxImpl* listbox = reinterpret_cast<ListBoxImpl*>( inUserData );
+ const WindowRef window = GetControlOwner(listbox->lb);
+ const HIViewRef rootView = HIViewGetRoot( window );
+ HIViewRef targetView = NULL;
+ HIViewGetViewForMouseEvent( rootView, inEvent, &targetView );
+ if ( targetView == listbox->lb )
+ {
+ if (listbox->doubleClickAction != NULL) {
+ listbox->doubleClickAction(listbox->doubleClickActionData);
+ }
+ }
+ }
+ }
+ }
+ }
+ return eventNotHandledErr;
+}
+
+#ifdef DB_TABLE_ROW_HEIGHT
+void ListBoxImpl::SetRowHeight(DataBrowserItemID itemID)
+{
+ // XXX does not seem to have any effect
+ SetDataBrowserTableViewItemRowHeight(lb, itemID, lineHeight);
+}
+#endif
+
+void ListBoxImpl::DrawRow(DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect)
+{
+ Rect row = *theRect;
+ row.left = 0;
+
+ ColourPair fore;
+
+ if (itemState == kDataBrowserItemIsSelected) {
+ long systemVersion;
+ Gestalt( gestaltSystemVersion, &systemVersion );
+ // Panther DB starts using kThemeBrushSecondaryHighlightColor for inactive browser hilighting
+ if ( (systemVersion >= 0x00001030) && (IsControlActive( lb ) == false) )
+ SetThemePen( kThemeBrushSecondaryHighlightColor, 32, true );
+ else
+ //SetThemePen( kThemeBrushPrimaryHighlightColor, 32, true );
+ SetThemePen( kThemeBrushAlternatePrimaryHighlightColor, 32, true );
+
+ PaintRect(&row);
+ fore = ColourDesired(0xff,0xff,0xff);
+ }
+
+ int widthPix = xset.GetWidth() + 2;
+ int pixId = ld.GetType(item - 1);
+ XPM *pxpm = xset.Get(pixId);
+
+ char s[255];
+ GetValue(item - 1, s, 255);
+
+ Surface *surfaceItem = Surface::Allocate();
+ if (surfaceItem) {
+ CGContextRef cgContext;
+ GrafPtr port;
+ Rect bounds;
+
+ GetControlBounds(lb, &bounds);
+ GetPort( &port );
+ QDBeginCGContext( port, &cgContext );
+
+ CGContextSaveGState( cgContext );
+ CGContextTranslateCTM(cgContext, 0, bounds.bottom - bounds.top);
+ CGContextScaleCTM(cgContext, 1.0, -1.0);
+
+ surfaceItem->Init(cgContext, NULL);
+
+ int left = row.left;
+ if (pxpm) {
+ PRectangle rc(left + 1, row.top,
+ left + 1 + widthPix, row.bottom);
+ pxpm->Draw(surfaceItem, rc);
+ }
+
+ // draw the text
+ PRectangle trc(left + 2 + widthPix, row.top, row.right, row.bottom);
+ int ascent = surfaceItem->Ascent(font) - surfaceItem->InternalLeading(font);
+ int ytext = trc.top + ascent + 1;
+ trc.bottom = ytext + surfaceItem->Descent(font) + 1;
+ surfaceItem->DrawTextTransparent( trc, font, ytext, s, strlen(s), fore.allocated );
+
+ CGContextRestoreGState( cgContext );
+ QDEndCGContext( port, &cgContext );
+ delete surfaceItem;
+ }
+}
+
+
+pascal void ListBoxDrawItemCallback(ControlRef browser, DataBrowserItemID item,
+ DataBrowserPropertyID property,
+ DataBrowserItemState itemState,
+ const Rect *theRect, SInt16 gdDepth,
+ Boolean colorDevice)
+{
+ if (property != kIconColumn) return;
+ ListBoxImpl* lbThis = NULL;
+ OSStatus err;
+ err = GetControlProperty( browser, scintillaListBoxType, 0, sizeof( lbThis ), NULL, &lbThis );
+ // adjust our rect
+ lbThis->DrawRow(item, property, itemState, theRect);
+
+}
+
+void ListBoxImpl::ConfigureDataBrowser()
+{
+ DataBrowserViewStyle viewStyle;
+ DataBrowserSelectionFlags selectionFlags;
+ ::GetDataBrowserViewStyle(lb, &viewStyle);
+
+ ::SetDataBrowserHasScrollBars(lb, false, true);
+ ::SetDataBrowserListViewHeaderBtnHeight(lb, 0);
+ ::GetDataBrowserSelectionFlags(lb, &selectionFlags);
+ ::SetDataBrowserSelectionFlags(lb, selectionFlags |= kDataBrowserSelectOnlyOne);
+ // if you change the hilite style, also change the style in ListBoxDrawItemCallback
+ ::SetDataBrowserTableViewHiliteStyle(lb, kDataBrowserTableViewFillHilite);
+
+ Rect insetRect;
+ ::GetDataBrowserScrollBarInset(lb, &insetRect);
+
+ insetRect.right = kScrollBarWidth - 1;
+ ::SetDataBrowserScrollBarInset(lb, &insetRect);
+
+ switch (viewStyle)
+ {
+ case kDataBrowserListView:
+ {
+ DataBrowserListViewColumnDesc iconCol;
+ iconCol.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
+ iconCol.headerBtnDesc.minimumWidth = 0;
+ iconCol.headerBtnDesc.maximumWidth = maxWidth;
+ iconCol.headerBtnDesc.titleOffset = 0;
+ iconCol.headerBtnDesc.titleString = NULL;
+ iconCol.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
+
+ iconCol.headerBtnDesc.btnFontStyle.flags = kControlUseJustMask;
+ iconCol.headerBtnDesc.btnFontStyle.just = teFlushLeft;
+
+ iconCol.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
+
+ iconCol.propertyDesc.propertyID = kIconColumn;
+ iconCol.propertyDesc.propertyType = kDataBrowserCustomType;
+ iconCol.propertyDesc.propertyFlags = kDataBrowserListViewSelectionColumn;
+
+ ::AddDataBrowserListViewColumn(lb, &iconCol, kDataBrowserListViewAppendColumn);
+ } break;
+
+ }
+}
+
+void ListBoxImpl::InstallDataBrowserCustomCallbacks()
+{
+ DataBrowserCustomCallbacks callbacks;
+
+ callbacks.version = kDataBrowserLatestCustomCallbacks;
+ verify_noerr(InitDataBrowserCustomCallbacks(&callbacks));
+ callbacks.u.v1.drawItemCallback = NewDataBrowserDrawItemUPP(ListBoxDrawItemCallback);
+ callbacks.u.v1.hitTestCallback = NULL;//NewDataBrowserHitTestUPP(ListBoxHitTestCallback);
+ callbacks.u.v1.trackingCallback = NULL;//NewDataBrowserTrackingUPP(ListBoxTrackingCallback);
+ callbacks.u.v1.editTextCallback = NULL;
+ callbacks.u.v1.dragRegionCallback = NULL;
+ callbacks.u.v1.acceptDragCallback = NULL;
+ callbacks.u.v1.receiveDragCallback = NULL;
+
+ SetDataBrowserCustomCallbacks(lb, &callbacks);
+}
+
+void ListBoxImpl::SetFont(Font &font_) {
+ // Having to do this conversion is LAME
+ QuartzTextStyle *ts = reinterpret_cast<QuartzTextStyle*>( font_.GetID() );
+ ControlFontStyleRec style;
+ ATSUAttributeValuePtr value;
+ ATSUFontID fontID;
+ style.flags = kControlUseFontMask | kControlUseSizeMask | kControlAddToMetaFontMask;
+ ts->getAttribute( kATSUFontTag, sizeof(fontID), &fontID, NULL );
+ ATSUFontIDtoFOND(fontID, &style.font, NULL);
+ ts->getAttribute( kATSUSizeTag, sizeof(Fixed), &value, NULL );
+ style.size = ((SInt16)FixRound((SInt32)value));
+ SetControlFontStyle(lb, &style);
+
+#ifdef DB_TABLE_ROW_HEIGHT
+ // XXX this doesn't *stick*
+ ATSUTextMeasurement ascent = ts->getAttribute<ATSUTextMeasurement>( kATSUAscentTag );
+ ATSUTextMeasurement descent = ts->getAttribute<ATSUTextMeasurement>( kATSUDescentTag );
+ lineHeight = Fix2Long( ascent ) + Fix2Long( descent );
+ SetDataBrowserTableViewRowHeight(lb, lineHeight + lineLeading);
+#endif
+
+ // !@&^#%$ we cant copy Font, but we need one for our custom drawing
+ Str255 fontName255;
+ char fontName[256];
+ FMGetFontFamilyName(style.font, fontName255);
+
+ CFStringRef fontNameCF = ::CFStringCreateWithPascalString( kCFAllocatorDefault, fontName255, kCFStringEncodingMacRoman );
+ ::CFStringGetCString( fontNameCF, fontName, (CFIndex)255, kCFStringEncodingMacRoman );
+
+ font.Create((const char *)fontName, 0, style.size, false, false);
+}
+
+void ListBoxImpl::SetAverageCharWidth(int width) {
+ aveCharWidth = width;
+}
+
+void ListBoxImpl::SetVisibleRows(int rows) {
+ desiredVisibleRows = rows;
+}
+
+int ListBoxImpl::GetVisibleRows() const {
+ // XXX Windows & GTK do this, but it seems incorrect to me. Other logic
+ // to do with visible rows is essentially the same across platforms.
+ return desiredVisibleRows;
+ /*
+ // This would be more correct
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+ return rows;
+ */
+}
+
+PRectangle ListBoxImpl::GetDesiredRect() {
+ PRectangle rcDesired = GetPosition();
+
+ // XXX because setting the line height on the table doesnt
+ // *stick*, we'll have to suffer and just use whatever
+ // the table desides is the correct height.
+ UInt16 itemHeight;// = lineHeight;
+ GetDataBrowserTableViewRowHeight(lb, &itemHeight);
+
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+
+ rcDesired.bottom = itemHeight * rows;
+ rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth;
+
+ if (Length() > rows)
+ rcDesired.right += kScrollBarWidth;
+ rcDesired.right += IconWidth();
+
+ // Set the column width
+ ::SetDataBrowserTableViewColumnWidth (lb, UInt16 (rcDesired.right - rcDesired.left));
+ return rcDesired;
+}
+
+void ListBoxImpl::ShowHideScrollbar() {
+ int rows = Length();
+ if (rows > desiredVisibleRows) {
+ ::SetDataBrowserHasScrollBars(lb, false, true);
+ } else {
+ ::SetDataBrowserHasScrollBars(lb, false, false);
+ }
+}
+
+int ListBoxImpl::IconWidth() {
+ return xset.GetWidth() + 2;
+}
+
+int ListBoxImpl::CaretFromEdge() {
+ return 0;
+}
+
+void ListBoxImpl::Clear() {
+ // passing NULL to "items" arg 4 clears the list
+ maxItemWidth = 0;
+ ld.Clear();
+ AddDataBrowserItems (lb, kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty);
+}
+
+void ListBoxImpl::Append(char *s, int type) {
+ int count = Length();
+ CFStringRef r = CFStringCreateWithCString(NULL, s, kTextEncodingMacRoman);
+ ld.Add(count, type, r);
+
+ Scintilla::SurfaceImpl surface;
+ unsigned int width = surface.WidthText (font, s, strlen (s));
+ if (width > maxItemWidth)
+ maxItemWidth = width;
+
+ DataBrowserItemID items[1];
+ items[0] = count + 1;
+ AddDataBrowserItems (lb, kDataBrowserNoItem, 1, items, kDataBrowserItemNoProperty);
+ ShowHideScrollbar();
+}
+
+void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
+ // XXX copied from PlatGTK, should be in base class
+ Clear();
+ int count = strlen(list) + 1;
+ char *words = new char[count];
+ if (words) {
+ memcpy(words, list, count);
+ char *startword = words;
+ char *numword = NULL;
+ int i = 0;
+ for (; words[i]; i++) {
+ if (words[i] == separator) {
+ words[i] = '\0';
+ if (numword)
+ *numword = '\0';
+ 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';
+ Append(startword, numword?atoi(numword + 1):-1);
+ }
+ delete []words;
+ }
+}
+
+int ListBoxImpl::Length() {
+ UInt32 numItems = 0;
+ GetDataBrowserItemCount(lb, kDataBrowserNoItem, false, kDataBrowserItemAnyState, &numItems);
+ return (int)numItems;
+}
+
+void ListBoxImpl::Select(int n) {
+ DataBrowserItemID items[1];
+ items[0] = n + 1;
+ SetDataBrowserSelectedItems(lb, 1, items, kDataBrowserItemsAssign);
+ RevealDataBrowserItem(lb, items[0], kIconColumn, kDataBrowserRevealOnly);
+ // force update on selection
+ Draw1Control(lb);
+}
+
+int ListBoxImpl::GetSelection() {
+ Handle selectedItems = NewHandle(0);
+ GetDataBrowserItems(lb, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems);
+ UInt32 numSelectedItems = GetHandleSize(selectedItems)/sizeof(DataBrowserItemID);
+ if (numSelectedItems == 0) {
+ return -1;
+ }
+ HLock( selectedItems );
+ DataBrowserItemID *individualItem = (DataBrowserItemID*)( *selectedItems );
+ DataBrowserItemID selected[numSelectedItems];
+ selected[0] = *individualItem;
+ HUnlock( selectedItems );
+ return selected[0] - 1;
+}
+
+int ListBoxImpl::Find(const char *prefix) {
+ int count = Length();
+ char s[255];
+ for (int i = 0; i < count; i++) {
+ GetValue(i, s, 255);
+ if (s[0] != NULL && (0 == strncmp(prefix, s, strlen(prefix)))) {
+ return i;
+ }
+ }
+ return - 1;
+}
+
+void ListBoxImpl::GetValue(int n, char *value, int len) {
+ CFStringRef textString = ld.GetString(n);
+ if (textString == NULL) {
+ value[0] = '\0';
+ return;
+ }
+ CFIndex numUniChars = CFStringGetLength( textString );
+
+ // XXX how do we know the encoding of the listbox?
+ CFStringEncoding encoding = kCFStringEncodingUTF8; //( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII);
+ CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1;
+ char* text = new char[maximumByteLength];
+ CFIndex usedBufferLength = 0;
+ CFStringGetBytes( textString, CFRangeMake( 0, numUniChars ), encoding,
+ '?', false, reinterpret_cast<UInt8*>( text ),
+ maximumByteLength, &usedBufferLength );
+ text[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string
+
+ if (text && len > 0) {
+ strncpy(value, text, len);
+ value[len - 1] = '\0';
+ } else {
+ value[0] = '\0';
+ }
+ delete []text;
+}
+
+void ListBoxImpl::Sort() {
+ // TODO: Implement this
+ fprintf(stderr, "ListBox::Sort\n");
+}
+
+void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
+ xset.Add(type, xpm_data);
+}
+
+void ListBoxImpl::ClearRegisteredImages() {
+ xset.Clear();
+}
+
+Menu::Menu() : mid(0) { }
+
+void Menu::CreatePopUp() {
+ // TODO: Could I just feed a constant menu ID parameter, or does
+ // it really need to be unique?
+ static int nextMenuID = 1;
+ Destroy();
+ OSStatus err;
+ err = CreateNewMenu( nextMenuID++, 0, reinterpret_cast<MenuRef*>( &mid ) );
+}
+
+void Menu::Destroy() {
+ if ( mid != NULL )
+ {
+ ReleaseMenu( reinterpret_cast<MenuRef>( mid ) );
+ mid = NULL;
+ }
+}
+
+void Menu::Show(Point pt, Window &) {
+ UInt32 userSelection = 0;
+ SInt16 menuId = 0;
+ MenuItemIndex menuItem = 0;
+ ::Point globalPoint;
+ globalPoint.h = pt.x;
+ globalPoint.v = pt.y;
+ OSStatus err;
+ err = ContextualMenuSelect( reinterpret_cast<MenuRef>( mid ), globalPoint,
+ false, kCMHelpItemRemoveHelp, NULL,
+ NULL, &userSelection,
+ &menuId,
+ &menuItem
+ );
+}
+
+// TODO: Consider if I should be using GetCurrentEventTime instead of gettimeoday
+ElapsedTime::ElapsedTime() {
+ struct timeval curTime;
+ int retVal;
+ retVal = gettimeofday( &curTime, NULL );
+
+ bigBit = curTime.tv_sec;
+ littleBit = curTime.tv_usec;
+}
+
+double ElapsedTime::Duration(bool reset) {
+ struct timeval curTime;
+ int retVal;
+ retVal = gettimeofday( &curTime, NULL );
+ long endBigBit = curTime.tv_sec;
+ long endLittleBit = curTime.tv_usec;
+ double result = 1000000.0 * (endBigBit - bigBit);
+ result += endLittleBit - littleBit;
+ result /= 1000000.0;
+ if (reset) {
+ bigBit = endBigBit;
+ littleBit = endLittleBit;
+ }
+ return result;
+}
+
+ColourDesired Platform::Chrome() {
+ RGBColor c;
+ GetThemeBrushAsColor(kThemeBrushButtonActiveDarkShadow , 24, true, &c);
+ return ColourDesired(c.red>>8, c.green>>8, c.blue>>8);
+}
+
+ColourDesired Platform::ChromeHighlight() {
+ RGBColor c;
+ GetThemeBrushAsColor(kThemeBrushButtonInactiveLightShadow , 24, true, &c);
+ return ColourDesired(c.red>>8, c.green>>8, c.blue>>8);
+}
+
+static Str255 PlatformDefaultFontName;
+const char *Platform::DefaultFont() {
+ long fid = HighShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize));
+ FMGetFontFamilyName(fid, PlatformDefaultFontName);
+ char* defaultFontName = (char*) PlatformDefaultFontName;
+ defaultFontName[defaultFontName[0]+1] = 0;
+ ++defaultFontName;
+
+ return defaultFontName;
+}
+
+int Platform::DefaultFontSize() {
+ return LowShortFromLong(GetScriptVariable(smCurrentScript, smScriptAppFondSize));
+}
+
+unsigned int Platform::DoubleClickTime() {
+ // Convert from ticks to milliseconds. I think it would be better to use the events to tell us
+ // when we have a double and triple click, but what do I know?
+ return static_cast<unsigned int>( TicksToEventTime( GetDblTime() ) / kEventDurationMillisecond );
+}
+
+bool Platform::MouseButtonBounce() {
+ return false;
+}
+
+bool Platform::IsKeyDown(int keyCode) {
+ return false;
+ // TODO: Map Scintilla/Windows key codes to Mac OS X key codes
+ // TODO: Do I need this?
+ /*
+ // Inspired by code at: http://www.sover.net/~jams/Morgan/docs/GameInputMethods.txt
+
+ // Get the keys
+ KeyMap keys;
+ GetKeys( keys );
+
+ // Calculate the key map index
+ long keyMapIndex = keys[keyCode/8];
+ // Calculate the individual bit to check
+ short bitToCheck = keyCode % 8;
+ // Check the status of the key
+ return ( keyMapIndex >> bitToCheck ) & 0x01;
+ */
+}
+
+long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
+ return scintilla_send_message( w, msg, wParam, lParam );
+}
+
+bool Platform::IsDBCSLeadByte(int /*codePage*/, char /*ch*/) {
+ // TODO: Implement this for code pages != UTF-8
+ return false;
+}
+
+int Platform::DBCSCharLength(int /*codePage*/, const char* /*s*/) {
+ // TODO: Implement this for code pages != UTF-8
+ return 1;
+}
+
+int Platform::DBCSCharMaxLength() {
+ // TODO: Implement this for code pages != UTF-8
+ //return CFStringGetMaximumSizeForEncoding( 1, CFStringEncoding encoding );
+ return 2;
+}
+
+// These are utility functions not really tied to a platform
+int Platform::Minimum(int a, int b) {
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int Platform::Maximum(int a, int b) {
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+//#define TRACE
+#ifdef TRACE
+
+void Platform::DebugDisplay(const char *s) {
+ fprintf( stderr, s );
+}
+
+void Platform::DebugPrintf(const char *format, ...) {
+ const int BUF_SIZE = 2000;
+ char buffer[BUF_SIZE];
+
+ va_list pArguments;
+ va_start(pArguments, format);
+ vsnprintf(buffer, BUF_SIZE, format, pArguments);
+ va_end(pArguments);
+ Platform::DebugDisplay(buffer);
+}
+
+#else
+
+void Platform::DebugDisplay(const char *) {}
+
+void Platform::DebugPrintf(const char *, ...) {}
+
+#endif
+
+// Not supported for GTK+
+static bool assertionPopUps = true;
+
+bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
+ bool ret = assertionPopUps;
+ assertionPopUps = assertionPopUps_;
+ return ret;
+}
+
+void Platform::Assert(const char *c, const char *file, int line) {
+ char buffer[2000];
+ sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
+ strcat(buffer, "\r\n");
+ Platform::DebugDisplay(buffer);
+#ifdef DEBUG
+ // Jump into debugger in assert on Mac (CL269835)
+ ::Debugger();
+#endif
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+ if (val > maxVal)
+ val = maxVal;
+ if (val < minVal)
+ val = minVal;
+ return val;
+}
diff --git a/scintilla/macosx/PlatMacOSX.h b/scintilla/macosx/PlatMacOSX.h
new file mode 100644
index 0000000..e2dcb35
--- /dev/null
+++ b/scintilla/macosx/PlatMacOSX.h
@@ -0,0 +1,99 @@
+#ifndef PLATMACOSX_H
+#define PLATMACOSX_H
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+
+#include <assert.h>
+
+#include <sys/time.h>
+
+#include <Carbon/Carbon.h>
+#include "QuartzTextLayout.h"
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+namespace Scintilla {
+
+class SurfaceImpl : public Surface {
+private:
+ bool unicodeMode;
+ float x;
+ float y;
+
+ CGContextRef gc;
+
+
+ /** The text layout instance */
+ QuartzTextLayout* textLayout;
+ /** If the surface is a bitmap context, contains a reference to the bitmap data. */
+ uint8_t* bitmapData;
+ /** If the surface is a bitmap context, stores the dimensions of the bitmap. */
+ int bitmapWidth;
+ int bitmapHeight;
+
+ /** Set the CGContext's fill colour to the specified allocated colour. */
+ void FillColour( const ColourAllocated& back );
+
+
+ // 24-bit RGB+A bitmap data constants
+ static const int BITS_PER_COMPONENT = 8;
+ static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4;
+ static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8;
+public:
+ SurfaceImpl();
+ ~SurfaceImpl();
+
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+ CGContextRef GetContext() { return gc; }
+
+ void Release();
+ bool Initialised();
+ void PenColour(ColourAllocated fore);
+
+ /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */
+ CGImageRef GetImage();
+ void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect);
+
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Scintilla::Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource);
+
+ void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, int *positions);
+ int WidthText(Font &font_, const char *s, int len);
+ int WidthChar(Font &font_, char ch);
+ int Ascent(Font &font_);
+ int Descent(Font &font_);
+ int InternalLeading(Font &font_);
+ int ExternalLeading(Font &font_);
+ int Height(Font &font_);
+ int AverageCharWidth(Font &font_);
+
+ int SetPalette(Scintilla::Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage);
+};
+
+}
+
+#endif
diff --git a/scintilla/macosx/QuartzTextLayout.h b/scintilla/macosx/QuartzTextLayout.h
new file mode 100644
index 0000000..0290632
--- /dev/null
+++ b/scintilla/macosx/QuartzTextLayout.h
@@ -0,0 +1,141 @@
+/*
+ * QuartzTextLayout.h
+ *
+ * Original Code by Evan Jones on Wed Oct 02 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ */
+
+#ifndef _QUARTZ_TEXT_LAYOUT_H
+#define _QUARTZ_TEXT_LAYOUT_H
+
+#include <Carbon/Carbon.h>
+
+#include "QuartzTextStyle.h"
+
+class QuartzTextLayout
+{
+public:
+ /** Create a text layout for drawing on the specified context. */
+ QuartzTextLayout( CGContextRef context ) : layout( NULL ), unicode_string( NULL ), unicode_length( 0 )
+ {
+ OSStatus err = ATSUCreateTextLayout( &layout );
+ if (0 != err)
+ layout = NULL;
+
+ setContext(context);
+
+ ATSUAttributeTag tag = kATSULineLayoutOptionsTag;
+ ByteCount size = sizeof( ATSLineLayoutOptions );
+ ATSLineLayoutOptions rendering = kATSLineUseDeviceMetrics; //| kATSLineFractDisable | kATSLineUseQDRendering
+ ATSUAttributeValuePtr valuePtr = &rendering;
+ err = ATSUSetLayoutControls( layout, 1, &tag, &size, &valuePtr );
+ }
+
+ ~QuartzTextLayout()
+ {
+ if (NULL != layout)
+ ATSUDisposeTextLayout( layout );
+ layout = NULL;
+
+ if ( unicode_string != NULL )
+ {
+ delete[] unicode_string;
+ unicode_string = NULL;
+ unicode_length = 0;
+ }
+ }
+
+ /** Assign a string to the text layout object. */
+ // TODO: Create a UTF8 version
+ // TODO: Optimise the ASCII version by not copying so much
+ OSStatus setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding )
+ {
+ if (NULL == layout)
+ return -1;
+ CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false );
+ if (!str)
+ return -1;
+
+ unicode_length = CFStringGetLength( str );
+ if (unicode_string)
+ delete[] unicode_string;
+ unicode_string = new UniChar[ unicode_length ];
+ CFStringGetCharacters( str, CFRangeMake( 0, unicode_length ), unicode_string );
+
+ CFRelease( str );
+ str = NULL;
+
+ OSStatus err;
+ err = ATSUSetTextPointerLocation( layout, unicode_string, kATSUFromTextBeginning, kATSUToTextEnd, unicode_length );
+ if( err != noErr ) return err;
+
+ // Turn on the default font fallbacks
+ return ATSUSetTransientFontMatching( layout, true );
+ }
+
+ inline void setText( const UInt8* buffer, size_t byteLength, const QuartzTextStyle& r )
+ {
+ this->setText( buffer, byteLength, kCFStringEncodingUTF8 );
+ ATSUSetRunStyle( layout, r.getATSUStyle(), 0, unicode_length );
+ }
+
+ /** Apply the specified text style on the entire range of text. */
+ void setStyle( const QuartzTextStyle& style )
+ {
+ ATSUSetRunStyle( layout, style.getATSUStyle(), kATSUFromTextBeginning, kATSUToTextEnd );
+ }
+
+ /** Draw the text layout into the current CGContext at the specified position, flipping the CGContext's Y axis if required.
+ * @param x The x axis position to draw the baseline in the current CGContext.
+ * @param y The y axis position to draw the baseline in the current CGContext.
+ * @param flipTextYAxis If true, the CGContext's Y axis will be flipped before drawing the text, and restored afterwards. Use this when drawing in an HIView's CGContext, where the origin is the top left corner. */
+ void draw( float x, float y, bool flipTextYAxis = false )
+ {
+ if (NULL == layout || 0 == unicode_length)
+ return;
+ if ( flipTextYAxis )
+ {
+ CGContextSaveGState( gc );
+ CGContextScaleCTM( gc, 1.0, -1.0 );
+ y = -y;
+ }
+
+ OSStatus err;
+ err = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) );
+
+ if ( flipTextYAxis ) CGContextRestoreGState( gc );
+ }
+
+ /** Sets a single text layout control on the ATSUTextLayout object.
+ * @param tag The control to set.
+ * @param size The size of the parameter pointed to by value.
+ * @param value A pointer to the new value for the control.
+ */
+ void setControl( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
+ {
+ ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
+ }
+
+ ATSUTextLayout getLayout() {
+ return layout;
+ }
+
+ inline CFIndex getLength() const { return unicode_length; }
+ inline void setContext (CGContextRef context)
+ {
+ gc = context;
+ if (NULL != layout)
+ setControl( kATSUCGContextTag, sizeof( gc ), &gc );
+ }
+
+private:
+ ATSUTextLayout layout;
+ UniChar* unicode_string;
+ int unicode_length;
+ CGContextRef gc;
+};
+
+#endif
diff --git a/scintilla/macosx/QuartzTextStyle.h b/scintilla/macosx/QuartzTextStyle.h
new file mode 100644
index 0000000..171281f
--- /dev/null
+++ b/scintilla/macosx/QuartzTextStyle.h
@@ -0,0 +1,94 @@
+/*
+ * QuartzTextStyle.h
+ * wtf
+ *
+ * Created by Evan Jones on Wed Oct 02 2002.
+ * Copyright (c) 2002 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include <Carbon/Carbon.h>
+
+#ifndef _QUARTZ_TEXT_STYLE_H
+#define _QUARTZ_TEXT_STYLE_H
+
+#include "QuartzTextStyleAttribute.h"
+
+class QuartzTextStyle
+{
+public:
+ QuartzTextStyle()
+ {
+ ATSUCreateStyle( &style );
+ }
+
+ ~QuartzTextStyle()
+ {
+ if ( style != NULL )
+ ATSUDisposeStyle( style );
+ style = NULL;
+ }
+
+ void setAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value )
+ {
+ ATSUSetAttributes( style, 1, &tag, &size, &value );
+ }
+
+ void setAttribute( QuartzTextStyleAttribute& attribute )
+ {
+ setAttribute( attribute.getTag(), attribute.getSize(), attribute.getValuePtr() );
+ }
+
+ void getAttribute( ATSUAttributeTag tag, ByteCount size, ATSUAttributeValuePtr value, ByteCount* actualSize )
+ {
+ ATSUGetAttribute( style, tag, size, value, actualSize );
+ }
+
+ template <class T>
+ T getAttribute( ATSUAttributeTag tag )
+ {
+ T value;
+ ByteCount actualSize;
+ ATSUGetAttribute( style, tag, sizeof( T ), &value, &actualSize );
+ return value;
+ }
+
+ // TODO: Is calling this actually faster than calling setAttribute multiple times?
+ void setAttributes( QuartzTextStyleAttribute* attributes[], int number )
+ {
+ // Create the parallel arrays and initialize them properly
+ ATSUAttributeTag* tags = new ATSUAttributeTag[ number ];
+ ByteCount* sizes = new ByteCount[ number ];
+ ATSUAttributeValuePtr* values = new ATSUAttributeValuePtr[ number ];
+
+ for ( int i = 0; i < number; ++ i )
+ {
+ tags[i] = attributes[i]->getTag();
+ sizes[i] = attributes[i]->getSize();
+ values[i] = attributes[i]->getValuePtr();
+ }
+
+ ATSUSetAttributes( style, number, tags, sizes, values );
+
+ // Free the arrays that were allocated
+ delete[] tags;
+ delete[] sizes;
+ delete[] values;
+ }
+
+ void setFontFeature( ATSUFontFeatureType featureType, ATSUFontFeatureSelector selector )
+ {
+ ATSUSetFontFeatures( style, 1, &featureType, &selector );
+ }
+
+ const ATSUStyle& getATSUStyle() const
+ {
+ return style;
+ }
+
+private:
+ ATSUStyle style;
+};
+
+#endif
+
diff --git a/scintilla/macosx/QuartzTextStyleAttribute.h b/scintilla/macosx/QuartzTextStyleAttribute.h
new file mode 100644
index 0000000..9ebbe0d
--- /dev/null
+++ b/scintilla/macosx/QuartzTextStyleAttribute.h
@@ -0,0 +1,144 @@
+/*
+ * QuartzTextStyleAttribute.h
+ *
+ * Original Code by Evan Jones on Wed Oct 02 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ */
+
+
+#include <Carbon/Carbon.h>
+
+#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
+#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
+
+class QuartzTextStyleAttribute
+{
+public:
+ QuartzTextStyleAttribute() {}
+ virtual ~QuartzTextStyleAttribute() {}
+ virtual ByteCount getSize() const = 0;
+ virtual ATSUAttributeValuePtr getValuePtr() = 0;
+ virtual ATSUAttributeTag getTag() const = 0;
+};
+
+class QuartzTextSize : public QuartzTextStyleAttribute
+{
+public:
+ QuartzTextSize( float points )
+ {
+ size = X2Fix( points );
+ }
+
+ ByteCount getSize() const
+ {
+ return sizeof( size );
+ }
+
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &size;
+ }
+
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUSizeTag;
+ }
+
+private:
+ Fixed size;
+};
+
+class QuartzTextStyleAttributeBoolean : public QuartzTextStyleAttribute
+{
+public:
+ QuartzTextStyleAttributeBoolean( bool newVal ) : value( newVal ) {}
+
+ ByteCount getSize() const
+ {
+ return sizeof( value );
+ }
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &value;
+ }
+
+ virtual ATSUAttributeTag getTag() const = 0;
+
+private:
+ Boolean value;
+};
+
+class QuartzTextBold : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextBold( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUQDBoldfaceTag;
+ }
+};
+
+class QuartzTextItalic : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextItalic( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUQDItalicTag;
+ }
+};
+
+class QuartzTextUnderline : public QuartzTextStyleAttributeBoolean
+{
+public:
+ QuartzTextUnderline( bool newVal ) : QuartzTextStyleAttributeBoolean( newVal ) {}
+ ATSUAttributeTag getTag() const {
+ return kATSUQDUnderlineTag;
+ }
+};
+
+class QuartzFont : public QuartzTextStyleAttribute
+{
+public:
+ /** Create a font style from a name. */
+ QuartzFont( const char* name, int length )
+ {
+ assert( name != NULL && length > 0 && name[length] == '\0' );
+ // try to create font
+ OSStatus err = ATSUFindFontFromName( const_cast<char*>( name ), length, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
+
+ // need a fallback if font isn't installed
+ if( err != noErr || fontid == kATSUInvalidFontID )
+ ::ATSUFindFontFromName( "Lucida Grande", 13, kFontFullName, (unsigned) kFontNoPlatform, kFontRomanScript, (unsigned) kFontNoLanguage, &fontid );
+ }
+
+ ByteCount getSize() const
+ {
+ return sizeof( fontid );
+ }
+
+ ATSUAttributeValuePtr getValuePtr()
+ {
+ return &fontid;
+ }
+
+ ATSUAttributeTag getTag() const
+ {
+ return kATSUFontTag;
+ }
+
+ ATSUFontID getFontID() const
+ {
+ return fontid;
+ }
+
+private:
+ ATSUFontID fontid;
+};
+
+
+#endif
+
diff --git a/scintilla/macosx/SciTest/English.lproj/InfoPlist.strings b/scintilla/macosx/SciTest/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..42b037c
--- /dev/null
+++ b/scintilla/macosx/SciTest/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/scintilla/macosx/SciTest/English.lproj/main.nib/classes.nib b/scintilla/macosx/SciTest/English.lproj/main.nib/classes.nib
new file mode 100644
index 0000000..3f89d05
--- /dev/null
+++ b/scintilla/macosx/SciTest/English.lproj/main.nib/classes.nib
@@ -0,0 +1,4 @@
+{
+IBClasses = ();
+IBVersion = 1;
+}
diff --git a/scintilla/macosx/SciTest/English.lproj/main.nib/info.nib b/scintilla/macosx/SciTest/English.lproj/main.nib/info.nib
new file mode 100644
index 0000000..aae9f6b
--- /dev/null
+++ b/scintilla/macosx/SciTest/English.lproj/main.nib/info.nib
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>345.0</string>
+ <key>IBOldestOS</key>
+ <integer>3</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>29</integer>
+ <integer>166</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>7B44</string>
+ <key>targetFramework</key>
+ <string>IBCarbonFramework</string>
+</dict>
+</plist>
diff --git a/scintilla/macosx/SciTest/English.lproj/main.nib/objects.xib b/scintilla/macosx/SciTest/English.lproj/main.nib/objects.xib
new file mode 100644
index 0000000..e78d4aa
--- /dev/null
+++ b/scintilla/macosx/SciTest/English.lproj/main.nib/objects.xib
@@ -0,0 +1,271 @@
+<?xml version="1.0" standalone="yes"?>
+<object class="NSIBObjectData">
+ <string name="targetFramework">IBCarbonFramework</string>
+ <object name="rootObject" class="NSCustomObject" id="1">
+ <string name="customClass">NSApplication</string>
+ </object>
+ <array count="38" name="allObjects">
+ <object class="IBCarbonMenu" id="29">
+ <string name="title">main</string>
+ <array count="4" name="items">
+ <object class="IBCarbonMenuItem" id="185">
+ <string name="title">Foo</string>
+ <object name="submenu" class="IBCarbonMenu" id="184">
+ <string name="title">Foo</string>
+ <array count="1" name="items">
+ <object class="IBCarbonMenuItem" id="187">
+ <string name="title">About Foo</string>
+ <int name="keyEquivalentModifier">0</int>
+ <ostype name="command">abou</ostype>
+ </object>
+ </array>
+ <string name="name">_NSAppleMenu</string>
+ </object>
+ </object>
+ <object class="IBCarbonMenuItem" id="127">
+ <string name="title">File</string>
+ <object name="submenu" class="IBCarbonMenu" id="131">
+ <string name="title">File</string>
+ <array count="10" name="items">
+ <object class="IBCarbonMenuItem" id="139">
+ <string name="title">New</string>
+ <string name="keyEquivalent">n</string>
+ <ostype name="command">new </ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="134">
+ <string name="title">Open…</string>
+ <string name="keyEquivalent">o</string>
+ <ostype name="command">open</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="133">
+ <boolean name="separator">TRUE</boolean>
+ </object>
+ <object class="IBCarbonMenuItem" id="130">
+ <string name="title">Close</string>
+ <string name="keyEquivalent">w</string>
+ <ostype name="command">clos</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="138">
+ <string name="title">Save</string>
+ <string name="keyEquivalent">s</string>
+ <ostype name="command">save</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="137">
+ <string name="title">Save As…</string>
+ <string name="keyEquivalent">S</string>
+ <ostype name="command">svas</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="132">
+ <string name="title">Revert</string>
+ <string name="keyEquivalent">r</string>
+ <ostype name="command">rvrt</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="128">
+ <boolean name="separator">TRUE</boolean>
+ </object>
+ <object class="IBCarbonMenuItem" id="135">
+ <string name="title">Page Setup…</string>
+ <string name="keyEquivalent">P</string>
+ <ostype name="command">page</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="136">
+ <string name="title">Print…</string>
+ <string name="keyEquivalent">p</string>
+ <ostype name="command">prnt</ostype>
+ </object>
+ </array>
+ </object>
+ </object>
+ <object class="IBCarbonMenuItem" id="152">
+ <string name="title">Edit</string>
+ <object name="submenu" class="IBCarbonMenu" id="147">
+ <string name="title">Edit</string>
+ <array count="10" name="items">
+ <object class="IBCarbonMenuItem" id="141">
+ <string name="title">Undo</string>
+ <string name="keyEquivalent">z</string>
+ <ostype name="command">undo</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="146">
+ <string name="title">Redo</string>
+ <string name="keyEquivalent">Z</string>
+ <ostype name="command">redo</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="142">
+ <boolean name="separator">TRUE</boolean>
+ </object>
+ <object class="IBCarbonMenuItem" id="143">
+ <string name="title">Cut</string>
+ <string name="keyEquivalent">x</string>
+ <ostype name="command">cut </ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="149">
+ <string name="title">Copy</string>
+ <string name="keyEquivalent">c</string>
+ <ostype name="command">copy</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="144">
+ <string name="title">Paste</string>
+ <string name="keyEquivalent">v</string>
+ <ostype name="command">past</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="151">
+ <string name="title">Delete</string>
+ <ostype name="command">clea</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="148">
+ <string name="title">Select All</string>
+ <string name="keyEquivalent">a</string>
+ <ostype name="command">sall</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="199">
+ <boolean name="separator">TRUE</boolean>
+ </object>
+ <object class="IBCarbonMenuItem" id="198">
+ <string name="title">Special Characters…</string>
+ <ostype name="command">chrp</ostype>
+ </object>
+ </array>
+ </object>
+ </object>
+ <object class="IBCarbonMenuItem" id="192">
+ <string name="title">Window</string>
+ <object name="submenu" class="IBCarbonMenu" id="195">
+ <string name="title">Window</string>
+ <array count="6" name="items">
+ <object class="IBCarbonMenuItem" id="197">
+ <string name="title">Zoom Window</string>
+ <ostype name="command">zoom</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="190">
+ <boolean name="dynamic">TRUE</boolean>
+ <string name="title">Minimize Window</string>
+ <string name="keyEquivalent">m</string>
+ <ostype name="command">mini</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="191">
+ <boolean name="dynamic">TRUE</boolean>
+ <string name="title">Minimize All Windows</string>
+ <string name="keyEquivalent">m</string>
+ <int name="keyEquivalentModifier">1572864</int>
+ <ostype name="command">mina</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="194">
+ <boolean name="separator">TRUE</boolean>
+ </object>
+ <object class="IBCarbonMenuItem" id="196">
+ <boolean name="dynamic">TRUE</boolean>
+ <string name="title">Bring All to Front</string>
+ <ostype name="command">bfrt</ostype>
+ </object>
+ <object class="IBCarbonMenuItem" id="193">
+ <boolean name="dynamic">TRUE</boolean>
+ <string name="title">Arrange in Front</string>
+ <int name="keyEquivalentModifier">1572864</int>
+ <ostype name="command">frnt</ostype>
+ </object>
+ </array>
+ <string name="name">_NSWindowsMenu</string>
+ </object>
+ </object>
+ </array>
+ <string name="name">_NSMainMenu</string>
+ </object>
+ <reference idRef="127"/>
+ <reference idRef="128"/>
+ <reference idRef="130"/>
+ <reference idRef="131"/>
+ <reference idRef="132"/>
+ <reference idRef="133"/>
+ <reference idRef="134"/>
+ <reference idRef="135"/>
+ <reference idRef="136"/>
+ <reference idRef="137"/>
+ <reference idRef="138"/>
+ <reference idRef="139"/>
+ <reference idRef="141"/>
+ <reference idRef="142"/>
+ <reference idRef="143"/>
+ <reference idRef="144"/>
+ <reference idRef="146"/>
+ <reference idRef="147"/>
+ <reference idRef="148"/>
+ <reference idRef="149"/>
+ <reference idRef="151"/>
+ <reference idRef="152"/>
+ <object class="IBCarbonWindow" id="166">
+ <string name="windowRect">204 300 564 780 </string>
+ <string name="title">Window</string>
+ <object name="rootControl" class="IBCarbonRootControl" id="167">
+ <string name="bounds">0 0 360 480 </string>
+ <string name="viewFrame">0 0 480 360 </string>
+ </object>
+ <boolean name="receiveUpdates">FALSE</boolean>
+ <boolean name="liveResize">TRUE</boolean>
+ <boolean name="compositing">TRUE</boolean>
+ </object>
+ <reference idRef="167"/>
+ <reference idRef="184"/>
+ <reference idRef="185"/>
+ <reference idRef="187"/>
+ <reference idRef="190"/>
+ <reference idRef="191"/>
+ <reference idRef="192"/>
+ <reference idRef="193"/>
+ <reference idRef="194"/>
+ <reference idRef="195"/>
+ <reference idRef="196"/>
+ <reference idRef="197"/>
+ <reference idRef="198"/>
+ <reference idRef="199"/>
+ </array>
+ <array count="38" name="allParents">
+ <reference idRef="1"/>
+ <reference idRef="29"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="127"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="131"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="152"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ <reference idRef="29"/>
+ <reference idRef="1"/>
+ <reference idRef="166"/>
+ <reference idRef="185"/>
+ <reference idRef="29"/>
+ <reference idRef="184"/>
+ <reference idRef="195"/>
+ <reference idRef="195"/>
+ <reference idRef="29"/>
+ <reference idRef="195"/>
+ <reference idRef="195"/>
+ <reference idRef="192"/>
+ <reference idRef="195"/>
+ <reference idRef="195"/>
+ <reference idRef="147"/>
+ <reference idRef="147"/>
+ </array>
+ <dictionary count="3" name="nameTable">
+ <string>Files Owner</string>
+ <reference idRef="1"/>
+ <string>MainWindow</string>
+ <reference idRef="166"/>
+ <string>MenuBar</string>
+ <reference idRef="29"/>
+ </dictionary>
+ <unsigned_int name="nextObjectID">200</unsigned_int>
+</object>
diff --git a/scintilla/macosx/SciTest/Info.plist b/scintilla/macosx/SciTest/Info.plist
new file mode 100644
index 0000000..6a66513
--- /dev/null
+++ b/scintilla/macosx/SciTest/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>SciTest</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.myCarbonApp</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/scintilla/macosx/SciTest/SciTest.xcode/project.pbxproj b/scintilla/macosx/SciTest/SciTest.xcode/project.pbxproj
new file mode 100644
index 0000000..c771cc5
--- /dev/null
+++ b/scintilla/macosx/SciTest/SciTest.xcode/project.pbxproj
@@ -0,0 +1,289 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 3002B123087DCEC600CEAF79 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3002B122087DCEC600CEAF79 /* main.cpp */; };
+ 30973FF8086B7F4F0088809C /* libscintilla.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30973FF7086B7F4F0088809C /* libscintilla.a */; };
+ 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
+ 8D0C4E8E0486CD37000505A6 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; };
+ 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; };
+ 20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ 3002B122087DCEC600CEAF79 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ 30973FF7086B7F4F0088809C /* libscintilla.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libscintilla.a; path = ../../bin/libscintilla.a; sourceTree = SOURCE_ROOT; };
+ 32DBCF6D0370B57F00C91783 /* SciTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SciTest_Prefix.pch; sourceTree = "<group>"; };
+ 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
+ 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
+ 8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D0C4E970486CD37000505A6 /* SciTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SciTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D0C4E910486CD37000505A6 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */,
+ 30973FF8086B7F4F0088809C /* libscintilla.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 195DF8CFFE9D517E11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D0C4E970486CD37000505A6 /* SciTest.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 20286C29FDCF999611CA2CEA /* SciTest */ = {
+ isa = PBXGroup;
+ children = (
+ 20286C2AFDCF999611CA2CEA /* Sources */,
+ 20286C2CFDCF999611CA2CEA /* Resources */,
+ 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */,
+ 195DF8CFFE9D517E11CA2CBB /* Products */,
+ );
+ name = SciTest;
+ sourceTree = "<group>";
+ };
+ 20286C2AFDCF999611CA2CEA /* Sources */ = {
+ isa = PBXGroup;
+ children = (
+ 3002B122087DCEC600CEAF79 /* main.cpp */,
+ 32DBCF6D0370B57F00C91783 /* SciTest_Prefix.pch */,
+ );
+ name = Sources;
+ sourceTree = "<group>";
+ };
+ 20286C2CFDCF999611CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D0C4E960486CD37000505A6 /* Info.plist */,
+ 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */,
+ 02345980000FD03B11CA0E72 /* main.nib */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 30973FF7086B7F4F0088809C /* libscintilla.a */,
+ 20286C33FDCF999611CA2CEA /* Carbon.framework */,
+ 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */,
+ 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D0C4E890486CD37000505A6 /* SciTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 304E977D0C0519E500702100 /* Build configuration list for PBXNativeTarget "SciTest" */;
+ buildPhases = (
+ 8D0C4E8C0486CD37000505A6 /* Resources */,
+ 8D0C4E8F0486CD37000505A6 /* Sources */,
+ 8D0C4E910486CD37000505A6 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SciTest;
+ productInstallPath = "$(HOME)/Applications";
+ productName = SciTest;
+ productReference = 8D0C4E970486CD37000505A6 /* SciTest.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 20286C28FDCF999611CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 304E97810C0519E500702100 /* Build configuration list for PBXProject "SciTest" */;
+ compatibilityVersion = "Xcode 2.4";
+ hasScannedForEncodings = 1;
+ mainGroup = 20286C29FDCF999611CA2CEA /* SciTest */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D0C4E890486CD37000505A6 /* SciTest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D0C4E8C0486CD37000505A6 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */,
+ 8D0C4E8E0486CD37000505A6 /* main.nib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D0C4E8F0486CD37000505A6 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3002B123087DCEC600CEAF79 /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 02345980000FD03B11CA0E72 /* main.nib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 1870340FFE93FCAF11CA0CD7 /* English */,
+ );
+ name = main.nib;
+ sourceTree = "<group>";
+ };
+ 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 0867D6ABFE840B52C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 304E977E0C0519E500702100 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = SciTest_Prefix.pch;
+ HEADER_SEARCH_PATHS = (
+ ..,
+ ../../include,
+ ../../src,
+ );
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ LIBRARY_SEARCH_PATHS = ../../bin;
+ OTHER_CFLAGS = (
+ "-DSCI_NAMESPACE=1",
+ "-DSCI_NAMESPACE",
+ "-DMACOSX",
+ "-DSCI_LEXER",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
+ "-DSCI_NAMESPACE=1",
+ "-DSCI_NAMESPACE",
+ "-DMACOSX",
+ "-DSCI_LEXER",
+ );
+ PRODUCT_NAME = SciTest;
+ WRAPPER_EXTENSION = app;
+ ZERO_LINK = YES;
+ };
+ name = Development;
+ };
+ 304E977F0C0519E500702100 /* Deployment */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = SciTest_Prefix.pch;
+ HEADER_SEARCH_PATHS = (
+ ..,
+ ../../include,
+ ../../src,
+ );
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ LIBRARY_SEARCH_PATHS = "";
+ PRODUCT_NAME = SciTest;
+ WRAPPER_EXTENSION = app;
+ ZERO_LINK = NO;
+ };
+ name = Deployment;
+ };
+ 304E97800C0519E500702100 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = SciTest_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ LIBRARY_SEARCH_PATHS = "";
+ PRODUCT_NAME = SciTest;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Default;
+ };
+ 304E97820C0519E500702100 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Development;
+ };
+ 304E97830C0519E500702100 /* Deployment */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Deployment;
+ };
+ 304E97840C0519E500702100 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Default;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 304E977D0C0519E500702100 /* Build configuration list for PBXNativeTarget "SciTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 304E977E0C0519E500702100 /* Development */,
+ 304E977F0C0519E500702100 /* Deployment */,
+ 304E97800C0519E500702100 /* Default */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
+ };
+ 304E97810C0519E500702100 /* Build configuration list for PBXProject "SciTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 304E97820C0519E500702100 /* Development */,
+ 304E97830C0519E500702100 /* Deployment */,
+ 304E97840C0519E500702100 /* Default */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 20286C28FDCF999611CA2CEA /* Project object */;
+}
diff --git a/scintilla/macosx/SciTest/SciTest_Prefix.pch b/scintilla/macosx/SciTest/SciTest_Prefix.pch
new file mode 100644
index 0000000..33b8548
--- /dev/null
+++ b/scintilla/macosx/SciTest/SciTest_Prefix.pch
@@ -0,0 +1,5 @@
+//
+// Prefix header for all source files of the 'SciTest' target in the 'SciTest' project.
+//
+
+#include <Carbon/Carbon.h>
diff --git a/scintilla/macosx/SciTest/main.cpp b/scintilla/macosx/SciTest/main.cpp
new file mode 100644
index 0000000..2171371
--- /dev/null
+++ b/scintilla/macosx/SciTest/main.cpp
@@ -0,0 +1,255 @@
+//
+// main.c
+// SciTest
+//
+// Copyright (c) 2005-2006 ActiveState Software Inc.
+// All rights reserved.
+//
+// Created by Shane Caraveo on 3/20/05.
+//
+
+#include <Carbon/Carbon.h>
+#include "TView.h"
+#include "TCarbonEvent.h"
+#include "ScintillaMacOSX.h"
+
+extern "C" HIViewRef scintilla_new(void);
+
+const HILayoutInfo kBindToParentLayout = {
+ kHILayoutInfoVersionZero,
+ { { NULL, kHILayoutBindTop }, { NULL, kHILayoutBindLeft }, { NULL, kHILayoutBindBottom }, { NULL, kHILayoutBindRight } },
+ { { NULL, kHILayoutScaleAbsolute, 0 }, { NULL, kHILayoutScaleAbsolute, 0 } },
+ { { NULL, kHILayoutPositionTop, 0 }, { NULL, kHILayoutPositionLeft, 0 } }
+};
+
+using namespace Scintilla;
+
+/* XPM */
+static char *ac_class[] = {
+/* columns rows colors chars-per-pixel */
+"18 12 24 1",
+" c black",
+". c #403030",
+"X c #473636",
+"o c #4E3C3C",
+"O c #474141",
+"+ c #5F4C4C",
+"@ c #756362",
+"# c #98342C",
+"$ c #A0392F",
+"% c #B24235",
+"& c #B2443C",
+"* c #B34E3E",
+"= c #B54E44",
+"- c #B65146",
+"; c #B7584F",
+": c #B8554C",
+"> c #B75A50",
+", c #B95852",
+"< c #B96259",
+"1 c #B89B9B",
+"2 c #BCA0A0",
+"3 c #C1A5A5",
+"4 c gray100",
+"5 c None",
+/* pixels */
+"555555555555555555",
+"55553$$$$$$$#@5555",
+"55552;%&&==;=o5555",
+"55551>&&*=;:=.5555",
+"55551>&*=;::=.5555",
+"55551>*==:::-X5555",
+"55551>==:::,;.5555",
+"55551<==:;,<>.5555",
+"55551<;;;;<<;.5555",
+"55551;-==;;;;X5555",
+"55555+XX..X..O5555",
+"555555555555555555"
+};
+
+const char keywords[]="and and_eq asm auto bitand bitor bool break "
+"case catch char class compl const const_cast continue "
+"default delete do double dynamic_cast else enum explicit export extern false float for "
+"friend goto if inline int long mutable namespace new not not_eq "
+"operator or or_eq private protected public "
+"register reinterpret_cast return short signed sizeof static static_cast struct switch "
+"template this throw true try typedef typeid typename union unsigned using "
+"virtual void volatile wchar_t while xor xor_eq";
+
+pascal OSStatus WindowEventHandler(EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+ HIViewRef sciView = *reinterpret_cast<HIViewRef*>( inUserData );
+ WindowRef window = GetControlOwner(sciView);
+ ScintillaMacOSX* scintilla;
+ GetControlProperty( sciView, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
+ TCarbonEvent event( inEvent );
+
+ // If the window is not active, let the standard window handler execute.
+ if ( ! IsWindowActive( window ) ) return eventNotHandledErr;
+
+ const HIViewRef rootView = HIViewGetRoot( window );
+ assert( rootView != NULL );
+
+ if ( event.GetKind() == kEventMouseDown )
+ {
+ UInt32 inKeyModifiers;
+ event.GetParameter( kEventParamKeyModifiers, &inKeyModifiers );
+
+ EventMouseButton inMouseButton;
+ event.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton );
+ if (inMouseButton == kEventMouseButtonTertiary) {
+ if (inKeyModifiers & optionKey) {
+ const char *test = "\001This is a test calltip This is a test calltip This is a test calltip";
+ scintilla->WndProc( SCI_CALLTIPSHOW, 0, (long int)test );
+ } else {
+ char *list = "test_1?0 test_2 test_3 test_4 test_5 test_6 test_7 test_8 test_9 test_10 test_11 test_12";
+ scintilla->WndProc( SCI_AUTOCSHOW, 0, (long int)list );
+ }
+ return noErr;
+ }
+ }
+
+ return eventNotHandledErr;
+}
+
+int main(int argc, char* argv[])
+{
+ IBNibRef nibRef;
+ WindowRef window;
+
+ OSStatus err;
+
+ // Create a Nib reference passing the name of the nib file (without the .nib extension)
+ // CreateNibReference only searches into the application bundle.
+ err = CreateNibReference(CFSTR("main"), &nibRef);
+ require_noerr( err, CantGetNibRef );
+
+ // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
+ // object. This name is set in InterfaceBuilder when the nib is created.
+ err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
+ require_noerr( err, CantSetMenuBar );
+
+ // Then create a window. "MainWindow" is the name of the window object. This name is set in
+ // InterfaceBuilder when the nib is created.
+ err = CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window);
+ require_noerr( err, CantCreateWindow );
+
+ // We don't need the nib reference anymore.
+ DisposeNibReference(nibRef);
+
+ HIRect boundsRect;
+ // GOOD and BAD methods off embedding into a window. This is used
+ // to test Window::SetPositionRelative under different situations.
+#define GOOD
+#ifdef GOOD
+#ifdef USE_CONTROL
+ ControlRef root;
+ GetRootControl(window, &root);
+#else
+ HIViewRef root;
+ HIViewFindByID(HIViewGetRoot(window),
+ kHIViewWindowContentID,
+ &root);
+#endif
+ HIViewGetBounds(root, &boundsRect);
+
+#else // BAD like mozilla
+ HIViewRef root;
+ root = HIViewGetRoot(window);
+
+ Rect cBounds, sBounds;
+ GetWindowBounds(window, kWindowContentRgn, &cBounds);
+ GetWindowBounds(window, kWindowStructureRgn, &sBounds);
+ boundsRect.origin.x = cBounds.left - sBounds.left;
+ boundsRect.origin.y = cBounds.top - sBounds.top;
+ boundsRect.size.width = cBounds.right - cBounds.left;
+ boundsRect.size.height = cBounds.bottom - cBounds.top;
+#endif
+
+ // get a scintilla control, and add it to it's parent container
+ HIViewRef sciView;
+ sciView = scintilla_new();
+ HIViewAddSubview(root, sciView);
+
+ // some scintilla init
+ ScintillaMacOSX* scintilla;
+ GetControlProperty( sciView, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
+
+ scintilla->WndProc( SCI_SETLEXER, SCLEX_CPP, 0);
+ scintilla->WndProc( SCI_SETSTYLEBITS, 5, 0);
+
+ scintilla->WndProc(SCI_STYLESETFORE, 0, 0x808080); // White space
+ scintilla->WndProc(SCI_STYLESETFORE, 1, 0x007F00); // Comment
+ scintilla->WndProc(SCI_STYLESETITALIC, 1, 1); // Comment
+ scintilla->WndProc(SCI_STYLESETFORE, 2, 0x007F00); // Line comment
+ scintilla->WndProc(SCI_STYLESETITALIC, 2, 1); // Line comment
+ scintilla->WndProc(SCI_STYLESETFORE, 3, 0x3F703F); // Doc comment
+ scintilla->WndProc(SCI_STYLESETITALIC, 3, 1); // Doc comment
+ scintilla->WndProc(SCI_STYLESETFORE, 4, 0x7F7F00); // Number
+ scintilla->WndProc(SCI_STYLESETFORE, 5, 0x7F0000); // Keyword
+ scintilla->WndProc(SCI_STYLESETBOLD, 5, 1); // Keyword
+ scintilla->WndProc(SCI_STYLESETFORE, 6, 0x7F007F); // String
+ scintilla->WndProc(SCI_STYLESETFORE, 7, 0x7F007F); // Character
+ scintilla->WndProc(SCI_STYLESETFORE, 8, 0x804080); // UUID
+ scintilla->WndProc(SCI_STYLESETFORE, 9, 0x007F7F); // Preprocessor
+ scintilla->WndProc(SCI_STYLESETFORE,10, 0x000000); // Operators
+ scintilla->WndProc(SCI_STYLESETBOLD,10, 1); // Operators
+ scintilla->WndProc(SCI_STYLESETFORE,11, 0x000000); // Identifiers
+
+
+ scintilla->WndProc(SCI_SETKEYWORDS, 0, (sptr_t)(char *)keywords); // Keyword
+
+ /*
+ these fail compilation on osx now
+ scintilla->WndProc( SCI_SETPROPERTY, "fold", (long int)"1");
+ scintilla->WndProc( SCI_SETPROPERTY, "fold.compact", (long int)"0");
+ scintilla->WndProc( SCI_SETPROPERTY, "fold.comment", (long int)"1");
+ scintilla->WndProc( SCI_SETPROPERTY, "fold.preprocessor", (long int)"1");
+ */
+
+ scintilla->WndProc( SCI_REGISTERIMAGE, 0, (long int)ac_class);
+
+ scintilla->WndProc( SCI_SETMARGINTYPEN, 0, (long int)SC_MARGIN_NUMBER);
+ scintilla->WndProc( SCI_SETMARGINWIDTHN, 0, (long int)30);
+ scintilla->WndProc( SCI_SETMARGINTYPEN, 1, (long int)SC_MARGIN_SYMBOL);
+ scintilla->WndProc( SCI_SETMARGINMASKN, 1, (long int)SC_MASK_FOLDERS);
+ scintilla->WndProc( SCI_SETMARGINWIDTHN, 1, (long int)20);
+ scintilla->WndProc( SCI_SETMARGINTYPEN, 2, (long int)SC_MARGIN_SYMBOL);
+ scintilla->WndProc( SCI_SETMARGINWIDTHN, 2, (long int)16);
+ //scintilla->WndProc( SCI_SETWRAPMODE, SC_WRAP_WORD, 0);
+ //scintilla->WndProc( SCI_SETWRAPVISUALFLAGS, SC_WRAPVISUALFLAG_END | SC_WRAPVISUALFLAG_START, 0);
+
+ // set the size of scintilla to the size of the container
+ HIViewSetFrame( sciView, &boundsRect );
+
+ // bind the size of scintilla to the size of it's container window
+ HIViewSetLayoutInfo(sciView, &kBindToParentLayout);
+
+ // setup some event handling
+ static const EventTypeSpec kWindowMouseEvents[] =
+ {
+ { kEventClassMouse, kEventMouseDown },
+ };
+
+ InstallEventHandler( GetWindowEventTarget( window ), WindowEventHandler,
+ GetEventTypeCount( kWindowMouseEvents ), kWindowMouseEvents, &sciView, NULL );
+
+ // show scintilla
+ ShowControl(sciView);
+
+ SetAutomaticControlDragTrackingEnabledForWindow(window, true);
+
+ // The window was created hidden so show it.
+ ShowWindow( window );
+
+ // Call the event loop
+ RunApplicationEventLoop();
+
+CantCreateWindow:
+CantSetMenuBar:
+CantGetNibRef:
+ return err;
+}
+
diff --git a/scintilla/macosx/SciTest/version.plist b/scintilla/macosx/SciTest/version.plist
new file mode 100644
index 0000000..ed07389
--- /dev/null
+++ b/scintilla/macosx/SciTest/version.plist
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>BuildVersion</key>
+ <string>92</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>ProductBuildVersion</key>
+ <string>7K571</string>
+ <key>ProjectName</key>
+ <string>NibPBTemplates</string>
+ <key>SourceVersion</key>
+ <string>1200000</string>
+</dict>
+</plist>
diff --git a/scintilla/macosx/ScintillaCallTip.cxx b/scintilla/macosx/ScintillaCallTip.cxx
new file mode 100644
index 0000000..3b87acb
--- /dev/null
+++ b/scintilla/macosx/ScintillaCallTip.cxx
@@ -0,0 +1,117 @@
+
+#include "ScintillaMacOSX.h"
+#include "ScintillaCallTip.h"
+#include "CallTip.h"
+
+using namespace Scintilla;
+
+const CFStringRef ScintillaCallTip::kScintillaCallTipClassID = CFSTR( "org.scintilla.calltip" );
+const ControlKind ScintillaCallTip::kScintillaCallTipKind = { 'ejon', 'Scct' };
+
+ScintillaCallTip::ScintillaCallTip( void* windowid ) :
+ TView( reinterpret_cast<HIViewRef>( windowid ) )
+{
+ ActivateInterface( kMouse );
+ // debugPrint = true;
+}
+
+void ScintillaCallTip::Draw(
+ RgnHandle /*inLimitRgn*/,
+ CGContextRef inContext )
+{
+ // Get a reference to the Scintilla C++ object
+ CallTip* ctip = NULL;
+ OSStatus err;
+ err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip );
+ assert(err == noErr);
+ if (ctip == NULL) return;
+
+ Rect contentBounds;
+ GetControlBounds(GetViewRef(), &contentBounds);
+
+ HIRect controlFrame;
+ HIViewGetFrame( GetViewRef(), &controlFrame );
+
+ // what is the global pos?
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(inContext, GetViewRef());
+ ctip->PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+
+}
+
+ControlPartCode ScintillaCallTip::HitTest( const HIPoint& where )
+{
+ if ( CGRectContainsPoint( Bounds(), where ) )
+ return 1;
+ else
+ return kControlNoPart;
+}
+
+OSStatus ScintillaCallTip::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ CallTip* ctip = NULL;
+ ScintillaMacOSX *sciThis = NULL;
+ OSStatus err = GetControlProperty( GetViewRef(), scintillaCallTipType, 0, sizeof( ctip ), NULL, &ctip );
+ err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis );
+ ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ));
+ sciThis->CallTipClick();
+ return noErr;
+}
+
+OSStatus ScintillaCallTip::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ return noErr;
+}
+
+OSStatus ScintillaCallTip::MouseDragged( HIPoint& location, UInt32 /*modifiers*/, EventMouseButton /*button*/, UInt32 /*clickCount*/ )
+{
+ SetThemeCursor( kThemeArrowCursor );
+ return noErr;
+}
+
+HIViewRef ScintillaCallTip::Create()
+{
+ // Register the HIView, if needed
+ static bool registered = false;
+
+ if ( not registered )
+ {
+ TView::RegisterSubclass( kScintillaCallTipClassID, Construct );
+ registered = true;
+ }
+
+ OSStatus err = noErr;
+ EventRef event = CreateInitializationEvent();
+ assert( event != NULL );
+
+ HIViewRef control = NULL;
+ err = HIObjectCreate( kScintillaCallTipClassID, event, reinterpret_cast<HIObjectRef*>( &control ) );
+ ReleaseEvent( event );
+ if ( err == noErr ) {
+ Platform::DebugPrintf("ScintillaCallTip::Create control %08X\n",control);
+ return control;
+ }
+ return NULL;
+}
+
+OSStatus ScintillaCallTip::Construct( HIViewRef inControl, TView** outView )
+{
+ *outView = new ScintillaCallTip( inControl );
+ Platform::DebugPrintf("ScintillaCallTip::Construct scintilla %08X\n",*outView);
+ if ( *outView != NULL )
+ return noErr;
+ else
+ return memFullErr;
+}
+
+extern "C" {
+HIViewRef scintilla_calltip_new() {
+ return ScintillaCallTip::Create();
+}
+}
diff --git a/scintilla/macosx/ScintillaCallTip.h b/scintilla/macosx/ScintillaCallTip.h
new file mode 100644
index 0000000..0d8526b
--- /dev/null
+++ b/scintilla/macosx/ScintillaCallTip.h
@@ -0,0 +1,64 @@
+/*
+ * ScintillaMacOSX.h
+ * tutorial
+ *
+ * Created by Evan Jones on Sun Sep 01 2002.
+ * Copyright (c) 2002 __MyCompanyName__. All rights reserved.
+ *
+ */
+#ifndef SCINTILLA_CALLTIP_H
+#define SCINTILLA_CALLTIP_H
+
+#include "TView.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+static const OSType scintillaCallTipType = 'Scct';
+
+namespace Scintilla {
+
+class ScintillaCallTip : public TView
+{
+public:
+ // Private so ScintillaCallTip objects can not be copied
+ ScintillaCallTip(const ScintillaCallTip &) : TView( NULL ) {}
+ ScintillaCallTip &operator=(const ScintillaCallTip &) { return * this; }
+ ~ScintillaCallTip() {};
+
+public:
+ /** This is the class ID that we've assigned to Scintilla. */
+ static const CFStringRef kScintillaCallTipClassID;
+ static const ControlKind kScintillaCallTipKind;
+
+ ScintillaCallTip( void* windowid );
+
+ /** Returns the HIView object kind, needed to subclass TView. */
+ virtual ControlKind GetKind() { return kScintillaCallTipKind; }
+
+private:
+
+ virtual ControlPartCode HitTest( const HIPoint& where );
+ virtual void Draw( RgnHandle rgn, CGContextRef gc );
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+
+public:
+ static HIViewRef Create();
+private:
+ static OSStatus Construct( HIViewRef inControl, TView** outView );
+
+};
+
+
+}
+
+
+#endif
diff --git a/scintilla/macosx/ScintillaListBox.cxx b/scintilla/macosx/ScintillaListBox.cxx
new file mode 100644
index 0000000..431e4b4
--- /dev/null
+++ b/scintilla/macosx/ScintillaListBox.cxx
@@ -0,0 +1,103 @@
+
+#include "ScintillaMacOSX.h"
+#include "ScintillaListBox.h"
+
+using namespace Scintilla;
+
+const CFStringRef ScintillaListBox::kScintillaListBoxClassID = CFSTR( "org.scintilla.listbox" );
+const ControlKind ScintillaListBox::kScintillaListBoxKind = { 'ejon', 'Sclb' };
+
+ScintillaListBox::ScintillaListBox( void* windowid ) :
+ TView( reinterpret_cast<HIViewRef>( windowid ) )
+{
+ ActivateInterface( kMouse );
+ // debugPrint = true;
+}
+
+void ScintillaListBox::Draw(
+ RgnHandle /*inLimitRgn*/,
+ CGContextRef inContext )
+{
+ Rect contentBounds;
+ GetControlBounds(GetViewRef(), &contentBounds);
+
+ HIRect controlFrame;
+ HIViewGetFrame( GetViewRef(), &controlFrame );
+
+ // what is the global pos?
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(inContext, GetViewRef());
+ ctip->PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+
+}
+
+ControlPartCode ScintillaListBox::HitTest( const HIPoint& where )
+{
+ if ( CGRectContainsPoint( Bounds(), where ) )
+ return 1;
+ else
+ return kControlNoPart;
+}
+
+OSStatus ScintillaListBox::MouseDown(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ ListBox* ctip = NULL;
+ ScintillaMacOSX *sciThis = NULL;
+ OSStatus err = GetControlProperty( GetViewRef(), scintillaListBoxType, 0, sizeof( ctip ), NULL, &ctip );
+ err = GetControlProperty( GetViewRef(), scintillaMacOSType, 0, sizeof( sciThis ), NULL, &sciThis );
+ ctip->MouseClick( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ));
+ sciThis->ListBoxClick();
+ return noErr;
+}
+
+OSStatus ScintillaListBox::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton button, UInt32 /*inClickCount*/ )
+{
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ return noErr;
+}
+
+HIViewRef ScintillaListBox::Create()
+{
+ // Register the HIView, if needed
+ static bool registered = false;
+
+ if ( not registered )
+ {
+ TView::RegisterSubclass( kScintillaListBoxClassID, Construct );
+ registered = true;
+ }
+
+ OSStatus err = noErr;
+ EventRef event = CreateInitializationEvent();
+ assert( event != NULL );
+
+ HIViewRef control = NULL;
+ err = HIObjectCreate( kScintillaListBoxClassID, event, reinterpret_cast<HIObjectRef*>( &control ) );
+ ReleaseEvent( event );
+ if ( err == noErr ) {
+ Platform::DebugPrintf("ScintillaListBox::Create control %08X\n",control);
+ return control;
+ }
+ return NULL;
+}
+
+OSStatus ScintillaListBox::Construct( HIViewRef inControl, TView** outView )
+{
+ *outView = new ScintillaListBox( inControl );
+ Platform::DebugPrintf("ScintillaListBox::Construct scintilla %08X\n",*outView);
+ if ( *outView != NULL )
+ return noErr;
+ else
+ return memFullErr;
+}
+
+extern "C" {
+HIViewRef scintilla_listbox_new() {
+ return ScintillaListBox::Create();
+}
+}
diff --git a/scintilla/macosx/ScintillaListBox.h b/scintilla/macosx/ScintillaListBox.h
new file mode 100644
index 0000000..a8582c2
--- /dev/null
+++ b/scintilla/macosx/ScintillaListBox.h
@@ -0,0 +1,63 @@
+/*
+ * ScintillaMacOSX.h
+ * tutorial
+ *
+ * Created by Evan Jones on Sun Sep 01 2002.
+ * Copyright (c) 2002 __MyCompanyName__. All rights reserved.
+ *
+ */
+#ifndef SCINTILLA_LISTBOX_H
+#define SCINTILLA_LISTBOX_H
+
+#include "TView.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "Platform.h"
+#include "Scintilla.h"
+
+static const OSType scintillaListBoxType = 'sclb';
+
+namespace Scintilla {
+
+class ScintillaListBox : public TView
+{
+public:
+ // Private so ScintillaListBox objects can not be copied
+ ScintillaListBox(const ScintillaListBox &) : TView( NULL ) {}
+ ScintillaListBox &operator=(const ScintillaListBox &) { return * this; }
+ ~ScintillaListBox() {};
+
+public:
+ /** This is the class ID that we've assigned to Scintilla. */
+ static const CFStringRef kScintillaListBoxClassID;
+ static const ControlKind kScintillaListBoxKind;
+
+ ScintillaListBox( void* windowid );
+
+ /** Returns the HIView object kind, needed to subclass TView. */
+ virtual ControlKind GetKind() { return kScintillaListBoxKind; }
+
+private:
+
+ virtual ControlPartCode HitTest( const HIPoint& where );
+ virtual void Draw( RgnHandle rgn, CGContextRef gc );
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+
+public:
+ static HIViewRef Create();
+private:
+ static OSStatus Construct( HIViewRef inControl, TView** outView );
+
+};
+
+
+}
+
+
+#endif
diff --git a/scintilla/macosx/ScintillaMacOSX.cxx b/scintilla/macosx/ScintillaMacOSX.cxx
new file mode 100644
index 0000000..e4f2f8c
--- /dev/null
+++ b/scintilla/macosx/ScintillaMacOSX.cxx
@@ -0,0 +1,2242 @@
+// Scintilla source code edit control
+// ScintillaMacOSX.cxx - Mac OS X subclass of ScintillaBase
+// Copyright 2003 by Evan Jones <ejones@uwaterloo.ca>
+// Based on ScintillaGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+
+#include "ScintillaMacOSX.h"
+#ifdef EXT_INPUT
+// External Input Editor
+#include "ExtInput.h"
+#else
+#include "UniConversion.h"
+#endif
+
+using namespace Scintilla;
+
+const CFStringRef ScintillaMacOSX::kScintillaClassID = CFSTR( "org.scintilla.scintilla" );
+const ControlKind ScintillaMacOSX::kScintillaKind = { 'ejon', 'Scin' };
+
+extern "C" HIViewRef scintilla_calltip_new(void);
+
+#ifndef WM_UNICHAR
+#define WM_UNICHAR 0x0109
+#endif
+
+// required for paste/dragdrop, see comment in paste function below
+static int BOMlen(unsigned char *cstr) {
+ switch(cstr[0]) {
+ case 0xEF: // BOM_UTF8
+ if (cstr[1] == 0xBB && cstr[2] == 0xBF) {
+ return 3;
+ }
+ break;
+ case 0xFE:
+ if (cstr[1] == 0xFF) {
+ if (cstr[2] == 0x00 && cstr[3] == 0x00) {
+ return 4;
+ }
+ return 2;
+ }
+ break;
+ case 0xFF:
+ if (cstr[1] == 0xFE) {
+ if (cstr[2] == 0x00 && cstr[3] == 0x00) {
+ return 4;
+ }
+ return 2;
+ }
+ break;
+ case 0x00:
+ if (cstr[1] == 0x00) {
+ if (cstr[2] == 0xFE && cstr[3] == 0xFF) {
+ return 4;
+ }
+ if (cstr[2] == 0xFF && cstr[3] == 0xFE) {
+ return 4;
+ }
+ return 2;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef EXT_INPUT
+#define SCI_CMD ( SCI_ALT | SCI_CTRL | SCI_SHIFT)
+
+static const KeyToCommand macMapDefault[] = {
+ {SCK_DOWN, SCI_CMD, SCI_DOCUMENTEND},
+ {SCK_UP, SCI_CMD, SCI_DOCUMENTSTART},
+ {SCK_LEFT, SCI_CMD, SCI_VCHOME},
+ {SCK_RIGHT, SCI_CMD, SCI_LINEEND},
+ {SCK_DOWN, SCI_NORM, SCI_LINEDOWN},
+ {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
+ {SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN},
+ {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
+ {SCK_UP, SCI_NORM, SCI_LINEUP},
+ {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
+ {SCK_UP, SCI_CTRL, SCI_LINESCROLLUP},
+ {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
+ {'[', SCI_CTRL, SCI_PARAUP},
+ {'[', SCI_CSHIFT, SCI_PARAUPEXTEND},
+ {']', SCI_CTRL, SCI_PARADOWN},
+ {']', SCI_CSHIFT, SCI_PARADOWNEXTEND},
+ {SCK_LEFT, SCI_NORM, SCI_CHARLEFT},
+ {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
+ {SCK_LEFT, SCI_ALT, SCI_WORDLEFT},
+ {SCK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND},
+ {SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND},
+ {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
+ {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
+ {SCK_RIGHT, SCI_ALT, SCI_WORDRIGHT},
+ {SCK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND},
+ {SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND},
+ {'/', SCI_CTRL, SCI_WORDPARTLEFT},
+ {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
+ {'\\', SCI_CTRL, SCI_WORDPARTRIGHT},
+ {'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
+ {SCK_HOME, SCI_NORM, SCI_VCHOME},
+ {SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
+ {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
+ {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
+ {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY},
+// {SCK_HOME, SCI_ASHIFT, SCI_HOMEDISPLAYEXTEND},
+ {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
+ {SCK_END, SCI_NORM, SCI_LINEEND},
+ {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
+ {SCK_END, SCI_CTRL, SCI_DOCUMENTEND},
+ {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
+ {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY},
+// {SCK_END, SCI_ASHIFT, SCI_LINEENDDISPLAYEXTEND},
+ {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
+ {SCK_PRIOR, SCI_NORM, SCI_PAGEUP},
+ {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
+ {SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
+ {SCK_NEXT, SCI_NORM, SCI_PAGEDOWN},
+ {SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
+ {SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
+ {SCK_DELETE, SCI_NORM, SCI_CLEAR},
+ {SCK_DELETE, SCI_SHIFT, SCI_CUT},
+ {SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
+ {SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT},
+ {SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
+ {SCK_INSERT, SCI_SHIFT, SCI_PASTE},
+ {SCK_INSERT, SCI_CTRL, SCI_COPY},
+ {SCK_ESCAPE, SCI_NORM, SCI_CANCEL},
+ {SCK_BACK, SCI_NORM, SCI_DELETEBACK},
+ {SCK_BACK, SCI_SHIFT, SCI_DELETEBACK},
+ {SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
+ {SCK_BACK, SCI_ALT, SCI_UNDO},
+ {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT},
+ {'Z', SCI_CTRL, SCI_UNDO},
+ {'Y', SCI_CTRL, SCI_REDO},
+ {'X', SCI_CTRL, SCI_CUT},
+ {'C', SCI_CTRL, SCI_COPY},
+ {'V', SCI_CTRL, SCI_PASTE},
+ {'A', SCI_CTRL, SCI_SELECTALL},
+ {SCK_TAB, SCI_NORM, SCI_TAB},
+ {SCK_TAB, SCI_SHIFT, SCI_BACKTAB},
+ {SCK_RETURN, SCI_NORM, SCI_NEWLINE},
+ {SCK_RETURN, SCI_SHIFT, SCI_NEWLINE},
+ {SCK_ADD, SCI_CTRL, SCI_ZOOMIN},
+ {SCK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT},
+ {SCK_DIVIDE, SCI_CTRL, SCI_SETZOOM},
+ //'L', SCI_CTRL, SCI_FORMFEED,
+ {'L', SCI_CTRL, SCI_LINECUT},
+ {'L', SCI_CSHIFT, SCI_LINEDELETE},
+ {'T', SCI_CSHIFT, SCI_LINECOPY},
+ {'T', SCI_CTRL, SCI_LINETRANSPOSE},
+ {'D', SCI_CTRL, SCI_SELECTIONDUPLICATE},
+ {'U', SCI_CTRL, SCI_LOWERCASE},
+ {'U', SCI_CSHIFT, SCI_UPPERCASE},
+ {0,0,0},
+};
+#endif
+
+ScintillaMacOSX::ScintillaMacOSX( void* windowid ) :
+ TView( reinterpret_cast<HIViewRef>( windowid ) )
+{
+ notifyObj = NULL;
+ notifyProc = NULL;
+ wMain = windowid;
+ OSStatus err;
+ err = GetThemeMetric( kThemeMetricScrollBarWidth, &scrollBarFixedSize );
+ assert( err == noErr );
+
+ mouseTrackingRef = NULL;
+ mouseTrackingID.signature = scintillaMacOSType;
+ mouseTrackingID.id = (SInt32)this;
+ capturedMouse = false;
+
+ // Enable keyboard events and mouse events
+#if !defined(CONTAINER_HANDLES_EVENTS)
+ ActivateInterface( kKeyboardFocus );
+ ActivateInterface( kMouse );
+ ActivateInterface( kDragAndDrop );
+#endif
+ ActivateInterface( kMouseTracking );
+
+ Initialise();
+
+ // Create some bounds rectangle which will just get reset to the correct rectangle later
+ Rect tempScrollRect;
+ tempScrollRect.top = -1;
+ tempScrollRect.left = 400;
+ tempScrollRect.bottom = 300;
+ tempScrollRect.right = 450;
+
+ // Create the scroll bar with fake values that will get set correctly later
+ err = CreateScrollBarControl( this->GetOwner(), &tempScrollRect, 0, 0, 100, 100, true, LiveScrollHandler, &vScrollBar );
+ assert( vScrollBar != NULL && err == noErr );
+ err = CreateScrollBarControl( this->GetOwner(), &tempScrollRect, 0, 0, 100, 100, true, LiveScrollHandler, &hScrollBar );
+ assert( hScrollBar != NULL && err == noErr );
+
+ // Set a property on the scrollbars to store a pointer to the Scintilla object
+ ScintillaMacOSX* objectPtr = this;
+ err = SetControlProperty( vScrollBar, scintillaMacOSType, 0, sizeof( this ), &objectPtr );
+ assert( err == noErr );
+ err = SetControlProperty( hScrollBar, scintillaMacOSType, 0, sizeof( this ), &objectPtr );
+ assert( err == noErr );
+
+ // set this into our parent control so we can be retrieved easily at a later time
+ // (see scintilla_send below)
+ err = SetControlProperty( reinterpret_cast<HIViewRef>( windowid ), scintillaMacOSType, 0, sizeof( this ), &objectPtr );
+ assert( err == noErr );
+
+ // Tell Scintilla not to buffer: Quartz buffers drawing for us
+ // TODO: Can we disable this option on Mac OS X?
+ WndProc( SCI_SETBUFFEREDDRAW, 0, 0 );
+ // Turn on UniCode mode
+ WndProc( SCI_SETCODEPAGE, SC_CP_UTF8, 0 );
+
+ const EventTypeSpec commandEventInfo[] = {
+ { kEventClassCommand, kEventProcessCommand },
+ { kEventClassCommand, kEventCommandUpdateStatus },
+ };
+
+ err = InstallEventHandler( GetControlEventTarget( reinterpret_cast<HIViewRef>( windowid ) ),
+ CommandEventHandler,
+ GetEventTypeCount( commandEventInfo ),
+ commandEventInfo,
+ this, NULL);
+#ifdef EXT_INPUT
+ ExtInput::attach (GetViewRef());
+ for (int i = 0; macMapDefault[i].key; i++)
+ {
+ this->kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg);
+ }
+#endif
+}
+
+ScintillaMacOSX::~ScintillaMacOSX() {
+ // If the window is closed and the timer is not removed,
+ // A segment violation will occur when it attempts to fire the timer next.
+ if ( mouseTrackingRef != NULL ) {
+ ReleaseMouseTrackingRegion(mouseTrackingRef);
+ }
+ mouseTrackingRef = NULL;
+ SetTicking(false);
+#ifdef EXT_INPUT
+ ExtInput::detach (GetViewRef());
+#endif
+}
+
+void ScintillaMacOSX::Initialise() {
+ // TODO: Do anything here? Maybe this stuff should be here instead of the constructor?
+}
+
+void ScintillaMacOSX::Finalise() {
+ SetTicking(false);
+ ScintillaBase::Finalise();
+}
+
+// --------------------------------------------------------------------------------------------------------------
+//
+// IsDropInFinderTrash - Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash.
+//
+#pragma segment Drag
+
+Boolean IsDropInFinderTrash(AEDesc *dropLocation)
+{
+ OSErr result;
+ AEDesc dropSpec;
+ FSSpec *theSpec;
+ CInfoPBRec thePB;
+ short trashVRefNum;
+ long trashDirID;
+
+ // Coerce the dropLocation descriptor into an FSSpec. If there's no dropLocation or
+ // it can't be coerced into an FSSpec, then it couldn't have been the Trash.
+
+ if ((dropLocation->descriptorType != typeNull) &&
+ (AECoerceDesc(dropLocation, typeFSS, &dropSpec) == noErr))
+ {
+ unsigned char flags = HGetState((Handle)dropSpec.dataHandle);
+
+ HLock((Handle)dropSpec.dataHandle);
+ theSpec = (FSSpec *) *dropSpec.dataHandle;
+
+ // Get the directory ID of the given dropLocation object.
+
+ thePB.dirInfo.ioCompletion = 0L;
+ thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name;
+ thePB.dirInfo.ioVRefNum = theSpec->vRefNum;
+ thePB.dirInfo.ioFDirIndex = 0;
+ thePB.dirInfo.ioDrDirID = theSpec->parID;
+
+ result = PBGetCatInfoSync(&thePB);
+
+ HSetState((Handle)dropSpec.dataHandle, flags);
+ AEDisposeDesc(&dropSpec);
+
+ if (result != noErr)
+ return false;
+
+ // If the result is not a directory, it must not be the Trash.
+
+ if (!(thePB.dirInfo.ioFlAttrib & (1 << 4)))
+ return false;
+
+ // Get information about the Trash folder.
+
+ FindFolder(theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID);
+
+ // If the directory ID of the dropLocation object is the same as the directory ID
+ // returned by FindFolder, then the drop must have occurred into the Trash.
+
+ if (thePB.dirInfo.ioDrDirID == trashDirID)
+ return true;
+ }
+
+ return false;
+
+} // IsDropInFinderTrash
+
+HIPoint ScintillaMacOSX::GetLocalPoint(::Point pt)
+{
+ // get the mouse position so we can offset it
+ Rect bounds;
+ GetWindowBounds( GetOwner(), kWindowStructureRgn, &bounds );
+
+ PRectangle hbounds = wMain.GetPosition();
+ HIViewRef parent = HIViewGetSuperview(GetViewRef());
+ Rect pbounds;
+ GetControlBounds(parent, &pbounds);
+
+ bounds.left += pbounds.left + hbounds.left;
+ bounds.top += pbounds.top + hbounds.top;
+
+ HIPoint offset = { pt.h - bounds.left, pt.v - bounds.top };
+ return offset;
+}
+
+void ScintillaMacOSX::StartDrag() {
+ if (sel.Empty()) return;
+
+ // calculate the bounds of the selection
+ PRectangle client = GetTextRectangle();
+ int selStart = sel.RangeMain().Start().Position();
+ int selEnd = sel.RangeMain().End().Position();
+ int startLine = pdoc->LineFromPosition(selStart);
+ int endLine = pdoc->LineFromPosition(selEnd);
+ Point pt;
+ int startPos, endPos, ep;
+ Rect rcSel;
+ rcSel.top = rcSel.bottom = rcSel.right = rcSel.left = -1;
+ for (int l = startLine; l <= endLine; l++) {
+ startPos = WndProc(SCI_GETLINESELSTARTPOSITION, l, 0);
+ endPos = WndProc(SCI_GETLINESELENDPOSITION, l, 0);
+ if (endPos == startPos) continue;
+ // step back a position if we're counting the newline
+ ep = WndProc(SCI_GETLINEENDPOSITION, l, 0);
+ if (endPos > ep) endPos = ep;
+
+ pt = LocationFromPosition(startPos); // top left of line selection
+ if (pt.x < rcSel.left || rcSel.left < 0) rcSel.left = pt.x;
+ if (pt.y < rcSel.top || rcSel.top < 0) rcSel.top = pt.y;
+
+ pt = LocationFromPosition(endPos); // top right of line selection
+ pt.y += vs.lineHeight; // get to the bottom of the line
+ if (pt.x > rcSel.right || rcSel.right < 0) {
+ if (pt.x > client.right)
+ rcSel.right = client.right;
+ else
+ rcSel.right = pt.x;
+ }
+ if (pt.y > rcSel.bottom || rcSel.bottom < 0) {
+ if (pt.y > client.bottom)
+ rcSel.bottom = client.bottom;
+ else
+ rcSel.bottom = pt.y;
+ }
+ }
+
+ // must convert to global coordinates for drag regions, but also save the
+ // image rectangle for further calculations and copy operations
+ PRectangle imageRect = PRectangle(rcSel.left, rcSel.top, rcSel.right, rcSel.bottom);
+ QDLocalToGlobalRect(GetWindowPort(GetOwner()), &rcSel);
+
+ // get the mouse position so we can offset it
+ HIPoint offset = GetLocalPoint(mouseDownEvent.where);
+ offset.y = (imageRect.top * 1.0) - offset.y;
+ offset.x = (imageRect.left * 1.0) - offset.x;
+
+ // to get a bitmap of the text we're dragging, we just use Paint on a
+ // pixmap surface.
+ SurfaceImpl *sw = new SurfaceImpl();
+ SurfaceImpl *pixmap = NULL;
+
+ if (sw) {
+ pixmap = new SurfaceImpl();
+ if (pixmap) {
+ client = GetClientRectangle();
+ paintState = painting;
+ sw->InitPixMap( client.Width(), client.Height(), NULL, NULL );
+ paintingAllText = true;
+ Paint(sw, imageRect);
+ paintState = notPainting;
+
+ pixmap->InitPixMap( imageRect.Width(), imageRect.Height(), NULL, NULL );
+
+ CGContextRef gc = pixmap->GetContext();
+
+ // to make Paint() work on a bitmap, we have to flip our coordinates
+ // and translate the origin
+ //fprintf(stderr, "translate to %d\n", client.Height() );
+ CGContextTranslateCTM(gc, 0, imageRect.Height());
+ CGContextScaleCTM(gc, 1.0, -1.0);
+
+ pixmap->CopyImageRectangle( *sw, imageRect, PRectangle( 0, 0, imageRect.Width(), imageRect.Height() ));
+ // XXX TODO: overwrite any part of the image that is not part of the
+ // selection to make it transparent. right now we just use
+ // the full rectangle which may include non-selected text.
+ }
+ sw->Release();
+ delete sw;
+ }
+
+ // now we initiate the drag session
+
+ RgnHandle dragRegion = NewRgn();
+ RgnHandle tempRegion;
+ DragRef inDrag;
+ DragAttributes attributes;
+ AEDesc dropLocation;
+ SInt16 mouseDownModifiers, mouseUpModifiers;
+ bool copyText;
+ CGImageRef image = NULL;
+
+ RectRgn(dragRegion, &rcSel);
+
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ PasteboardRef theClipboard;
+ SetPasteboardData(theClipboard, selectedText);
+ NewDragWithPasteboard( theClipboard, &inDrag);
+ CFRelease( theClipboard );
+
+ // Set the item's bounding rectangle in global coordinates.
+ SetDragItemBounds(inDrag, 1, &rcSel);
+
+ // Prepare the drag region.
+ tempRegion = NewRgn();
+ CopyRgn(dragRegion, tempRegion);
+ InsetRgn(tempRegion, 1, 1);
+ DiffRgn(dragRegion, tempRegion, dragRegion);
+ DisposeRgn(tempRegion);
+
+ // if we have a pixmap, lets use that
+ if (pixmap) {
+ image = pixmap->GetImage();
+ SetDragImageWithCGImage (inDrag, image, &offset, kDragStandardTranslucency);
+ }
+
+ // Drag the text. TrackDrag will return userCanceledErr if the drop whooshed back for any reason.
+ inDragDrop = ddDragging;
+ OSErr error = TrackDrag(inDrag, &mouseDownEvent, dragRegion);
+ inDragDrop = ddNone;
+
+ // Check to see if the drop occurred in the Finder's Trash. If the drop occurred
+ // in the Finder's Trash and a copy operation wasn't specified, delete the
+ // source selection. Note that we can continute to get the attributes, drop location
+ // modifiers, etc. of the drag until we dispose of it using DisposeDrag.
+ if (error == noErr) {
+ GetDragAttributes(inDrag, &attributes);
+ if (!(attributes & kDragInsideSenderApplication))
+ {
+ GetDropLocation(inDrag, &dropLocation);
+
+ GetDragModifiers(inDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
+ copyText = (mouseDownModifiers | mouseUpModifiers) & optionKey;
+
+ if ((!copyText) && (IsDropInFinderTrash(&dropLocation)))
+ {
+ // delete the selected text from the buffer
+ ClearSelection();
+ }
+
+ AEDisposeDesc(&dropLocation);
+ }
+ }
+
+ // Dispose of this drag, 'cause we're done.
+ DisposeDrag(inDrag);
+ DisposeRgn(dragRegion);
+
+ if (pixmap) {
+ CGImageRelease(image);
+ pixmap->Release();
+ delete pixmap;
+ }
+}
+
+void ScintillaMacOSX::SetDragCursor(DragRef inDrag)
+{
+ DragAttributes attributes;
+ SInt16 modifiers = 0;
+ ThemeCursor cursor = kThemeCopyArrowCursor;
+ GetDragAttributes( inDrag, &attributes );
+
+ if ( attributes & kDragInsideSenderWindow ) {
+ GetDragModifiers(inDrag, &modifiers, NULL, NULL);
+ switch (modifiers & ~btnState) // Filter out btnState (on for drop)
+ {
+ case optionKey:
+ // it's a copy, leave it as a copy arrow
+ break;
+
+ case cmdKey:
+ case cmdKey | optionKey:
+ default:
+ // what to do with these? rectangular drag?
+ cursor = kThemeArrowCursor;
+ break;
+ }
+ }
+ SetThemeCursor(cursor);
+}
+
+bool ScintillaMacOSX::DragEnter(DragRef inDrag )
+{
+ if (!DragWithin(inDrag))
+ return false;
+
+ DragAttributes attributes;
+ GetDragAttributes( inDrag, &attributes );
+
+ // only show the drag hilight if the drag has left the sender window per HI spec
+ if( attributes & kDragHasLeftSenderWindow )
+ {
+ HIRect textFrame;
+ RgnHandle hiliteRgn = NewRgn();
+
+ // get the text view's frame ...
+ HIViewGetFrame( GetViewRef(), &textFrame );
+
+ // ... and convert it into a region for ShowDragHilite
+ HIShapeRef textShape = HIShapeCreateWithRect( &textFrame );
+ HIShapeGetAsQDRgn( textShape, hiliteRgn );
+ CFRelease( textShape );
+
+ // add the drag hilight to the inside of the text view
+ ShowDragHilite( inDrag, hiliteRgn, true );
+
+ DisposeRgn( hiliteRgn );
+ }
+ SetDragCursor(inDrag);
+ return true;
+}
+
+Scintilla::Point ScintillaMacOSX::GetDragPoint(DragRef inDrag)
+{
+ ::Point mouse, globalMouse;
+ GetDragMouse(inDrag, &mouse, &globalMouse);
+ HIPoint hiPoint = GetLocalPoint (globalMouse);
+ return Point(static_cast<int>(hiPoint.x), static_cast<int>(hiPoint.y));
+}
+
+
+void ScintillaMacOSX::DragScroll()
+{
+#define RESET_SCROLL_TIMER(lines) \
+ scrollSpeed = (lines); \
+ scrollTicks = 2000;
+
+ if (!posDrag.IsValid()) {
+ RESET_SCROLL_TIMER(1);
+ return;
+ }
+ Point dragMouse = LocationFromPosition(posDrag);
+ int line = pdoc->LineFromPosition(posDrag.Position());
+ int currentVisibleLine = cs.DisplayFromDoc(line);
+ int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen() - 1, pdoc->LinesTotal() - 1);
+
+ if (currentVisibleLine <= topLine && topLine > 0) {
+ ScrollTo( topLine - scrollSpeed );
+ } else if (currentVisibleLine >= lastVisibleLine) {
+ ScrollTo( topLine + scrollSpeed );
+ } else {
+ RESET_SCROLL_TIMER(1);
+ return;
+ }
+ if (scrollSpeed == 1) {
+ scrollTicks -= timer.tickSize;
+ if (scrollTicks <= 0) {
+ RESET_SCROLL_TIMER(5);
+ }
+ }
+
+ SetDragPosition(SPositionFromLocation(dragMouse));
+
+#undef RESET_SCROLL_TIMER
+}
+
+bool ScintillaMacOSX::DragWithin(DragRef inDrag )
+{
+ PasteboardRef pasteBoard;
+ bool isFileURL = false;
+ if (!GetDragData(inDrag, pasteBoard, NULL, &isFileURL)) {
+ return false;
+ }
+
+ Point pt = GetDragPoint (inDrag);
+ SetDragPosition(SPositionFromLocation(pt));
+ SetDragCursor(inDrag);
+
+ return true;
+}
+
+bool ScintillaMacOSX::DragLeave(DragRef inDrag )
+{
+ HideDragHilite( inDrag );
+ SetDragPosition(SelectionPosition(invalidPosition));
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ return true;
+}
+
+enum
+{
+ kFormatBad,
+ kFormatText,
+ kFormatUnicode,
+ kFormatUTF8,
+ kFormatFile
+};
+
+bool ScintillaMacOSX::GetDragData(DragRef inDrag, PasteboardRef &pasteBoard,
+ SelectionText *selectedText, bool *isFileURL)
+{
+ // TODO: add support for special flavors: flavorTypeHFS and flavorTypePromiseHFS so we
+ // can handle files being dropped on the editor
+ OSStatus status;
+ status = GetDragPasteboard(inDrag, &pasteBoard);
+ if (status != noErr) {
+ return false;
+ }
+ return GetPasteboardData(pasteBoard, selectedText, isFileURL);
+}
+
+void ScintillaMacOSX::SetPasteboardData(PasteboardRef &theClipboard, const SelectionText &selectedText)
+{
+ if (selectedText.len == 0)
+ return;
+
+ CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman);
+
+ // Create a CFString from the ASCII/UTF8 data, convert it to UTF16
+ CFStringRef string = CFStringCreateWithBytes( NULL, reinterpret_cast<UInt8*>( selectedText.s ), selectedText.len - 1, encoding, false );
+
+ PasteboardCreate( kPasteboardClipboard, &theClipboard );
+ PasteboardClear( theClipboard );
+
+ CFDataRef data = NULL;
+ if (selectedText.rectangular) {
+ // This is specific to scintilla, allows us to drag rectangular selections
+ // around the document
+ data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingUnicode, 0 );
+ if (data) {
+ PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1,
+ CFSTR("com.scintilla.utf16-plain-text.rectangular"),
+ data, 0 );
+ CFRelease(data);
+ }
+ }
+ data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingUnicode, 0 );
+ if (data) {
+ PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1,
+ CFSTR("public.utf16-plain-text"),
+ data, 0 );
+ CFRelease(data);
+ data = NULL;
+ }
+ data = CFStringCreateExternalRepresentation ( kCFAllocatorDefault, string, kCFStringEncodingMacRoman, 0 );
+ if (data) {
+ PasteboardPutItemFlavor( theClipboard, (PasteboardItemID)1,
+ CFSTR("com.apple.traditional-mac-plain-text"),
+ data, 0 );
+ CFRelease(data);
+ data = NULL;
+ }
+ CFRelease(string);
+}
+
+bool ScintillaMacOSX::GetPasteboardData(PasteboardRef &pasteBoard,
+ SelectionText *selectedText,
+ bool *isFileURL)
+{
+ // how many items in the pasteboard?
+ CFDataRef data;
+ CFStringRef textString = NULL;
+ bool isRectangular = selectedText ? selectedText->rectangular : false;
+ ItemCount i, itemCount;
+ OSStatus status = PasteboardGetItemCount(pasteBoard, &itemCount);
+ if (status != noErr) {
+ return false;
+ }
+
+ // as long as we didn't get our text, let's loop on the items. We stop as soon as we get it
+ CFArrayRef flavorTypeArray = NULL;
+ bool haveMatch = false;
+ for (i = 1; i <= itemCount; i++)
+ {
+ PasteboardItemID itemID;
+ CFIndex j, flavorCount = 0;
+
+ status = PasteboardGetItemIdentifier(pasteBoard, i, &itemID);
+ if (status != noErr) {
+ return false;
+ }
+
+ // how many flavors in this item?
+ status = PasteboardCopyItemFlavors(pasteBoard, itemID, &flavorTypeArray);
+ if (status != noErr) {
+ return false;
+ }
+
+ if (flavorTypeArray != NULL)
+ flavorCount = CFArrayGetCount(flavorTypeArray);
+
+ // as long as we didn't get our text, let's loop on the flavors. We stop as soon as we get it
+ for(j = 0; j < flavorCount; j++)
+ {
+ CFDataRef flavorData;
+ CFStringRef flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, j);
+ if (flavorType != NULL)
+ {
+ int format = kFormatBad;
+ if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) {
+ format = kFormatFile;
+ *isFileURL = true;
+ }
+ else if (UTTypeConformsTo(flavorType, CFSTR("com.scintilla.utf16-plain-text.rectangular"))) {
+ format = kFormatUnicode;
+ isRectangular = true;
+ }
+ else if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))) { // this is 'utxt'
+ format = kFormatUnicode;
+ }
+ else if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text"))) {
+ format = kFormatUTF8;
+ }
+ else if (UTTypeConformsTo(flavorType, CFSTR("com.apple.traditional-mac-plain-text"))) { // this is 'TEXT'
+ format = kFormatText;
+ }
+ if (format == kFormatBad)
+ continue;
+
+ // if we got a flavor match, and we have no textString, we just want
+ // to know that we can accept this data, so jump out now
+ if (selectedText == NULL) {
+ haveMatch = true;
+ goto PasteboardDataRetrieved;
+ }
+ if (PasteboardCopyItemFlavorData(pasteBoard, itemID, flavorType, &flavorData) == noErr)
+ {
+ CFIndex dataSize = CFDataGetLength (flavorData);
+ const UInt8* dataBytes = CFDataGetBytePtr (flavorData);
+ switch (format)
+ {
+ case kFormatFile:
+ case kFormatText:
+ data = CFDataCreate (NULL, dataBytes, dataSize);
+ textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingMacRoman);
+ break;
+ case kFormatUnicode:
+ data = CFDataCreate (NULL, dataBytes, dataSize);
+ textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingUnicode);
+ break;
+ case kFormatUTF8:
+ data = CFDataCreate (NULL, dataBytes, dataSize);
+ textString = CFStringCreateFromExternalRepresentation (NULL, data, kCFStringEncodingUTF8);
+ break;
+ }
+ CFRelease (flavorData);
+ goto PasteboardDataRetrieved;
+ }
+ }
+ }
+ }
+PasteboardDataRetrieved:
+ if (flavorTypeArray != NULL) CFRelease(flavorTypeArray);
+ int newlen = 0;
+ if (textString != NULL) {
+ selectedText->s = GetStringFromCFString(textString, &selectedText->len);
+ selectedText->rectangular = isRectangular;
+ // Default allocator releases both the CFString and the UniChar buffer (text)
+ CFRelease( textString );
+ textString = NULL;
+ }
+ if (haveMatch || selectedText != NULL && selectedText->s != NULL) {
+ return true;
+ }
+ return false;
+}
+
+char *ScintillaMacOSX::GetStringFromCFString(CFStringRef &textString, int *textLen)
+{
+
+ // Allocate a buffer, plus the null byte
+ CFIndex numUniChars = CFStringGetLength( textString );
+ CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman);
+ CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1;
+ char* cstring = new char[maximumByteLength];
+ CFIndex usedBufferLength = 0;
+ CFIndex numCharsConverted;
+ numCharsConverted = CFStringGetBytes( textString, CFRangeMake( 0, numUniChars ), encoding,
+ '?', false, reinterpret_cast<UInt8*>( cstring ),
+ maximumByteLength, &usedBufferLength );
+ cstring[usedBufferLength] = '\0'; // null terminate the ASCII/UTF8 string
+
+ // determine whether a BOM is in the string. Apps like Emacs prepends a BOM
+ // to the string, CFStrinGetBytes reflects that (though it may change in the conversion)
+ // so we need to remove it before pasting into our buffer. TextWrangler has no
+ // problem dealing with BOM when pasting into it.
+ int bomLen = BOMlen((unsigned char *)cstring);
+
+ // convert line endings to the document line ending
+ *textLen = 0;
+ char *result = Document::TransformLineEnds(textLen,
+ cstring + bomLen,
+ usedBufferLength - bomLen,
+ pdoc->eolMode);
+ delete[] cstring;
+ return result;
+}
+
+OSStatus ScintillaMacOSX::DragReceive(DragRef inDrag )
+{
+ // dragleave IS called, but for some reason (probably to do with inDrag)
+ // the hide hilite does not happen unless we do it here
+ HideDragHilite( inDrag );
+
+ PasteboardRef pasteBoard;
+ SelectionText selectedText;
+ CFStringRef textString = NULL;
+ bool isFileURL = false;
+ if (!GetDragData(inDrag, pasteBoard, &selectedText, &isFileURL)) {
+ return dragNotAcceptedErr;
+ }
+
+ if (isFileURL) {
+ NotifyURIDropped(selectedText.s);
+ } else {
+ // figure out if this is a move or a paste
+ DragAttributes attributes;
+ SInt16 modifiers = 0;
+ GetDragAttributes( inDrag, &attributes );
+ bool moving = true;
+
+ SelectionPosition position = SPositionFromLocation(GetDragPoint(inDrag));
+ if ( attributes & kDragInsideSenderWindow ) {
+ GetDragModifiers(inDrag, NULL, NULL, &modifiers);
+ switch (modifiers & ~btnState) // Filter out btnState (on for drop)
+ {
+ case optionKey:
+ // default is copy text
+ moving = false;
+ break;
+ case cmdKey:
+ case cmdKey | optionKey:
+ default:
+ // what to do with these? rectangular drag?
+ break;
+ }
+ }
+
+ DropAt(position, selectedText.s, moving, selectedText.rectangular);
+ }
+
+ return noErr;
+}
+
+// Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070)
+void ScintillaMacOSX::InsertCharacters (const UniChar* buf, int len)
+{
+ CFStringRef str = CFStringCreateWithCharactersNoCopy (NULL, buf, (UInt32) len, kCFAllocatorNull);
+ CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingMacRoman);
+ CFRange range = { 0, len };
+ CFIndex bufLen;
+ CFStringGetBytes (str, range, encoding, '?', false, NULL, 0, &bufLen);
+ UInt8* utf8buf = new UInt8 [bufLen];
+ CFStringGetBytes (str, range, encoding, '?', false, utf8buf, bufLen, NULL);
+ AddCharUTF ((char*) utf8buf, bufLen, false);
+ delete [] utf8buf;
+ CFRelease (str);
+}
+
+/** The simulated message loop. */
+sptr_t ScintillaMacOSX::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ switch (iMessage) {
+ case SCI_GETDIRECTFUNCTION:
+ Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Returning DirectFunction address.\n" );
+ return reinterpret_cast<sptr_t>( DirectFunction );
+
+ case SCI_GETDIRECTPOINTER:
+ Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Returning Direct pointer address.\n" );
+ return reinterpret_cast<sptr_t>( this );
+
+ case SCI_GRABFOCUS:
+ Platform::DebugDisplay( "ScintillaMacOSX::WndProc: Got an unhandled message. Ignoring it.\n" );
+ break;
+ case WM_UNICHAR:
+ if (IsUnicodeMode()) {
+ // Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070)
+ UniChar wcs[1] = { (UniChar) wParam};
+ InsertCharacters(wcs, 1);
+ return 1;
+ } else {
+ return 0;
+ }
+
+ default:
+ unsigned int r = ScintillaBase::WndProc(iMessage, wParam, lParam);
+
+ return r;
+ }
+ return 0l;
+}
+
+sptr_t ScintillaMacOSX::DefWndProc(unsigned int, uptr_t, sptr_t) {
+ return 0;
+}
+
+void ScintillaMacOSX::SetTicking(bool on) {
+ if (timer.ticking != on) {
+ timer.ticking = on;
+ if (timer.ticking) {
+ // Scintilla ticks = milliseconds
+ EventLoopTimerRef timerRef = NULL;
+ InstallTimer( timer.tickSize * kEventDurationMillisecond, &timerRef );
+ assert( timerRef != NULL );
+ timer.tickerID = reinterpret_cast<TickerID>( timerRef );
+ } else if ( timer.tickerID != NULL ) {
+ RemoveEventLoopTimer( reinterpret_cast<EventLoopTimerRef>( timer.tickerID ) );
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+bool ScintillaMacOSX::SetIdle(bool on) {
+ if (on) {
+ // Start idler, if it's not running.
+ if (idler.state == false) {
+ idler.state = true;
+ EventLoopTimerRef idlTimer;
+ InstallEventLoopIdleTimer(GetCurrentEventLoop(),
+ timer.tickSize * kEventDurationMillisecond,
+ 75 * kEventDurationMillisecond,
+ IdleTimerEventHandler, this, &idlTimer);
+ idler.idlerID = reinterpret_cast<IdlerID>( idlTimer );
+ }
+ } else {
+ // Stop idler, if it's running
+ if (idler.state == true) {
+ idler.state = false;
+ if (idler.idlerID != NULL)
+ RemoveEventLoopTimer( reinterpret_cast<EventLoopTimerRef>( idler.idlerID ) );
+ }
+ }
+ return true;
+}
+
+pascal void ScintillaMacOSX::IdleTimerEventHandler( EventLoopTimerRef inTimer,
+ EventLoopIdleTimerMessage inState,
+ void *scintilla )
+{
+ ScintillaMacOSX *sciThis = reinterpret_cast<ScintillaMacOSX*>( scintilla );
+ bool ret = sciThis->Idle();
+ if (ret == false) {
+ sciThis->SetIdle(false);
+ }
+}
+
+void ScintillaMacOSX::SetMouseCapture(bool on) {
+ capturedMouse = on;
+ if (mouseDownCaptures) {
+ if (capturedMouse) {
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ } else {
+ // reset to normal, buttonmove will change for other area's in the editor
+ WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0);
+ }
+ }
+}
+
+bool ScintillaMacOSX::HaveMouseCapture() {
+ return capturedMouse;
+}
+
+// The default GetClientRectangle calls GetClientPosition on wMain.
+// We override it to return "view local" co-ordinates so we can draw properly
+// plus we need to remove the space occupied by the scroll bars
+PRectangle ScintillaMacOSX::GetClientRectangle() {
+ PRectangle rc = wMain.GetClientPosition();
+ if (verticalScrollBarVisible)
+ rc.right -= scrollBarFixedSize + 1;
+ if (horizontalScrollBarVisible && (wrapState == eWrapNone))
+ rc.bottom -= scrollBarFixedSize + 1;
+ // Move to origin
+ rc.right -= rc.left;
+ rc.bottom -= rc.top;
+ rc.left = 0;
+ rc.top = 0;
+ return rc;
+}
+
+// Synchronously paint a rectangle of the window.
+void ScintillaMacOSX::SyncPaint(void* gc, PRectangle rc) {
+ paintState = painting;
+ rcPaint = rc;
+ PRectangle rcText = GetTextRectangle();
+ paintingAllText = rcPaint.Contains(rcText);
+ //Platform::DebugPrintf("ScintillaMacOSX::SyncPaint %0d,%0d %0d,%0d\n",
+ // rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
+ Surface *sw = Surface::Allocate();
+ if (sw) {
+ sw->Init( gc, wMain.GetID() );
+ Paint(sw, rc);
+ if (paintState == paintAbandoned) {
+ // do a FULL paint.
+ rcPaint = GetClientRectangle();
+ paintState = painting;
+ paintingAllText = true;
+ Paint(sw, rcPaint);
+ wMain.InvalidateAll();
+ }
+ sw->Release();
+ delete sw;
+ }
+ paintState = notPainting;
+}
+
+void ScintillaMacOSX::ScrollText(int /*linesToMove*/) {
+ // This function will invalidate the correct regions of the view,
+ // So shortly after this happens, draw will be called.
+ // But I'm not quite sure how this works ...
+ // I have a feeling that it is only supposed to work in conjunction with an HIScrollView.
+ // TODO: Cook up my own bitblt scroll: Grab the bits on screen, blit them shifted, invalidate the remaining stuff
+ //CGRect r = CGRectMake( 0, 0, rc.Width(), rc.Height() );
+ //HIViewScrollRect( reinterpret_cast<HIViewRef>( wMain.GetID() ), NULL, 0, vs.lineHeight * linesToMove );
+ wMain.InvalidateAll();
+}
+
+void ScintillaMacOSX::SetVerticalScrollPos() {
+ SetControl32BitValue( vScrollBar, topLine );
+}
+
+void ScintillaMacOSX::SetHorizontalScrollPos() {
+ SetControl32BitValue( hScrollBar, xOffset );
+}
+
+bool ScintillaMacOSX::ModifyScrollBars(int nMax, int nPage) {
+ Platform::DebugPrintf( "nMax: %d nPage: %d hScroll (%d -> %d) page: %d\n", nMax, nPage, 0, scrollWidth, GetTextRectangle().Width() );
+ // Minimum value = 0
+ // TODO: This is probably not needed, since we set this when the scroll bars are created
+ SetControl32BitMinimum( vScrollBar, 0 );
+ SetControl32BitMinimum( hScrollBar, 0 );
+
+ // Maximum vertical value = nMax + 1 - nPage (lines available to scroll)
+ SetControl32BitMaximum( vScrollBar, Platform::Maximum( nMax + 1 - nPage, 0 ) );
+ // Maximum horizontal value = scrollWidth - GetTextRectangle().Width() (pixels available to scroll)
+ SetControl32BitMaximum( hScrollBar, Platform::Maximum( scrollWidth - GetTextRectangle().Width(), 0 ) );
+
+ // Vertical page size = nPage
+ SetControlViewSize( vScrollBar, nPage );
+ // Horizontal page size = TextRectangle().Width()
+ SetControlViewSize( hScrollBar, GetTextRectangle().Width() );
+
+ // TODO: Verify what this return value is for
+ // The scroll bar components will handle if they need to be rerendered or not
+ return false;
+}
+
+void ScintillaMacOSX::ReconfigureScrollBars() {
+ PRectangle rc = wMain.GetClientPosition();
+ Resize(rc.Width(), rc.Height());
+}
+
+void ScintillaMacOSX::Resize(int width, int height) {
+ // Get the horizontal/vertical size of the scroll bars
+ GetThemeMetric( kThemeMetricScrollBarWidth, &scrollBarFixedSize );
+
+ bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
+ HIRect scrollRect;
+ if (verticalScrollBarVisible) {
+ scrollRect.origin.x = width - scrollBarFixedSize;
+ scrollRect.origin.y = 0;
+ scrollRect.size.width = scrollBarFixedSize;
+ if (showSBHorizontal) {
+ scrollRect.size.height = Platform::Maximum(1, height - scrollBarFixedSize);
+ } else {
+ scrollRect.size.height = height;
+ }
+
+ HIViewSetFrame( vScrollBar, &scrollRect );
+ if (HIViewGetSuperview(vScrollBar) == NULL) {
+ HIViewSetDrawingEnabled( vScrollBar, true );
+ HIViewSetVisible(vScrollBar, true);
+ HIViewAddSubview(GetViewRef(), vScrollBar );
+ Draw1Control(vScrollBar);
+ }
+ } else if (HIViewGetSuperview(vScrollBar) != NULL) {
+ HIViewSetDrawingEnabled( vScrollBar, false );
+ HIViewRemoveFromSuperview(vScrollBar);
+ }
+
+ if (showSBHorizontal) {
+ scrollRect.origin.x = 0;
+ // Always draw the scrollbar to avoid the "potiential" horizontal scroll bar and to avoid the resize box.
+ // This should be "good enough". Best would be to avoid the resize box.
+ // Even better would be to embed Scintilla inside an HIScrollView, which would handle this for us.
+ scrollRect.origin.y = height - scrollBarFixedSize;
+ if (verticalScrollBarVisible) {
+ scrollRect.size.width = Platform::Maximum( 1, width - scrollBarFixedSize );
+ } else {
+ scrollRect.size.width = width;
+ }
+ scrollRect.size.height = scrollBarFixedSize;
+
+ HIViewSetFrame( hScrollBar, &scrollRect );
+ if (HIViewGetSuperview(hScrollBar) == NULL) {
+ HIViewSetDrawingEnabled( hScrollBar, true );
+ HIViewAddSubview( GetViewRef(), hScrollBar );
+ Draw1Control(hScrollBar);
+ }
+ } else if (HIViewGetSuperview(hScrollBar) != NULL) {
+ HIViewSetDrawingEnabled( hScrollBar, false );
+ HIViewRemoveFromSuperview(hScrollBar);
+ }
+
+ ChangeSize();
+
+ // fixup mouse tracking regions, this causes mouseenter/exit to work
+ if (HIViewGetSuperview(GetViewRef()) != NULL) {
+ RgnHandle rgn = NewRgn();
+ HIRect r;
+ HIViewGetFrame( reinterpret_cast<HIViewRef>( GetViewRef() ), &r );
+ SetRectRgn(rgn, short (r.origin.x), short (r.origin.y),
+ short (r.origin.x + r.size.width - (verticalScrollBarVisible ? scrollBarFixedSize : 0)),
+ short (r.origin.y + r.size.height - (showSBHorizontal ? scrollBarFixedSize : 0)));
+ if (mouseTrackingRef == NULL) {
+ CreateMouseTrackingRegion(GetOwner(), rgn, NULL,
+ kMouseTrackingOptionsLocalClip,
+ mouseTrackingID, NULL,
+ GetControlEventTarget( GetViewRef() ),
+ &mouseTrackingRef);
+ } else {
+ ChangeMouseTrackingRegion(mouseTrackingRef, rgn, NULL);
+ }
+ DisposeRgn(rgn);
+ } else {
+ if (mouseTrackingRef != NULL) {
+ ReleaseMouseTrackingRegion(mouseTrackingRef);
+ }
+ mouseTrackingRef = NULL;
+ }
+}
+
+pascal void ScintillaMacOSX::LiveScrollHandler( HIViewRef control, SInt16 part )
+{
+ int currentValue = GetControl32BitValue( control );
+ int min = GetControl32BitMinimum( control );
+ int max = GetControl32BitMaximum( control );
+ int page = GetControlViewSize( control );
+
+ // Get a reference to the Scintilla C++ object
+ ScintillaMacOSX* scintilla = NULL;
+ OSStatus err;
+ err = GetControlProperty( control, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
+ assert( err == noErr && scintilla != NULL );
+
+ int singleScroll = 0;
+ if ( control == scintilla->vScrollBar )
+ {
+ // Vertical single scroll = one line
+ // TODO: Is there a Scintilla preference for this somewhere?
+ singleScroll = 1;
+ } else {
+ assert( control == scintilla->hScrollBar );
+ // Horizontal single scroll = 20 pixels (hardcoded from ScintillaWin)
+ // TODO: Is there a Scintilla preference for this somewhere?
+ singleScroll = 20;
+ }
+
+ // Determine the new value
+ int newValue = 0;
+ switch ( part )
+ {
+ case kControlUpButtonPart:
+ newValue = Platform::Maximum( currentValue - singleScroll, min );
+ break;
+
+ case kControlDownButtonPart:
+ // the the user scrolls to the right, allow more scroll space
+ if ( control == scintilla->hScrollBar && currentValue >= max) {
+ // change the max value
+ scintilla->scrollWidth += singleScroll;
+ SetControl32BitMaximum( control,
+ Platform::Maximum( scintilla->scrollWidth - scintilla->GetTextRectangle().Width(), 0 ) );
+ max = GetControl32BitMaximum( control );
+ scintilla->SetScrollBars();
+ }
+ newValue = Platform::Minimum( currentValue + singleScroll, max );
+ break;
+
+ case kControlPageUpPart:
+ newValue = Platform::Maximum( currentValue - page, min );
+ break;
+
+ case kControlPageDownPart:
+ newValue = Platform::Minimum( currentValue + page, max );
+ break;
+
+ case kControlIndicatorPart:
+ case kControlNoPart:
+ newValue = currentValue;
+ break;
+
+ default:
+ assert( false );
+ return;
+ }
+
+ // Set the new value
+ if ( control == scintilla->vScrollBar )
+ {
+ scintilla->ScrollTo( newValue );
+ } else {
+ assert( control == scintilla->hScrollBar );
+ scintilla->HorizontalScrollTo( newValue );
+ }
+}
+
+bool ScintillaMacOSX::ScrollBarHit(HIPoint location) {
+ // is this on our scrollbars? If so, track them
+ HIViewRef view;
+ // view is null if on editor, otherwise on scrollbar
+ HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()),
+ &location, true, &view);
+ if (view) {
+ HIViewPartCode part;
+
+ // make the point local to a scrollbar
+ PRectangle client = GetClientRectangle();
+ if (view == vScrollBar) {
+ location.x -= client.Width();
+ } else if (view == hScrollBar) {
+ location.y -= client.Height();
+ } else {
+ fprintf(stderr, "got a subview hit, but not a scrollbar???\n");
+ return false;
+ }
+
+ HIViewGetPartHit(view, &location, &part);
+
+ switch (part)
+ {
+ case kControlUpButtonPart:
+ case kControlDownButtonPart:
+ case kControlPageUpPart:
+ case kControlPageDownPart:
+ case kControlIndicatorPart:
+ ::Point p;
+ p.h = location.x;
+ p.v = location.y;
+ // We are assuming Appearance 1.1 or later, so we
+ // have the "live scroll" variant of the scrollbar,
+ // which lets you pass the action proc to TrackControl
+ // for the thumb (this was illegal in previous
+ // versions of the defproc).
+ isTracking = true;
+ ::TrackControl(view, p, ScintillaMacOSX::LiveScrollHandler);
+ ::HiliteControl(view, 0);
+ isTracking = false;
+ // The mouseup was eaten by TrackControl, however if we
+ // do not get a mouseup in the scintilla xbl widget,
+ // many bad focus issues happen. Simply post a mouseup
+ // and this firey pit becomes a bit cooler.
+ PostEvent(mouseUp, 0);
+ break;
+ default:
+ fprintf(stderr, "PlatformScrollBarHit part %d\n", part);
+ }
+ return true;
+ }
+ return false;
+}
+
+void ScintillaMacOSX::NotifyFocus(bool focus) {
+#ifdef EXT_INPUT
+ ExtInput::activate (GetViewRef(), focus);
+#endif
+ if (NULL != notifyProc)
+ notifyProc (notifyObj, WM_COMMAND,
+ (uintptr_t) ((focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS) << 16),
+ (uintptr_t) GetViewRef());
+}
+
+void ScintillaMacOSX::NotifyChange() {
+ if (NULL != notifyProc)
+ notifyProc (notifyObj, WM_COMMAND,
+ (uintptr_t) (SCEN_CHANGE << 16),
+ (uintptr_t) GetViewRef());
+}
+
+void ScintillaMacOSX::registerNotifyCallback(intptr_t windowid, SciNotifyFunc callback) {
+ notifyObj = windowid;
+ notifyProc = callback;
+}
+
+void ScintillaMacOSX::NotifyParent(SCNotification scn) {
+ if (NULL != notifyProc) {
+ scn.nmhdr.hwndFrom = (void*) this;
+ scn.nmhdr.idFrom = (unsigned int)wMain.GetID();
+ notifyProc (notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &scn);
+ }
+}
+
+void ScintillaMacOSX::NotifyKey(int key, int modifiers) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_KEY;
+ scn.ch = key;
+ scn.modifiers = modifiers;
+
+ NotifyParent(scn);
+}
+
+void ScintillaMacOSX::NotifyURIDropped(const char *list) {
+ SCNotification scn;
+ scn.nmhdr.code = SCN_URIDROPPED;
+ scn.text = list;
+
+ NotifyParent(scn);
+}
+
+#ifndef EXT_INPUT
+// Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070)
+int ScintillaMacOSX::KeyDefault(int key, int modifiers) {
+ if (!(modifiers & SCI_CTRL) && !(modifiers & SCI_ALT) && (key < 256)) {
+ AddChar(key);
+ return 1;
+ } else {
+ // Pass up to container in case it is an accelerator
+ NotifyKey(key, modifiers);
+ return 0;
+ }
+ //Platform::DebugPrintf("SK-key: %d %x %x\n",key, modifiers);
+}
+#endif
+
+template <class T, class U>
+struct StupidMap
+{
+public:
+ T key;
+ U value;
+};
+
+template <class T, class U>
+inline static U StupidMapFindFunction( const StupidMap<T, U>* elements, size_t length, const T& desiredKey )
+{
+ for ( size_t i = 0; i < length; ++ i )
+ {
+ if ( elements[i].key == desiredKey )
+ {
+ return elements[i].value;
+ }
+ }
+
+ return NULL;
+}
+
+// NOTE: If this macro is used on a StupidMap that isn't defined by StupidMap x[] = ...
+// The size calculation will fail!
+#define StupidMapFind( x, y ) StupidMapFindFunction( x, sizeof(x)/sizeof(*x), y )
+
+pascal OSStatus ScintillaMacOSX::CommandEventHandler( EventHandlerCallRef /*inCallRef*/, EventRef event, void* data )
+{
+ // TODO: Verify automatically that each constant only appears once?
+ const StupidMap<UInt32, void (ScintillaMacOSX::*)()> processCommands[] = {
+ { kHICommandCopy, &ScintillaMacOSX::Copy },
+ { kHICommandPaste, &ScintillaMacOSX::Paste },
+ { kHICommandCut, &ScintillaMacOSX::Cut },
+ { kHICommandUndo, &ScintillaMacOSX::Undo },
+ { kHICommandRedo, &ScintillaMacOSX::Redo },
+ { kHICommandClear, &ScintillaMacOSX::ClearSelection },
+ { kHICommandSelectAll, &ScintillaMacOSX::SelectAll },
+ };
+ const StupidMap<UInt32, bool (ScintillaMacOSX::*)()> canProcessCommands[] = {
+ { kHICommandCopy, &ScintillaMacOSX::HasSelection },
+ { kHICommandPaste, &ScintillaMacOSX::CanPaste },
+ { kHICommandCut, &ScintillaMacOSX::HasSelection },
+ { kHICommandUndo, &ScintillaMacOSX::CanUndo },
+ { kHICommandRedo, &ScintillaMacOSX::CanRedo },
+ { kHICommandClear, &ScintillaMacOSX::HasSelection },
+ { kHICommandSelectAll, &ScintillaMacOSX::AlwaysTrue },
+ };
+
+ HICommand command;
+ OSStatus result = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( command ), NULL, &command );
+ assert( result == noErr );
+
+ UInt32 kind = GetEventKind( event );
+ Platform::DebugPrintf("ScintillaMacOSX::CommandEventHandler kind %d\n", kind);
+
+ ScintillaMacOSX* scintilla = reinterpret_cast<ScintillaMacOSX*>( data );
+ assert( scintilla != NULL );
+
+ if ( kind == kEventProcessCommand )
+ {
+#ifdef EXT_INPUT
+ // We are getting a HI command, so stop extended input
+ ExtInput::stop (scintilla->GetViewRef());
+#endif
+ // Find the method pointer that matches this command
+ void (ScintillaMacOSX::*methodPtr)() = StupidMapFind( processCommands, command.commandID );
+
+ if ( methodPtr != NULL )
+ {
+ // Call the method if we found it, and tell the caller that we handled this event
+ (scintilla->*methodPtr)();
+ result = noErr;
+ } else {
+ // tell the caller that we did not handle the event
+ result = eventNotHandledErr;
+ }
+ }
+ // The default Mac OS X text editor does not handle these events to enable/disable menu items
+ // Why not? I think it should, so Scintilla does.
+ else if ( kind == kEventCommandUpdateStatus && ( command.attributes & kHICommandFromMenu ) )
+ {
+ // Find the method pointer that matches this command
+ bool (ScintillaMacOSX::*methodPtr)() = StupidMapFind( canProcessCommands, command.commandID );
+
+ if ( methodPtr != NULL ) {
+ // Call the method if we found it: enabling/disabling menu items
+ if ( (scintilla->*methodPtr)() ) {
+ EnableMenuItem( command.menu.menuRef, command.menu.menuItemIndex );
+ } else {
+ DisableMenuItem( command.menu.menuRef, command.menu.menuItemIndex );
+ }
+ result = noErr;
+ } else {
+ // tell the caller that we did not handle the event
+ result = eventNotHandledErr;
+ }
+ } else {
+ // Unhandled event: We should never get here
+ assert( false );
+ result = eventNotHandledErr;
+ }
+
+ return result;
+}
+
+bool ScintillaMacOSX::HasSelection()
+{
+ return ( !sel.Empty() );
+}
+
+bool ScintillaMacOSX::CanUndo()
+{
+ return pdoc->CanUndo();
+}
+
+bool ScintillaMacOSX::CanRedo()
+{
+ return pdoc->CanRedo();
+}
+
+bool ScintillaMacOSX::AlwaysTrue()
+{
+ return true;
+}
+
+void ScintillaMacOSX::CopyToClipboard(const SelectionText &selectedText) {
+ PasteboardRef theClipboard;
+ SetPasteboardData(theClipboard, selectedText);
+ // Done with the CFString
+ CFRelease( theClipboard );
+}
+
+void ScintillaMacOSX::Copy()
+{
+ if (!sel.Empty()) {
+#ifdef EXT_INPUT
+ ExtInput::stop (GetViewRef());
+#endif
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ fprintf(stderr, "copied text is rectangular? %d\n", selectedText.rectangular);
+ CopyToClipboard(selectedText);
+ }
+}
+
+bool ScintillaMacOSX::CanPaste()
+{
+ if (!Editor::CanPaste())
+ return false;
+
+ PasteboardRef theClipboard;
+ bool isFileURL = false;
+
+ PasteboardCreate( kPasteboardClipboard, &theClipboard );
+ bool ok = GetPasteboardData(theClipboard, NULL, &isFileURL);
+ CFRelease( theClipboard );
+ return ok;
+}
+
+void ScintillaMacOSX::Paste()
+{
+ Paste(false);
+}
+
+// XXX there is no system flag (I can find) to tell us that a paste is rectangular, so
+// applications must implement an additional command (eg. option-V like BBEdit)
+// in order to provide rectangular paste
+void ScintillaMacOSX::Paste(bool forceRectangular)
+{
+ PasteboardRef theClipboard;
+ SelectionText selectedText;
+ selectedText.rectangular = forceRectangular;
+ bool isFileURL = false;
+ PasteboardCreate( kPasteboardClipboard, &theClipboard );
+ bool ok = GetPasteboardData(theClipboard, &selectedText, &isFileURL);
+ CFRelease( theClipboard );
+ fprintf(stderr, "paste is rectangular? %d\n", selectedText.rectangular);
+ if (!ok || !selectedText.s)
+ // no data or no flavor we support
+ return;
+
+ pdoc->BeginUndoAction();
+ ClearSelection();
+ if (selectedText.rectangular) {
+ SelectionPosition selStart = sel.RangeMain().Start();
+ PasteRectangular(selStart, selectedText.s, selectedText.len);
+ } else
+ if ( pdoc->InsertString( sel.RangeMain().caret.Position(), selectedText.s, selectedText.len ) ) {
+ SetEmptySelection( sel.RangeMain().caret.Position() + selectedText.len );
+ }
+
+ pdoc->EndUndoAction();
+
+ Redraw();
+ EnsureCaretVisible();
+}
+
+void ScintillaMacOSX::CreateCallTipWindow(PRectangle rc) {
+ // create a calltip window
+ if (!ct.wCallTip.Created()) {
+ WindowClass windowClass = kHelpWindowClass;
+ WindowAttributes attributes = kWindowNoAttributes;
+ Rect contentBounds;
+ WindowRef outWindow;
+
+ // convert PRectangle to Rect
+ // this adjustment gets the calltip window placed in the correct location relative
+ // to our editor window
+ Rect bounds;
+ OSStatus err;
+ err = GetWindowBounds( this->GetOwner(), kWindowGlobalPortRgn, &bounds );
+ assert( err == noErr );
+ contentBounds.top = rc.top + bounds.top;
+ contentBounds.bottom = rc.bottom + bounds.top;
+ contentBounds.right = rc.right + bounds.left;
+ contentBounds.left = rc.left + bounds.left;
+
+ // create our calltip hiview
+ HIViewRef ctw = scintilla_calltip_new();
+ CallTip* objectPtr = &ct;
+ ScintillaMacOSX* sciThis = this;
+ SetControlProperty( ctw, scintillaMacOSType, 0, sizeof( this ), &sciThis );
+ SetControlProperty( ctw, scintillaCallTipType, 0, sizeof( objectPtr ), &objectPtr );
+
+ CreateNewWindow(windowClass, attributes, &contentBounds, &outWindow);
+ ControlRef root;
+ CreateRootControl(outWindow, &root);
+
+ HIViewRef hiroot = HIViewGetRoot (outWindow);
+ HIViewAddSubview(hiroot, ctw);
+
+ HIRect boundsRect;
+ HIViewGetFrame(hiroot, &boundsRect);
+ HIViewSetFrame( ctw, &boundsRect );
+
+ // bind the size of the calltip to the size of it's container window
+ HILayoutInfo layout = {
+ kHILayoutInfoVersionZero,
+ {
+ { NULL, kHILayoutBindTop, 0 },
+ { NULL, kHILayoutBindLeft, 0 },
+ { NULL, kHILayoutBindBottom, 0 },
+ { NULL, kHILayoutBindRight, 0 }
+ },
+ {
+ { NULL, kHILayoutScaleAbsolute, 0 },
+ { NULL, kHILayoutScaleAbsolute, 0 }
+
+ },
+ {
+ { NULL, kHILayoutPositionTop, 0 },
+ { NULL, kHILayoutPositionLeft, 0 }
+ }
+ };
+ HIViewSetLayoutInfo(ctw, &layout);
+
+ ct.wCallTip = root;
+ ct.wDraw = ctw;
+ ct.wCallTip.SetWindow(outWindow);
+ HIViewSetVisible(ctw,true);
+
+ }
+}
+
+void ScintillaMacOSX::CallTipClick()
+{
+ ScintillaBase::CallTipClick();
+}
+
+void ScintillaMacOSX::AddToPopUp( const char *label, int cmd, bool enabled )
+{
+ // Translate stuff into menu item attributes
+ MenuItemAttributes attributes = 0;
+ if ( label[0] == '\0' ) attributes |= kMenuItemAttrSeparator;
+ if ( ! enabled ) attributes |= kMenuItemAttrDisabled;
+
+ // Translate Scintilla commands into Mac OS commands
+ // TODO: If I create an AEDesc, OS X may insert these standard
+ // text editing commands into the menu for me
+ MenuCommand macCommand;
+ switch( cmd )
+ {
+ case idcmdUndo:
+ macCommand = kHICommandUndo;
+ break;
+ case idcmdRedo:
+ macCommand = kHICommandRedo;
+ break;
+ case idcmdCut:
+ macCommand = kHICommandCut;
+ break;
+ case idcmdCopy:
+ macCommand = kHICommandCopy;
+ break;
+ case idcmdPaste:
+ macCommand = kHICommandPaste;
+ break;
+ case idcmdDelete:
+ macCommand = kHICommandClear;
+ break;
+ case idcmdSelectAll:
+ macCommand = kHICommandSelectAll;
+ break;
+ case 0:
+ macCommand = 0;
+ break;
+ default:
+ assert( false );
+ return;
+ }
+
+ CFStringRef string = CFStringCreateWithCString( NULL, label, kCFStringEncodingUTF8 );
+ OSStatus err;
+ err = AppendMenuItemTextWithCFString( reinterpret_cast<MenuRef>( popup.GetID() ),
+ string, attributes, macCommand, NULL );
+ assert( err == noErr );
+
+ CFRelease( string );
+ string = NULL;
+}
+
+void ScintillaMacOSX::ClaimSelection() {
+ // Mac OS X does not have a primary selection
+}
+
+/** A wrapper function to permit external processes to directly deliver messages to our "message loop". */
+sptr_t ScintillaMacOSX::DirectFunction(
+ ScintillaMacOSX *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ return sciThis->WndProc(iMessage, wParam, lParam);
+}
+
+sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ HIViewRef control = reinterpret_cast<HIViewRef>(sci);
+ // Platform::DebugPrintf("scintilla_send_message %08X control %08X\n",sci,control);
+ // Get a reference to the Scintilla C++ object
+ ScintillaMacOSX* scintilla = NULL;
+ OSStatus err;
+ err = GetControlProperty( control, scintillaMacOSType, 0, sizeof( scintilla ), NULL, &scintilla );
+ assert( err == noErr && scintilla != NULL );
+ //Platform::DebugPrintf("scintilla_send_message scintilla %08X\n",scintilla);
+
+ return scintilla->WndProc(iMessage, wParam, lParam);
+}
+
+void ScintillaMacOSX::TimerFired( EventLoopTimerRef )
+{
+ Tick();
+ DragScroll();
+}
+
+OSStatus ScintillaMacOSX::BoundsChanged( UInt32 /*inOptions*/, const HIRect& inOriginalBounds, const HIRect& inCurrentBounds, RgnHandle /*inInvalRgn*/ )
+{
+ // If the width or height changed, modify the scroll bars and notify Scintilla
+ // This event is also delivered when the window moves, and we don't care about that
+ if ( inOriginalBounds.size.width != inCurrentBounds.size.width || inOriginalBounds.size.height != inCurrentBounds.size.height )
+ {
+ Resize( static_cast<int>( inCurrentBounds.size.width ), static_cast<int>( inCurrentBounds.size.height ) );
+ }
+ return noErr;
+}
+
+void ScintillaMacOSX::Draw( RgnHandle rgn, CGContextRef gc )
+{
+ Rect invalidRect;
+ GetRegionBounds( rgn, &invalidRect );
+
+ // NOTE: We get draw events that include the area covered by the scroll bar. No fear: Scintilla correctly ignores them
+ SyncPaint( gc, PRectangle( invalidRect.left, invalidRect.top, invalidRect.right, invalidRect.bottom ) );
+}
+
+ControlPartCode ScintillaMacOSX::HitTest( const HIPoint& where )
+{
+ if ( CGRectContainsPoint( Bounds(), where ) )
+ return 1;
+ else
+ return kControlNoPart;
+}
+
+OSStatus ScintillaMacOSX::SetFocusPart( ControlPartCode desiredFocus, RgnHandle /*invalidRgn*/, Boolean /*inFocusEverything*/, ControlPartCode* outActualFocus )
+{
+ assert( outActualFocus != NULL );
+
+ if ( desiredFocus == 0 ) {
+ // We are losing the focus
+ SetFocusState(false);
+ } else {
+ // We are getting the focus
+ SetFocusState(true);
+ }
+
+ *outActualFocus = desiredFocus;
+ return noErr;
+}
+
+// Map Mac Roman character codes to their equivalent Scintilla codes
+static inline int KeyTranslate( UniChar unicodeChar )
+{
+ switch ( unicodeChar )
+ {
+ case kDownArrowCharCode:
+ return SCK_DOWN;
+ case kUpArrowCharCode:
+ return SCK_UP;
+ case kLeftArrowCharCode:
+ return SCK_LEFT;
+ case kRightArrowCharCode:
+ return SCK_RIGHT;
+ case kHomeCharCode:
+ return SCK_HOME;
+ case kEndCharCode:
+ return SCK_END;
+#ifndef EXT_INPUT
+ case kPageUpCharCode:
+ return SCK_PRIOR;
+ case kPageDownCharCode:
+ return SCK_NEXT;
+#endif
+ case kDeleteCharCode:
+ return SCK_DELETE;
+ // TODO: Is there an insert key in the mac world? My insert key is the "help" key
+ case kHelpCharCode:
+ return SCK_INSERT;
+ case kEnterCharCode:
+ case kReturnCharCode:
+ return SCK_RETURN;
+#ifdef EXT_INPUT
+ // BP 2006-08-22: These codes below should not be translated. Otherwise TextInput() will fail for keys like SCK_ADD, which is '+'.
+ case kBackspaceCharCode:
+ return SCK_BACK;
+ case kFunctionKeyCharCode:
+ case kBellCharCode:
+ case kVerticalTabCharCode:
+ case kFormFeedCharCode:
+ case 14:
+ case 15:
+ case kCommandCharCode:
+ case kCheckCharCode:
+ case kAppleLogoCharCode:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case kEscapeCharCode:
+ return 0; // ignore
+ default:
+ return unicodeChar;
+#else
+ case kEscapeCharCode:
+ return SCK_ESCAPE;
+ case kBackspaceCharCode:
+ return SCK_BACK;
+ case '\t':
+ return SCK_TAB;
+ case '+':
+ return SCK_ADD;
+ case '-':
+ return SCK_SUBTRACT;
+ case '/':
+ return SCK_DIVIDE;
+ case kFunctionKeyCharCode:
+ return kFunctionKeyCharCode;
+ default:
+ return 0;
+#endif
+ }
+}
+
+static inline UniChar GetCharacterWithoutModifiers( EventRef rawKeyboardEvent )
+{
+ UInt32 keyCode;
+ // Get the key code from the raw key event
+ GetEventParameter( rawKeyboardEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof( keyCode ), NULL, &keyCode );
+
+ // Get the current keyboard layout
+ // TODO: If this is a performance sink, we need to cache these values
+ SInt16 lastKeyLayoutID = GetScriptVariable( /*currentKeyScript*/ GetScriptManagerVariable(smKeyScript), smScriptKeys);
+ Handle uchrHandle = GetResource('uchr', lastKeyLayoutID);
+
+ if (uchrHandle) {
+ // Translate the key press ignoring ctrl and option
+ UInt32 ignoredDeadKeys = 0;
+ UInt32 ignoredActualLength = 0;
+ UniChar unicodeKey = 0;
+ // (((modifiers & shiftKey) >> 8) & 0xFF)
+ OSStatus err;
+ err = UCKeyTranslate( reinterpret_cast<UCKeyboardLayout*>( *uchrHandle ), keyCode, kUCKeyActionDown,
+ /* modifierKeyState */ 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &ignoredDeadKeys,
+ /* buffer length */ 1,
+ /* actual length */ &ignoredActualLength,
+ /* string */ &unicodeKey );
+ assert( err == noErr );
+
+ return unicodeKey;
+ }
+ return 0;
+}
+
+// Text input is very annoying:
+// If the control key is pressed, or if the key is a "special" key (eg. arrow keys, function keys, whatever)
+// we let Scintilla handle it. If scintilla does not handle it, we do nothing (eventNotHandledErr).
+// Otherwise, the event is just some text and we add it to the buffer
+OSStatus ScintillaMacOSX::TextInput( TCarbonEvent& event )
+{
+ // Obtain the number of bytes of text
+ UInt32 actualSize = 0;
+ OSStatus err;
+ err = event.GetParameterSize( kEventParamTextInputSendText, &actualSize );
+ assert( err == noErr );
+ assert( actualSize != 0 );
+
+ const int numUniChars = actualSize / sizeof( UniChar );
+
+#ifdef EXT_INPUT
+ UniChar* text = new UniChar [numUniChars];
+ err = event.GetParameter( kEventParamTextInputSendText, typeUnicodeText, actualSize, text );
+ PLATFORM_ASSERT( err == noErr );
+
+ int modifiers = GetCurrentEventKeyModifiers();
+
+ // Loop over all characters in sequence
+ for (int i = 0; i < numUniChars; i++)
+ {
+ UniChar key = KeyTranslate( text[i] );
+ if (!key)
+ continue;
+
+ bool consumed = false;
+
+ // need to go here first so e.g. Tab indentation works
+ KeyDown ((int) key, (modifiers & shiftKey) != 0 || (modifiers & cmdKey) != 0, (modifiers & controlKey) != 0 || (modifiers & cmdKey) != 0,
+ (modifiers & optionKey) != 0 || (modifiers & cmdKey) != 0, &consumed);
+
+ // BP 2007-01-08: 1452623 Second Cmd+s to save doc inserts an "s" into the text on Mac.
+ // At this point we need to ignore all cmd/option keys with char value smaller than 32
+ if( !consumed )
+ consumed = ( modifiers & ( cmdKey | optionKey ) ) != 0 && text[i] < 32;
+
+ // If not consumed, insert the original key
+ if (!consumed)
+ InsertCharacters (text+i, 1);
+ }
+
+ delete[] text;
+ return noErr;
+#else
+ // Allocate a buffer for the text using Core Foundation
+ UniChar* text = reinterpret_cast<UniChar*>( CFAllocatorAllocate( CFAllocatorGetDefault(), actualSize, 0 ) );
+ assert( text != NULL );
+
+ // Get a copy of the text
+ err = event.GetParameter( kEventParamTextInputSendText, typeUnicodeText, actualSize, text );
+ assert( err == noErr );
+
+ // TODO: This is a gross hack to ignore function keys
+ // Surely we can do better?
+ if ( numUniChars == 1 && text[0] == kFunctionKeyCharCode ) return eventNotHandledErr;
+ int modifiers = GetCurrentEventKeyModifiers();
+ int scintillaKey = KeyTranslate( text[0] );
+
+ // Create a CFString which wraps and takes ownership of the "text" buffer
+ CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, text, numUniChars, NULL );
+ assert( string != NULL );
+ //delete text;
+ text = NULL;
+
+ // If we have a single unicode character that is special or
+ // to process a command. Try to do some translation.
+ if ( numUniChars == 1 && ( modifiers & controlKey || scintillaKey != 0 ) ) {
+ // If we have a modifier, we need to get the character without modifiers
+ if ( modifiers & controlKey ) {
+ EventRef rawKeyboardEvent = NULL;
+ event.GetParameter(
+ kEventParamTextInputSendKeyboardEvent,
+ typeEventRef,
+ sizeof( EventRef ),
+ &rawKeyboardEvent );
+ assert( rawKeyboardEvent != NULL );
+ scintillaKey = GetCharacterWithoutModifiers( rawKeyboardEvent );
+
+ // Make sure that we still handle special characters correctly
+ int temp = KeyTranslate( scintillaKey );
+ if ( temp != 0 ) scintillaKey = temp;
+
+ // TODO: This is a gross Unicode hack: ASCII chars have a value < 127
+ if ( scintillaKey <= 127 ) {
+ scintillaKey = toupper( (char) scintillaKey );
+ }
+ }
+
+ // Code taken from Editor::KeyDown
+ // It is copied here because we don't want to feed the key via
+ // KeyDefault if there is no special action
+ DwellEnd(false);
+ int scintillaModifiers = ( (modifiers & shiftKey) ? SCI_SHIFT : 0) | ( (modifiers & controlKey) ? SCI_CTRL : 0) |
+ ( (modifiers & optionKey) ? SCI_ALT : 0);
+ int msg = kmap.Find( scintillaKey, scintillaModifiers );
+ if (msg) {
+ // The keymap has a special event for this key: perform the operation
+ WndProc(msg, 0, 0);
+ err = noErr;
+ } else {
+ // We do not handle this event
+ err = eventNotHandledErr;
+ }
+ } else {
+ CFStringEncoding encoding = ( IsUnicodeMode() ? kCFStringEncodingUTF8 : kCFStringEncodingASCII);
+
+ // Allocate the buffer (don't forget the null!)
+ CFIndex maximumByteLength = CFStringGetMaximumSizeForEncoding( numUniChars, encoding ) + 1;
+ char* buffer = new char[maximumByteLength];
+
+ CFIndex usedBufferLength = 0;
+ CFIndex numCharsConverted;
+ numCharsConverted = CFStringGetBytes( string, CFRangeMake( 0, numUniChars ), encoding,
+ '?', false, reinterpret_cast<UInt8*>( buffer ),
+ maximumByteLength, &usedBufferLength );
+ assert( numCharsConverted == numUniChars );
+ buffer[usedBufferLength] = '\0'; // null terminate
+
+ // Add all the characters to the document
+ // NOTE: OS X doesn't specify that text input events provide only a single character
+ // if we get a single character, add it as a character
+ // otherwise, we insert the entire string
+ if ( numUniChars == 1 ) {
+ AddCharUTF( buffer, usedBufferLength );
+ } else {
+ // WARNING: This is an untested code path as with my US keyboard, I only enter a single character at a time
+ if (pdoc->InsertString(sel.RangeMain().caret.Position(), buffer, usedBufferLength)) {
+ SetEmptySelection(sel.RangeMain().caret.Position() + usedBufferLength);
+ }
+ }
+
+ // Free the buffer that was allocated
+ delete[] buffer;
+ buffer = NULL;
+ err = noErr;
+ }
+
+ // Default allocator releases both the CFString and the UniChar buffer (text)
+ CFRelease( string );
+ string = NULL;
+
+ return err;
+#endif
+}
+
+UInt32 ScintillaMacOSX::GetBehaviors()
+{
+ return TView::GetBehaviors() | kControlGetsFocusOnClick | kControlSupportsEmbedding;
+}
+
+OSStatus ScintillaMacOSX::MouseEntered(HIPoint& location, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ )
+{
+ if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) {
+ HIViewRef view;
+ HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()), &location, true, &view);
+ if (view) {
+ // the hit is on a subview (ie. scrollbars)
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ } else {
+ // reset to normal, buttonmove will change for other area's in the editor
+ WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0);
+ ButtonMove( Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) );
+ }
+ return noErr;
+ }
+ return eventNotHandledErr;
+}
+
+OSStatus ScintillaMacOSX::MouseExited(HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount )
+{
+ if (HIViewGetSuperview(GetViewRef()) != NULL) {
+ if (HaveMouseCapture()) {
+ ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ),
+ static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),
+ (modifiers & controlKey) != 0 );
+ }
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ return noErr;
+ }
+ return eventNotHandledErr;
+}
+
+
+OSStatus ScintillaMacOSX::MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount , TCarbonEvent& inEvent)
+{
+ ConvertEventRefToEventRecord( inEvent.GetEventRef(), &mouseDownEvent );
+ return MouseDown(location, modifiers, button, clickCount);
+}
+
+OSStatus ScintillaMacOSX::MouseDown( EventRecord *event )
+{
+ HIPoint pt = GetLocalPoint(event->where);
+ int button = kEventMouseButtonPrimary;
+ mouseDownEvent = *event;
+
+ if ( event->modifiers & controlKey )
+ button = kEventMouseButtonSecondary;
+ return MouseDown(pt, event->modifiers, button, 1);
+}
+
+OSStatus ScintillaMacOSX::MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 /*clickCount*/ )
+{
+ // We only deal with the first mouse button
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ // TODO: Verify that Scintilla wants the time in milliseconds
+ if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) {
+ if (ScrollBarHit(location)) return noErr;
+ }
+ ButtonDown( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ),
+ static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),
+ (modifiers & shiftKey) != 0,
+ (modifiers & controlKey) != 0,
+ (modifiers & cmdKey) );
+#if !defined(CONTAINER_HANDLES_EVENTS)
+ OSStatus err;
+ err = SetKeyboardFocus( this->GetOwner(), this->GetViewRef(), 1 );
+ ::SetUserFocusWindow(::HIViewGetWindow( this->GetViewRef() ));
+ return noErr;
+#else
+ return eventNotHandledErr; // allow event to go to container
+#endif
+}
+
+OSStatus ScintillaMacOSX::MouseUp( EventRecord *event )
+{
+ HIPoint pt = GetLocalPoint(event->where);
+ int button = kEventMouseButtonPrimary;
+ if ( event->modifiers & controlKey )
+ button = kEventMouseButtonSecondary;
+ return MouseUp(pt, event->modifiers, button, 1);
+}
+
+OSStatus ScintillaMacOSX::MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 /*clickCount*/ )
+{
+ // We only deal with the first mouse button
+ if ( button != kEventMouseButtonPrimary ) return eventNotHandledErr;
+ ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ),
+ static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),
+ (modifiers & controlKey) != 0 );
+
+#if !defined(CONTAINER_HANDLES_EVENTS)
+ return noErr;
+#else
+ return eventNotHandledErr; // allow event to go to container
+#endif
+}
+
+OSStatus ScintillaMacOSX::MouseDragged( EventRecord *event )
+{
+ HIPoint pt = GetLocalPoint(event->where);
+ int button = 0;
+ if ( event->modifiers & btnStateBit ) {
+ button = kEventMouseButtonPrimary;
+ if ( event->modifiers & controlKey )
+ button = kEventMouseButtonSecondary;
+ }
+ return MouseDragged(pt, event->modifiers, button, 1);
+}
+
+OSStatus ScintillaMacOSX::MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount )
+{
+#if !defined(CONTAINER_HANDLES_EVENTS)
+ ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) );
+ return noErr;
+#else
+ if (HaveMouseCapture() && !inDragDrop) {
+ MouseTrackingResult mouseStatus = 0;
+ ::Point theQDPoint;
+ UInt32 outModifiers;
+ EventTimeout inTimeout=0.1;
+ while (mouseStatus != kMouseTrackingMouseReleased) {
+ ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) );
+ TrackMouseLocationWithOptions((GrafPtr)-1,
+ kTrackMouseLocationOptionDontConsumeMouseUp,
+ inTimeout,
+ &theQDPoint,
+ &outModifiers,
+ &mouseStatus);
+ location = GetLocalPoint(theQDPoint);
+ }
+ ButtonUp( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ),
+ static_cast<int>( GetCurrentEventTime() / kEventDurationMillisecond ),
+ (modifiers & controlKey) != 0 );
+ } else {
+ if (!HaveMouseCapture() && HIViewGetSuperview(GetViewRef()) != NULL) {
+ HIViewRef view;
+ HIViewGetSubviewHit(reinterpret_cast<ControlRef>(wMain.GetID()), &location, true, &view);
+ if (view) {
+ // the hit is on a subview (ie. scrollbars)
+ WndProc(SCI_SETCURSOR, Window::cursorArrow, 0);
+ return eventNotHandledErr;
+ } else {
+ // reset to normal, buttonmove will change for other area's in the editor
+ WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0);
+ }
+ }
+ ButtonMove( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) );
+ }
+ return eventNotHandledErr; // allow event to go to container
+#endif
+}
+
+OSStatus ScintillaMacOSX::MouseWheelMoved( EventMouseWheelAxis axis, SInt32 delta, UInt32 modifiers )
+{
+ if ( axis != 1 ) return eventNotHandledErr;
+
+ if ( modifiers & controlKey ) {
+ // Zoom! We play with the font sizes in the styles.
+ // Number of steps/line is ignored, we just care if sizing up or down
+ if ( delta > 0 ) {
+ KeyCommand( SCI_ZOOMIN );
+ } else {
+ KeyCommand( SCI_ZOOMOUT );
+ }
+ } else {
+ // Decide if this should be optimized?
+ ScrollTo( topLine - delta );
+ }
+
+ return noErr;
+}
+
+OSStatus ScintillaMacOSX::ContextualMenuClick( HIPoint& location )
+{
+ // convert screen coords to window relative
+ Rect bounds;
+ OSStatus err;
+ err = GetWindowBounds( this->GetOwner(), kWindowContentRgn, &bounds );
+ assert( err == noErr );
+ location.x += bounds.left;
+ location.y += bounds.top;
+ ContextMenu( Scintilla::Point( static_cast<int>( location.x ), static_cast<int>( location.y ) ) );
+ return noErr;
+}
+
+OSStatus ScintillaMacOSX::ActiveStateChanged()
+{
+ // If the window is being deactivated, lose the focus and turn off the ticking
+ if ( ! this->IsActive() ) {
+ DropCaret();
+ //SetFocusState( false );
+ SetTicking( false );
+ } else {
+ ShowCaretAtCurrentPosition();
+ }
+ return noErr;
+}
+
+HIViewRef ScintillaMacOSX::Create()
+{
+ // Register the HIView, if needed
+ static bool registered = false;
+
+ if ( not registered ) {
+ TView::RegisterSubclass( kScintillaClassID, Construct );
+ registered = true;
+ }
+
+ OSStatus err = noErr;
+ EventRef event = CreateInitializationEvent();
+ assert( event != NULL );
+
+ HIViewRef control = NULL;
+ err = HIObjectCreate( kScintillaClassID, event, reinterpret_cast<HIObjectRef*>( &control ) );
+ ReleaseEvent( event );
+ if ( err == noErr ) {
+ Platform::DebugPrintf("ScintillaMacOSX::Create control %08X\n",control);
+ return control;
+ }
+ return NULL;
+}
+
+OSStatus ScintillaMacOSX::Construct( HIViewRef inControl, TView** outView )
+{
+ *outView = new ScintillaMacOSX( inControl );
+ Platform::DebugPrintf("ScintillaMacOSX::Construct scintilla %08X\n",*outView);
+ if ( *outView != NULL )
+ return noErr;
+ else
+ return memFullErr; // could be a lie
+}
+
+extern "C" {
+HIViewRef scintilla_new() {
+ return ScintillaMacOSX::Create();
+}
+}
diff --git a/scintilla/macosx/ScintillaMacOSX.h b/scintilla/macosx/ScintillaMacOSX.h
new file mode 100644
index 0000000..f934820
--- /dev/null
+++ b/scintilla/macosx/ScintillaMacOSX.h
@@ -0,0 +1,234 @@
+/*
+ * ScintillaMacOSX.h
+ * tutorial
+ *
+ * Original code by Evan Jones on Sun Sep 01 2002.
+ * Contributors:
+ * Shane Caraveo, ActiveState
+ * Bernd Paradies, Adobe
+ *
+ */
+#include "TView.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <vector>
+
+#include "Platform.h"
+#include "Scintilla.h"
+#include "PlatMacOSX.h"
+
+
+#include "ScintillaWidget.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "PropSetSimple.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "SVector.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "AutoComplete.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+#include "ScintillaCallTip.h"
+
+static const OSType scintillaMacOSType = 'Scin';
+
+namespace Scintilla {
+
+/**
+On the Mac, there is no WM_COMMAND or WM_NOTIFY message that can be sent
+back to the parent. Therefore, there must be a callback handler that acts
+like a Windows WndProc, where Scintilla can send notifications to. Use
+ScintillaMacOSX::registerNotifyHandler() to register such a handler.
+Messgae format is:
+<br>
+WM_COMMAND: HIWORD (wParam) = notification code, LOWORD (wParam) = 0 (no control ID), lParam = ScintillaMacOSX*
+<br>
+WM_NOTIFY: wParam = 0 (no control ID), lParam = ptr to SCNotification structure, with hwndFrom set to ScintillaMacOSX*
+*/
+typedef void(*SciNotifyFunc) (intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam);
+
+/**
+Scintilla sends these two messages to the nofity handler. Please refer
+to the Windows API doc for details about the message format.
+*/
+#define WM_COMMAND 1001
+#define WM_NOTIFY 1002
+
+class ScintillaMacOSX : public ScintillaBase, public TView
+{
+ public:
+ HIViewRef vScrollBar;
+ HIViewRef hScrollBar;
+ SInt32 scrollBarFixedSize;
+ SciNotifyFunc notifyProc;
+ intptr_t notifyObj;
+
+ bool capturedMouse;
+ // true if scintilla initiated the drag session
+ bool inDragSession() { return inDragDrop == ddDragging; };
+ bool isTracking;
+
+ // Private so ScintillaMacOSX objects can not be copied
+ ScintillaMacOSX(const ScintillaMacOSX &) : ScintillaBase(), TView( NULL ) {}
+ ScintillaMacOSX &operator=(const ScintillaMacOSX &) { return * this; }
+
+public:
+ /** This is the class ID that we've assigned to Scintilla. */
+ static const CFStringRef kScintillaClassID;
+ static const ControlKind kScintillaKind;
+
+ ScintillaMacOSX( void* windowid );
+ virtual ~ScintillaMacOSX();
+ //~ static void ClassInit(GtkObjectClass* object_class, GtkWidgetClass *widget_class);
+
+ /** Returns the HIView object kind, needed to subclass TView. */
+ virtual ControlKind GetKind() { return kScintillaKind; }
+
+ /// Register the notify callback
+ void registerNotifyCallback(intptr_t windowid, SciNotifyFunc callback);
+private:
+ virtual void Initialise();
+ virtual void Finalise();
+
+ // pasteboard support
+ bool GetPasteboardData(PasteboardRef &pasteBoard,
+ SelectionText *selectedText, bool *isFileURL);
+ void SetPasteboardData(PasteboardRef &pasteBoard,
+ const SelectionText &selectedText);
+ char *GetStringFromCFString(CFStringRef &textString, int *textLen);
+
+ // Drag and drop
+ virtual void StartDrag();
+ Scintilla::Point GetDragPoint(DragRef inDrag);
+ bool GetDragData(DragRef inDrag, PasteboardRef &pasteBoard,
+ SelectionText *selectedText,
+ bool *isFileURL);
+ void SetDragCursor(DragRef inDrag);
+ virtual bool DragEnter(DragRef inDrag );
+ virtual bool DragWithin(DragRef inDrag );
+ virtual bool DragLeave(DragRef inDrag );
+ virtual OSStatus DragReceive(DragRef inDrag );
+ void DragScroll();
+ int scrollSpeed;
+ int scrollTicks;
+
+ EventRecord mouseDownEvent;
+ MouseTrackingRef mouseTrackingRef;
+ MouseTrackingRegionID mouseTrackingID;
+ HIPoint GetLocalPoint(::Point pt);
+
+ void InsertCharacters (const UniChar* buf, int len);
+ static pascal void IdleTimerEventHandler(EventLoopTimerRef inTimer,
+ EventLoopIdleTimerMessage inState,
+ void *scintilla );
+
+public: // Public for scintilla_send_message
+ virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ void SyncPaint( void* gc, PRectangle rc);
+ //void FullPaint( void* gc );
+ virtual void Draw( RgnHandle rgn, CGContextRef gc );
+
+ virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ virtual void SetTicking(bool on);
+ virtual bool SetIdle(bool on);
+ virtual void SetMouseCapture(bool on);
+ virtual bool HaveMouseCapture();
+ virtual PRectangle GetClientRectangle();
+
+ virtual void ScrollText(int linesToMove);
+ virtual void SetVerticalScrollPos();
+ virtual void SetHorizontalScrollPos();
+ virtual bool ModifyScrollBars(int nMax, int nPage);
+ virtual void ReconfigureScrollBars();
+ void Resize(int width, int height);
+ static pascal void LiveScrollHandler( ControlHandle control, SInt16 part );
+ bool ScrollBarHit(HIPoint location);
+
+ virtual void NotifyChange();
+ virtual void NotifyFocus(bool focus);
+ virtual void NotifyParent(SCNotification scn);
+ void NotifyKey(int key, int modifiers);
+ void NotifyURIDropped(const char *list);
+#ifndef EXT_INPUT
+ // Extended UTF8-UTF6-conversion to handle surrogate pairs correctly (CL265070)
+ virtual int KeyDefault(int key, int modifiers);
+#endif
+ static pascal OSStatus CommandEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* data );
+
+ bool HasSelection();
+ bool CanUndo();
+ bool CanRedo();
+ bool AlwaysTrue();
+ virtual void CopyToClipboard(const SelectionText &selectedText);
+ virtual void Copy();
+ virtual bool CanPaste();
+ virtual void Paste();
+ virtual void Paste(bool rectangular);
+ virtual void CreateCallTipWindow(PRectangle rc);
+ virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+ virtual void ClaimSelection();
+
+ static sptr_t DirectFunction(ScintillaMacOSX *sciThis,
+ unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ /** Timer event handler. Simply turns around and calls Tick. */
+ virtual void TimerFired( EventLoopTimerRef );
+ virtual OSStatus BoundsChanged( UInt32 inOptions, const HIRect& inOriginalBounds, const HIRect& inCurrentBounds, RgnHandle inInvalRgn );
+ virtual ControlPartCode HitTest( const HIPoint& where );
+ virtual OSStatus SetFocusPart( ControlPartCode desiredFocus, RgnHandle, Boolean, ControlPartCode* outActualFocus );
+ virtual OSStatus TextInput( TCarbonEvent& event );
+
+ // Configure the features of this control
+ virtual UInt32 GetBehaviors();
+
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount, TCarbonEvent& inEvent );
+ virtual OSStatus MouseDown( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseDown( EventRecord *rec );
+ virtual OSStatus MouseUp( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseUp( EventRecord *rec );
+ virtual OSStatus MouseDragged( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseDragged( EventRecord *rec );
+ virtual OSStatus MouseEntered( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseExited( HIPoint& location, UInt32 modifiers, EventMouseButton button, UInt32 clickCount );
+ virtual OSStatus MouseWheelMoved( EventMouseWheelAxis axis, SInt32 delta, UInt32 modifiers );
+ virtual OSStatus ContextualMenuClick( HIPoint& location );
+
+ virtual OSStatus ActiveStateChanged();
+
+ virtual void CallTipClick();
+
+
+public:
+ static HIViewRef Create();
+private:
+ static OSStatus Construct( HIViewRef inControl, TView** outView );
+
+};
+
+
+}
diff --git a/scintilla/macosx/TCarbonEvent.cxx b/scintilla/macosx/TCarbonEvent.cxx
new file mode 100644
index 0000000..6fe98c8
--- /dev/null
+++ b/scintilla/macosx/TCarbonEvent.cxx
@@ -0,0 +1,519 @@
+/*
+ File: TCarbonEvent.cp
+
+ Version: 1.0
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+*/
+
+#include "TCarbonEvent.h"
+
+//-----------------------------------------------------------------------------------
+// TCarbonEvent constructor
+//-----------------------------------------------------------------------------------
+//
+TCarbonEvent::TCarbonEvent(
+ UInt32 inClass,
+ UInt32 inKind )
+{
+ CreateEvent( NULL, inClass, inKind, GetCurrentEventTime(), 0, &fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// TCarbonEvent constructor
+//-----------------------------------------------------------------------------------
+//
+TCarbonEvent::TCarbonEvent(
+ EventRef inEvent )
+{
+ fEvent = inEvent;
+ RetainEvent( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// TCarbonEvent destructor
+//-----------------------------------------------------------------------------------
+//
+TCarbonEvent::~TCarbonEvent()
+{
+ ReleaseEvent( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// GetClass
+//-----------------------------------------------------------------------------------
+//
+UInt32 TCarbonEvent::GetClass() const
+{
+ return GetEventClass( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// GetKind
+//-----------------------------------------------------------------------------------
+//
+UInt32 TCarbonEvent::GetKind() const
+{
+ return GetEventKind( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// SetTime
+//-----------------------------------------------------------------------------------
+//
+void TCarbonEvent::SetTime(
+ EventTime inTime )
+{
+ SetEventTime( fEvent, inTime );
+}
+
+//-----------------------------------------------------------------------------------
+// GetTime
+//-----------------------------------------------------------------------------------
+//
+EventTime TCarbonEvent::GetTime() const
+{
+ return GetEventTime( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// Retain
+//-----------------------------------------------------------------------------------
+//
+void TCarbonEvent::Retain()
+{
+ RetainEvent( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// Release
+//-----------------------------------------------------------------------------------
+//
+void TCarbonEvent::Release()
+{
+ ReleaseEvent( fEvent );
+}
+
+//-----------------------------------------------------------------------------------
+// PostToQueue
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::PostToQueue(
+ EventQueueRef inQueue,
+ EventPriority inPriority )
+{
+ return PostEventToQueue( inQueue, fEvent, inPriority );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ UInt32 inSize,
+ const void* inData )
+{
+ return SetEventParameter( fEvent, inName, inType, inSize, inData );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ UInt32 inBufferSize,
+ void* outData )
+{
+ return GetEventParameter( fEvent, inName, inType, NULL, inBufferSize, NULL, outData );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameterType
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameterType(
+ EventParamName inName,
+ EventParamType* outType )
+{
+ return GetEventParameter( fEvent, inName, typeWildCard, outType, 0, NULL, NULL );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameterSize
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameterSize(
+ EventParamName inName,
+ UInt32* outSize )
+{
+ return GetEventParameter( fEvent, inName, typeWildCard, NULL, 0, outSize, NULL );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ Boolean inValue )
+{
+ return SetParameter<Boolean>( inName, typeBoolean, inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ Boolean* outValue )
+{
+ return GetParameter<Boolean>( inName, typeBoolean, outValue );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ bool inValue )
+{
+ return SetParameter<Boolean>( inName, typeBoolean, (Boolean) inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ bool* outValue )
+{
+ return GetParameter<Boolean>( inName, sizeof( Boolean ), (Boolean*) outValue );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ Point inPt )
+{
+ return SetParameter<Point>( inName, typeQDPoint, inPt );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ Point* outPt )
+{
+ return GetParameter<Point>( inName, typeQDPoint, outPt );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const HIPoint& inPt )
+{
+ return SetParameter<HIPoint>( inName, typeHIPoint, inPt );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ HIPoint* outPt )
+{
+ return GetParameter<HIPoint>( inName, typeHIPoint, outPt );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const Rect& inRect )
+{
+ return SetParameter<Rect>( inName, typeQDRectangle, inRect );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ Rect* outRect )
+{
+ return GetParameter<Rect>( inName, typeQDRectangle, outRect );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const HIRect& inRect )
+{
+ return SetParameter<HIRect>( inName, typeHIRect, inRect );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ HIRect* outRect )
+{
+ return GetParameter<HIRect>( inName, typeHIRect, outRect );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const HISize& inSize )
+{
+ return SetParameter<HISize>( inName, typeHISize, inSize );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ HISize* outSize )
+{
+ return GetParameter<HISize>( inName, typeHISize, outSize );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ RgnHandle inRegion )
+{
+ return SetParameter<RgnHandle>( inName, typeQDRgnHandle, inRegion );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ RgnHandle* outRegion )
+{
+ return GetParameter<RgnHandle>( inName, typeQDRgnHandle, outRegion );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ WindowRef inWindow )
+{
+ return SetParameter<WindowRef>( inName, typeWindowRef, inWindow );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ WindowRef* outWindow )
+{
+ return GetParameter<WindowRef>( inName, typeWindowRef, outWindow );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ ControlRef inControl )
+{
+ return SetParameter<ControlRef>( inName, typeControlRef, inControl );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ ControlRef* outControl )
+{
+ return GetParameter<ControlRef>( inName, typeControlRef, outControl );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ MenuRef inMenu )
+{
+ return SetParameter<MenuRef>( inName, typeMenuRef, inMenu );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ MenuRef* outMenu )
+{
+ return GetParameter<MenuRef>( inName, typeMenuRef, outMenu );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ DragRef inDrag )
+{
+ return SetParameter<DragRef>( inName, typeDragRef, inDrag );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ DragRef* outDrag )
+{
+ return GetParameter<DragRef>( inName, typeDragRef, outDrag );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ UInt32 inValue )
+{
+ return SetParameter<UInt32>( inName, typeUInt32, inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ UInt32* outValue )
+{
+ return GetParameter<UInt32>( inName, typeUInt32, outValue );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const HICommand& inValue )
+{
+ return SetParameter<HICommand>( inName, typeHICommand, inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ HICommand* outValue )
+{
+ return GetParameter<HICommand>( inName, typeHICommand, outValue );
+}
+
+//-----------------------------------------------------------------------------------
+// SetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::SetParameter(
+ EventParamName inName,
+ const ControlPartCode& inValue )
+{
+ return SetParameter<ControlPartCode>( inName, typeControlPartCode, inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetParameter
+//-----------------------------------------------------------------------------------
+//
+OSStatus TCarbonEvent::GetParameter(
+ EventParamName inName,
+ ControlPartCode* outValue )
+{
+ return GetParameter<ControlPartCode>( inName, typeControlPartCode, outValue );
+}
diff --git a/scintilla/macosx/TCarbonEvent.h b/scintilla/macosx/TCarbonEvent.h
new file mode 100644
index 0000000..0c1e2cf
--- /dev/null
+++ b/scintilla/macosx/TCarbonEvent.h
@@ -0,0 +1,230 @@
+/*
+ File: TCarbonEvent.h
+
+ Version: 1.0
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+*/
+
+#ifndef TCarbonEvent_H_
+#define TCarbonEvent_H_
+
+#include <Carbon/Carbon.h>
+
+class TCarbonEvent
+{
+public:
+ // Construction/Destruction
+ TCarbonEvent(
+ UInt32 inClass,
+ UInt32 inKind );
+ TCarbonEvent(
+ EventRef inEvent );
+ virtual ~TCarbonEvent();
+
+ UInt32 GetClass() const;
+ UInt32 GetKind() const;
+
+ // Time
+ void SetTime(
+ EventTime inTime );
+ EventTime GetTime() const;
+
+ // Retention
+ void Retain();
+ void Release();
+
+ // Accessors
+ operator EventRef&()
+ { return fEvent; };
+ EventRef GetEventRef()
+ { return fEvent; }
+
+ // Posting
+ OSStatus PostToQueue(
+ EventQueueRef inQueue,
+ EventPriority inPriority = kEventPriorityStandard );
+
+ // Parameters
+ OSStatus SetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ UInt32 inSize,
+ const void* inData );
+ OSStatus GetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ UInt32 inBufferSize,
+ void* outData );
+
+ OSStatus GetParameterType(
+ EventParamName inName,
+ EventParamType* outType );
+ OSStatus GetParameterSize(
+ EventParamName inName,
+ UInt32* outSize );
+
+ // Simple parameters
+ OSStatus SetParameter(
+ EventParamName inName,
+ Boolean inValue );
+ OSStatus GetParameter(
+ EventParamName inName,
+ Boolean* outValue );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ bool inValue );
+ OSStatus GetParameter(
+ EventParamName inName,
+ bool* outValue );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ Point inPt );
+ OSStatus GetParameter(
+ EventParamName inName,
+ Point* outPt );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const HIPoint& inPt );
+
+ OSStatus GetParameter(
+ EventParamName inName,
+ HIPoint* outPt );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const Rect& inRect );
+ OSStatus GetParameter(
+ EventParamName inName,
+ Rect* outRect );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const HIRect& inRect );
+ OSStatus GetParameter(
+ EventParamName inName,
+ HIRect* outRect );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const HISize& inSize );
+ OSStatus GetParameter(
+ EventParamName inName,
+ HISize* outSize );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ RgnHandle inRegion );
+ OSStatus GetParameter(
+ EventParamName inName,
+ RgnHandle* outRegion );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ WindowRef inWindow );
+ OSStatus GetParameter(
+ EventParamName inName,
+ WindowRef* outWindow );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ ControlRef inControl );
+ OSStatus GetParameter(
+ EventParamName inName,
+ ControlRef* outControl );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ MenuRef inMenu );
+ OSStatus GetParameter(
+ EventParamName inName,
+ MenuRef* outMenu );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ DragRef inDrag );
+ OSStatus GetParameter(
+ EventParamName inName,
+ DragRef* outDrag );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ UInt32 inValue );
+ OSStatus GetParameter(
+ EventParamName inName,
+ UInt32* outValue );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const HICommand& inValue );
+ OSStatus GetParameter(
+ EventParamName inName,
+ HICommand* outValue );
+
+ OSStatus SetParameter(
+ EventParamName inName,
+ const ControlPartCode& inValue );
+ OSStatus GetParameter(
+ EventParamName inName,
+ ControlPartCode* outValue );
+
+ // Template parameters
+ template <class T> OSStatus SetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ const T& inValue )
+ {
+ return SetParameter( inName, inType, sizeof( T ), &inValue );
+ }
+
+ template <class T> OSStatus GetParameter(
+ EventParamName inName,
+ EventParamType inType,
+ T* outValue )
+ {
+ return GetParameter( inName, inType, sizeof( T ), outValue );
+ }
+
+private:
+ EventRef fEvent;
+};
+
+#endif // TCarbonEvent_H_
diff --git a/scintilla/macosx/TRect.h b/scintilla/macosx/TRect.h
new file mode 100644
index 0000000..b8a9f4b
--- /dev/null
+++ b/scintilla/macosx/TRect.h
@@ -0,0 +1,496 @@
+/*
+ File: TRect.h
+
+ Version: 1.0
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+*/
+
+#ifndef TRect_H_
+#define TRect_H_
+
+#include <Carbon/Carbon.h>
+
+class TRect
+ : public HIRect
+{
+public:
+ // Construction/Destruction
+ TRect();
+ TRect(
+ const HIRect* inRect );
+ TRect(
+ const HIRect& inRect );
+ TRect(
+ const HIPoint& inOrigin,
+ const HISize& inSize );
+ TRect(
+ float inX,
+ float inY,
+ float inWidth,
+ float inHeight );
+ TRect(
+ const Rect& inRect );
+ ~TRect();
+
+ // Operators
+ operator HIRect*()
+ { return this; }
+ operator Rect() const;
+
+ // Accessors
+ float MinX() const
+ { return CGRectGetMinX( *this ); }
+ float MaxX() const
+ { return CGRectGetMaxX( *this ); }
+ float MinY() const
+ { return CGRectGetMinY( *this ); }
+ float MaxY() const
+ { return CGRectGetMaxY( *this ); }
+
+ float Width() const
+ { return CGRectGetWidth( *this ); }
+ float Height() const
+ { return CGRectGetHeight( *this ); }
+
+ const HIPoint& Origin() const
+ { return origin; }
+ const HISize& Size() const
+ { return size; }
+
+ float CenterX() const
+ { return CGRectGetMidX( *this ); }
+ float CenterY() const
+ { return CGRectGetMidY( *this ); }
+ HIPoint Center() const;
+
+ // Modifiers
+ const HIRect& Inset(
+ float inX,
+ float inY );
+ const HIRect& Outset(
+ float inX,
+ float inY );
+ const HIRect& MoveBy(
+ float inDx,
+ float inDy );
+ const HIRect& MoveTo(
+ float inX,
+ float inY );
+
+ const HIRect& Set(
+ const HIRect* inRect );
+ const HIRect& Set(
+ const HIRect& inRect );
+ const HIRect& Set(
+ float inX,
+ float inY,
+ float inWidth,
+ float inHeight );
+ const HIRect& Set(
+ const Rect* inRect );
+
+ const HIRect& SetAroundCenter(
+ float inCenterX,
+ float inCenterY,
+ float inWidth,
+ float inHeight );
+
+ const HIRect& SetWidth(
+ float inWidth );
+ const HIRect& SetHeight(
+ float inHeight );
+
+ const HIRect& SetOrigin(
+ const HIPoint& inOrigin );
+ const HIRect& SetOrigin(
+ float inX,
+ float inY );
+ const HIRect& SetSize(
+ const HISize& inSize );
+ const HIRect& SetSize(
+ float inWidth,
+ float inHeight );
+
+ // Tests
+ bool Contains(
+ const HIPoint& inPoint );
+ bool Contains(
+ const HIRect& inRect );
+ bool Contains(
+ const Point& inPoint );
+ bool Contains(
+ const Rect& inRect );
+};
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect()
+{
+}
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect(
+ const HIRect* inRect )
+{
+ *this = *inRect;
+}
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect(
+ const HIRect& inRect )
+{
+ origin = inRect.origin;
+ size = inRect.size;
+}
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect(
+ const HIPoint& inOrigin,
+ const HISize& inSize )
+{
+ origin = inOrigin;
+ size = inSize;
+}
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect(
+ float inX,
+ float inY,
+ float inWidth,
+ float inHeight )
+{
+ *this = CGRectMake( inX, inY, inWidth, inHeight );
+}
+
+//-----------------------------------------------------------------------------------
+// TRect destructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::~TRect()
+{
+}
+
+//-----------------------------------------------------------------------------------
+// TRect constructor
+//-----------------------------------------------------------------------------------
+//
+inline TRect::TRect(
+ const Rect& inRect )
+{
+ Set( &inRect );
+}
+
+//-----------------------------------------------------------------------------------
+// Rect operator
+//-----------------------------------------------------------------------------------
+// Converts the HIRect to a QD rect and returns it
+//
+inline TRect::operator Rect() const
+{
+ Rect qdRect;
+
+ qdRect.top = (SInt16) MinY();
+ qdRect.left = (SInt16) MinX();
+ qdRect.bottom = (SInt16) MaxY();
+ qdRect.right = (SInt16) MaxX();
+
+ return qdRect;
+}
+
+//-----------------------------------------------------------------------------------
+// Center
+//-----------------------------------------------------------------------------------
+//
+inline HIPoint TRect::Center() const
+{
+ return CGPointMake( CGRectGetMidX( *this ), CGRectGetMidY( *this ) );
+}
+
+//-----------------------------------------------------------------------------------
+// Inset
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Inset(
+ float inX,
+ float inY )
+{
+ *this = CGRectInset( *this, inX, inY );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Outset
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Outset(
+ float inX,
+ float inY )
+{
+ *this = CGRectInset( *this, -inX, -inY );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// MoveBy
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::MoveBy(
+ float inDx,
+ float inDy )
+{
+ origin = CGPointMake( MinX() + inDx, MinY() + inDy );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// MoveTo
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::MoveTo(
+ float inX,
+ float inY )
+{
+ origin = CGPointMake( inX, inY );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Set
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Set(
+ const HIRect* inRect )
+{
+ *this = *inRect;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Set
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Set(
+ const HIRect& inRect )
+{
+ *this = inRect;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Set
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Set(
+ float inX,
+ float inY,
+ float inWidth,
+ float inHeight )
+{
+ *this = CGRectMake( inX, inY, inWidth, inHeight );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Set
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::Set(
+ const Rect* inRect )
+{
+ origin.x = inRect->left;
+ origin.y = inRect->top;
+ size.width = inRect->right - inRect->left;
+ size.height = inRect->bottom - inRect->top;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetAroundCenter
+//-----------------------------------------------------------------------------------
+// Sets the rectangle by specifying dimensions around a center point
+//
+inline const HIRect& TRect::SetAroundCenter(
+ float inCenterX,
+ float inCenterY,
+ float inWidth,
+ float inHeight )
+{
+ *this = CGRectMake( inCenterX - inWidth/2, inCenterY - inHeight/2, inWidth, inHeight );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetWidth
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetWidth(
+ float inWidth )
+{
+ size.width = inWidth;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetHeight
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetHeight(
+ float inHeight )
+{
+ size.height = inHeight;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetOrigin
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetOrigin(
+ const HIPoint& inOrigin )
+{
+ origin = inOrigin;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetOrigin
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetOrigin(
+ float inX,
+ float inY )
+{
+ origin = CGPointMake( inX, inY );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetSize
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetSize(
+ const HISize& inSize )
+{
+ size = inSize;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// SetSize
+//-----------------------------------------------------------------------------------
+//
+inline const HIRect& TRect::SetSize(
+ float inWidth,
+ float inHeight )
+{
+ size = CGSizeMake( inWidth, inHeight );
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------------
+// Contains
+//-----------------------------------------------------------------------------------
+//
+inline bool TRect::Contains(
+ const HIPoint& inPoint )
+{
+ return CGRectContainsPoint( *this, inPoint );
+}
+
+//-----------------------------------------------------------------------------------
+// Contains
+//-----------------------------------------------------------------------------------
+//
+inline bool TRect::Contains(
+ const HIRect& inRect )
+{
+ return CGRectContainsRect( *this, inRect );
+}
+
+//-----------------------------------------------------------------------------------
+// Contains
+//-----------------------------------------------------------------------------------
+//
+inline bool TRect::Contains(
+ const Point& inPoint )
+{
+ return Contains( CGPointMake( inPoint.h, inPoint.v ) );
+}
+
+//-----------------------------------------------------------------------------------
+// Contains
+//-----------------------------------------------------------------------------------
+//
+inline bool TRect::Contains(
+ const Rect& inRect )
+{
+ return Contains( CGRectMake( inRect.left, inRect.top,
+ inRect.right - inRect.left, inRect.bottom - inRect.top ) );
+}
+
+#endif // TRect_H_
diff --git a/scintilla/macosx/TView.cxx b/scintilla/macosx/TView.cxx
new file mode 100644
index 0000000..aa0c634
--- /dev/null
+++ b/scintilla/macosx/TView.cxx
@@ -0,0 +1,1442 @@
+/*
+ File: TView.cp
+
+ Version: 1.0
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+*/
+
+/*
+ NOTE: This is NOWHERE near a completely exhaustive implementation of a view. There are
+ many more carbon events one could intercept and hook into this.
+*/
+
+#include "TView.h"
+
+//-----------------------------------------------------------------------------------
+// constants
+//-----------------------------------------------------------------------------------
+//
+const EventTypeSpec kHIObjectEvents[] =
+{ { kEventClassHIObject, kEventHIObjectConstruct },
+ { kEventClassHIObject, kEventHIObjectInitialize },
+ { kEventClassHIObject, kEventHIObjectDestruct }
+};
+
+const EventTypeSpec kHIViewEvents[] =
+{ { kEventClassCommand, kEventCommandProcess },
+ { kEventClassCommand, kEventCommandUpdateStatus },
+
+ { kEventClassControl, kEventControlInitialize },
+ { kEventClassControl, kEventControlDraw },
+ { kEventClassControl, kEventControlHitTest },
+ { kEventClassControl, kEventControlGetPartRegion },
+ { kEventClassControl, kEventControlGetData },
+ { kEventClassControl, kEventControlSetData },
+ { kEventClassControl, kEventControlGetOptimalBounds },
+ { kEventClassControl, kEventControlBoundsChanged },
+ { kEventClassControl, kEventControlTrack },
+ { kEventClassControl, kEventControlGetSizeConstraints },
+ { kEventClassControl, kEventControlHit },
+
+ { kEventClassControl, kEventControlHiliteChanged },
+ { kEventClassControl, kEventControlActivate },
+ { kEventClassControl, kEventControlDeactivate },
+ { kEventClassControl, kEventControlValueFieldChanged },
+ { kEventClassControl, kEventControlTitleChanged },
+ { kEventClassControl, kEventControlEnabledStateChanged },
+};
+
+// This param name was accidentally left unexported for
+// the release of Jaguar.
+const EventParamName kEventParamControlLikesDrag = 'cldg';
+
+//-----------------------------------------------------------------------------------
+// TView constructor
+//-----------------------------------------------------------------------------------
+//
+TView::TView(
+ HIViewRef inControl )
+ : fViewRef( inControl )
+{
+ verify_noerr( InstallEventHandler( GetControlEventTarget( fViewRef ), ViewEventHandler,
+ GetEventTypeCount( kHIViewEvents ), kHIViewEvents, this, &fHandler ) );
+
+ mouseEventHandler = NULL;
+ fAutoInvalidateFlags = 0;
+ debugPrint = false;
+}
+
+//-----------------------------------------------------------------------------------
+// TView destructor
+//-----------------------------------------------------------------------------------
+//
+TView::~TView()
+{
+ // If we have installed our custom mouse events handler on the window,
+ // go forth and remove it. Note: -1 is used to indicate that no handler has
+ // been installed yet, but we want to once we get a window.
+ if ( mouseEventHandler != NULL && mouseEventHandler != reinterpret_cast<void*>( -1 ) )
+ RemoveEventHandler( mouseEventHandler );
+ mouseEventHandler = NULL;
+}
+
+//-----------------------------------------------------------------------------------
+// Initialize
+//-----------------------------------------------------------------------------------
+// Called during HIObject construction, this is your subclasses' chance to extract
+// any parameters it might have added to the initialization event passed into the
+// HIObjectCreate call.
+//
+OSStatus TView::Initialize( TCarbonEvent& /*inEvent*/ )
+{
+ return noErr;
+}
+
+//-----------------------------------------------------------------------------------
+// GetBehaviors
+//-----------------------------------------------------------------------------------
+// Returns our behaviors. Any subclass that overrides this should OR in its behaviors
+// into the inherited behaviors.
+//
+UInt32 TView::GetBehaviors()
+{
+ return kControlSupportsDataAccess | kControlSupportsGetRegion;
+}
+
+//-----------------------------------------------------------------------------------
+// Draw
+//-----------------------------------------------------------------------------------
+// Draw your view. You should draw based on VIEW coordinates, not frame coordinates.
+//
+void TView::Draw(
+ RgnHandle /*inLimitRgn*/,
+ CGContextRef /*inContext*/ )
+{
+}
+
+//-----------------------------------------------------------------------------------
+// HitTest
+//-----------------------------------------------------------------------------------
+// Asks your view to return what part of itself (if any) is hit by the point given
+// to it. The point is in VIEW coordinates, so you should get the view rect to do
+// bounds checking.
+//
+ControlPartCode TView::HitTest(
+ const HIPoint& /*inWhere*/ )
+{
+ return kControlNoPart;
+}
+
+//-----------------------------------------------------------------------------------
+// GetRegion
+//-----------------------------------------------------------------------------------
+// This is called when someone wants to know certain metrics regarding this view.
+// The base class does nothing. Subclasses should handle their own parts, such as
+// the content region by overriding this method. The structure region is, by default,
+// the view's bounds. If a subclass does not have a region for a given part, it
+// should always call the inherited method.
+//
+OSStatus TView::GetRegion(
+ ControlPartCode inPart,
+ RgnHandle outRgn )
+{
+#pragma unused( inPart, outRgn )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// PrintDebugInfo
+//-----------------------------------------------------------------------------------
+// This is called when asked to print debugging information.
+//
+void TView::PrintDebugInfo()
+{
+}
+
+//-----------------------------------------------------------------------------------
+// GetData
+//-----------------------------------------------------------------------------------
+// Gets some data from our view. Subclasses should override to handle their own
+// defined data tags. If a tag is not understood by the subclass, it should call the
+// inherited method. As a convienience, we map the request for ControlKind into our
+// GetKind method.
+//
+OSStatus TView::GetData(
+ OSType inTag,
+ ControlPartCode inPart,
+ Size inSize,
+ Size* outSize,
+ void* inPtr )
+{
+#pragma unused( inPart )
+
+ OSStatus err = noErr;
+
+ switch( inTag )
+ {
+ case kControlKindTag:
+ if ( inPtr )
+ {
+ if ( inSize != sizeof( ControlKind ) )
+ err = errDataSizeMismatch;
+ else
+ ( *(ControlKind *) inPtr ) = GetKind();
+ }
+ *outSize = sizeof( ControlKind );
+ break;
+
+ default:
+ err = eventNotHandledErr;
+ break;
+ }
+
+ return err;
+}
+
+//-----------------------------------------------------------------------------------
+// SetData
+//-----------------------------------------------------------------------------------
+// Sets some data on our control. Subclasses should override to handle their own
+// defined data tags. If a tag is not understood by the subclass, it should call the
+// inherited method.
+//
+OSStatus TView::SetData(
+ OSType inTag,
+ ControlPartCode inPart,
+ Size inSize,
+ const void* inPtr )
+{
+#pragma unused( inTag, inPart, inSize, inPtr )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// GetOptimalSize
+//-----------------------------------------------------------------------------------
+// Someone wants to know this view's optimal size and text baseline, probably to help
+// do some type of layout. The base class does nothing, but subclasses should
+// override and do something meaningful here.
+//
+OSStatus TView::GetOptimalSize(
+ HISize* outSize,
+ float* outBaseLine )
+{
+#pragma unused( outSize, outBaseLine )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// GetSizeConstraints
+//-----------------------------------------------------------------------------------
+// Someone wants to know this view's minimum and maximum sizes, probably to help
+// do some type of layout. The base class does nothing, but subclasses should
+// override and do something meaningful here.
+//
+OSStatus TView::GetSizeConstraints(
+ HISize* outMin,
+ HISize* outMax )
+{
+#pragma unused( outMin, outMax )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// BoundsChanged
+//-----------------------------------------------------------------------------------
+// The bounds of our view have changed. Subclasses can override here to make note
+// of it and flush caches, etc. The base class does nothing.
+//
+OSStatus TView::BoundsChanged(
+ UInt32 inOptions,
+ const HIRect& inOriginalBounds,
+ const HIRect& inCurrentBounds,
+ RgnHandle inInvalRgn )
+{
+#pragma unused( inOptions, inOriginalBounds, inCurrentBounds, inInvalRgn )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// ControlHit
+//-----------------------------------------------------------------------------------
+// The was hit. Subclasses can overide to care about what part was hit.
+//
+OSStatus TView::ControlHit(
+ ControlPartCode inPart,
+ UInt32 inModifiers )
+{
+#pragma unused( inPart, inModifiers )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// HiliteChanged
+//-----------------------------------------------------------------------------------
+// The hilite of our view has changed. Subclasses can override here to make note
+// of it and flush caches, etc. The base class does nothing.
+//
+OSStatus TView::HiliteChanged(
+ ControlPartCode inOriginalPart,
+ ControlPartCode inCurrentPart,
+ RgnHandle inInvalRgn )
+{
+#pragma unused( inOriginalPart, inCurrentPart, inInvalRgn )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// DragEnter
+//-----------------------------------------------------------------------------------
+// A drag has entered our bounds. The Drag and Drop interface also should have been
+// activated or else this method will NOT be called. If true is returned, this view
+// likes the drag and will receive drag within/leave/receive messages as appropriate.
+// If false is returned, it is assumed the drag is not valid for this view, and no
+// further drag activity will flow into this view unless the drag leaves and is
+// re-entered.
+//
+bool TView::DragEnter(
+ DragRef inDrag )
+{
+#pragma unused( inDrag )
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------------
+// DragWithin
+//-----------------------------------------------------------------------------------
+// A drag has moved within our bounds. In order for this method to be called, the
+// view must have signaled the drag as being desirable in the DragEnter method. The
+// Drag and Drop interface also should have been activated.
+//
+bool TView::DragWithin(
+ DragRef inDrag )
+{
+#pragma unused( inDrag )
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------------
+// DragLeave
+//-----------------------------------------------------------------------------------
+// A drag has left. Deal with it. Subclasses should override as necessary. The
+// Drag and Drop interface should be activated in order for this method to be valid.
+// The drag must have also been accepted in the DragEnter method, else this method
+// will NOT be called.
+//
+bool TView::DragLeave(
+ DragRef inDrag )
+{
+#pragma unused( inDrag )
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------------
+// DragReceive
+//-----------------------------------------------------------------------------------
+// Deal with receiving a drag. By default we return dragNotAcceptedErr. I'm not sure
+// if this is correct, or eventNotHandledErr. Time will tell...
+//
+OSStatus TView::DragReceive(
+ DragRef inDrag )
+{
+#pragma unused( inDrag )
+
+ return dragNotAcceptedErr;
+}
+
+//-----------------------------------------------------------------------------------
+// Track
+//-----------------------------------------------------------------------------------
+// Default tracking method. Subclasses should override as necessary. We do nothing
+// here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::Track(
+ TCarbonEvent& inEvent,
+ ControlPartCode* outPart )
+{
+#pragma unused( inEvent, outPart )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// SetFocusPart
+//-----------------------------------------------------------------------------------
+// Handle focusing. Our base behavior is to punt.
+//
+OSStatus TView::SetFocusPart(
+ ControlPartCode inDesiredFocus,
+ RgnHandle inInvalidRgn,
+ Boolean inFocusEverything,
+ ControlPartCode* outActualFocus )
+{
+#pragma unused( inDesiredFocus, inInvalidRgn, inFocusEverything, outActualFocus )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// ProcessCommand
+//-----------------------------------------------------------------------------------
+// Process a command. Subclasses should override as necessary.
+//
+OSStatus TView::ProcessCommand(
+ const HICommand& inCommand )
+{
+#pragma unused( inCommand )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// UpdateCommandStatus
+//-----------------------------------------------------------------------------------
+// Update the status for a command. Subclasses should override as necessary.
+//
+OSStatus
+TView::UpdateCommandStatus(
+ const HICommand& inCommand )
+{
+#pragma unused( inCommand )
+
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseDown(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ ,
+ TCarbonEvent& /*inEvent*/)
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseUp(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ )
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseDragged(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ )
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseEntered(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ )
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseExited(HIPoint& /*inMouseLocation*/, UInt32 /*inKeyModifiers*/, EventMouseButton /*inMouseButton*/, UInt32 /*inClickCount*/ )
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::MouseWheelMoved( EventMouseWheelAxis /*inAxis*/, SInt32 /*inDelta*/, UInt32 /*inKeyModifiers*/ )
+{
+ return eventNotHandledErr;
+}
+
+OSStatus TView::ContextualMenuClick( HIPoint& /*inMouseLocation*/ )
+{
+ return eventNotHandledErr;
+}
+
+
+//-----------------------------------------------------------------------------------
+// ActivateInterface
+//-----------------------------------------------------------------------------------
+// This routine is used to allow a subclass to turn on a specific event or suite of
+// events, like Drag and Drop. This allows us to keep event traffic down if we are
+// not interested, but register for the events if we are.
+//
+OSStatus TView::ActivateInterface(
+ TView::Interface inInterface )
+{
+ OSStatus result = noErr;
+
+ switch( inInterface )
+ {
+ case kDragAndDrop:
+ {
+ static const EventTypeSpec kDragEvents[] =
+ {
+ { kEventClassControl, kEventControlDragEnter },
+ { kEventClassControl, kEventControlDragLeave },
+ { kEventClassControl, kEventControlDragWithin },
+ { kEventClassControl, kEventControlDragReceive }
+ };
+
+ result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kDragEvents ),
+ kDragEvents );
+
+ SetControlDragTrackingEnabled( GetViewRef(), true);
+ }
+ break;
+
+ case kKeyboardFocus:
+ {
+ static const EventTypeSpec kKeyboardFocusEvents[] =
+ {
+ { kEventClassControl, kEventControlSetFocusPart },
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ };
+
+ result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kKeyboardFocusEvents ),
+ kKeyboardFocusEvents );
+ }
+ break;
+
+ case kMouse:
+ {
+ if ( mouseEventHandler == NULL )
+ {
+ // This case is quite different: Mouse events are delivered to the window, not the controls.
+ // mouse wheel events are the exception: They ARE delivered to the control
+ static const EventTypeSpec kControlMouseEvents[] =
+ {
+ { kEventClassMouse, kEventMouseWheelMoved },
+ { kEventClassControl, kEventControlContextualMenuClick },
+ // So we can reinstall our events when the window changes
+ { kEventClassControl, kEventControlOwningWindowChanged },
+ };
+
+ result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kControlMouseEvents ),
+ kControlMouseEvents );
+ }
+
+ if ( this->GetOwner() != NULL )
+ {
+ // We use "-1" to indicate that we want to install an event handler once we get a window
+ if ( mouseEventHandler != NULL && mouseEventHandler != reinterpret_cast<void*>( -1 ) )
+ {
+ result = RemoveEventHandler( mouseEventHandler );
+ }
+ mouseEventHandler = NULL;
+
+ static const EventTypeSpec kWindowMouseEvents[] =
+ {
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged },
+ };
+
+ result = InstallEventHandler( GetWindowEventTarget( this->GetOwner() ), WindowEventHandler,
+ GetEventTypeCount( kWindowMouseEvents ), kWindowMouseEvents,
+ this, &mouseEventHandler );
+ }
+ // If we have no window yet. Set the mouseEventHandler to -1 so when we get one we
+ // will install the event handler
+ else
+ {
+ mouseEventHandler = reinterpret_cast<EventHandlerRef>( -1 );
+ }
+ }
+ break;
+ case kMouseTracking:
+ {
+ {
+ static const EventTypeSpec kControlMouseEvents[] =
+ {
+ { kEventClassMouse, kEventMouseEntered }, // only works if mousetracking is started
+ { kEventClassMouse, kEventMouseExited }, // only works if mousetracking is started
+ };
+
+ result = AddEventTypesToHandler( fHandler, GetEventTypeCount( kControlMouseEvents ),
+ kControlMouseEvents );
+ }
+ }
+
+ //default:
+ // assert( false );
+ }
+
+ return result;
+}
+
+OSStatus TView::InstallTimer( EventTimerInterval inFireDelay, EventLoopTimerRef* outTimer )
+{
+ return InstallEventLoopTimer( GetCurrentEventLoop(), inFireDelay, inFireDelay, TimerEventHandler, this, outTimer );
+}
+
+//-----------------------------------------------------------------------------------
+// RegisterSubclass
+//-----------------------------------------------------------------------------------
+// This routine should be called by subclasses so they can be created as HIObjects.
+//
+OSStatus TView::RegisterSubclass(
+ CFStringRef inID,
+ ConstructProc inProc )
+{
+ return HIObjectRegisterSubclass( inID, kHIViewClassID, 0, ObjectEventHandler,
+ GetEventTypeCount( kHIObjectEvents ), kHIObjectEvents, (void*) inProc, NULL );
+}
+
+//-----------------------------------------------------------------------------------
+// ObjectEventHandler
+//-----------------------------------------------------------------------------------
+// Our static event handler proc. We handle any HIObject based events directly in
+// here at present.
+//
+pascal OSStatus TView::ObjectEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+ OSStatus result = eventNotHandledErr;
+ TView* view = (TView*) inUserData;
+ TCarbonEvent event( inEvent );
+
+ switch ( event.GetClass() )
+ {
+ case kEventClassHIObject:
+ switch ( event.GetKind() )
+ {
+ case kEventHIObjectConstruct:
+ {
+ ControlRef control; // ControlRefs are HIObjectRefs
+ TView* view;
+
+ result = event.GetParameter<HIObjectRef>( kEventParamHIObjectInstance,
+ typeHIObjectRef, (HIObjectRef*)&control );
+ require_noerr( result, ParameterMissing );
+
+ // on entry for our construct event, we're passed the
+ // creation proc we registered with for this class.
+ // we use it now to create the instance, and then we
+ // replace the instance parameter data with said instance
+ // as type void.
+
+ result = (*(ConstructProc)inUserData)( control, &view );
+ if ( result == noErr )
+ event.SetParameter<TViewPtr>( kEventParamHIObjectInstance,
+ typeVoidPtr, view );
+ }
+ break;
+
+ case kEventHIObjectInitialize:
+ result = CallNextEventHandler( inCallRef, inEvent );
+ if ( result == noErr )
+ result = view->Initialize( event );
+ break;
+
+ case kEventHIObjectDestruct:
+ delete view;
+ break;
+ }
+ break;
+ }
+
+ParameterMissing:
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------------
+// ViewEventHandler
+//-----------------------------------------------------------------------------------
+// Our static event handler proc. We handle all non-HIObject events here.
+//
+pascal OSStatus TView::ViewEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+ OSStatus result;
+ TView* view = (TView*) inUserData;
+ TCarbonEvent event( inEvent );
+ //if (view->debugPrint)
+ // fprintf(stderr,"TView::ViewEventHandler\n");
+ result = view->HandleEvent( inCallRef, event );
+
+ return result;
+}
+
+
+pascal OSStatus TView::WindowEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData )
+{
+ TView* view = reinterpret_cast<TView*>( inUserData );
+ TCarbonEvent event( inEvent );
+
+ const WindowRef window = view->GetOwner();
+ if (NULL == window)
+ return eventNotHandledErr;
+
+ // If the window is not active, let the standard window handler execute.
+ if ( ! IsWindowActive( window ) ) return eventNotHandledErr;
+ if (view->debugPrint)
+ fprintf(stderr,"TView::WindowEventHandler\n");
+
+ const HIViewRef rootView = HIViewGetRoot( window );
+ if (NULL == rootView)
+ return eventNotHandledErr;
+
+ // TODO: On OS X 10.3, test if this bug still exists
+ // This is a hack to work around a bug in the OS. See:
+ // http://lists.apple.com/archives/carbon-development/2002/Sep/29/keventmousemovedeventsno.004.txt
+ OSStatus err;
+ if ( event.GetKind() == kEventMouseMoved )
+ {
+ // We need to set some parameters correctly
+ event.SetParameter( kEventParamWindowRef, window );
+
+ HIPoint ptMouse;
+ event.GetParameter( kEventParamMouseLocation, &ptMouse );
+
+ // convert screen coords to window relative
+ Rect bounds;
+ err = GetWindowBounds( window, kWindowStructureRgn, &bounds );
+ if( err == noErr )
+ {
+ ptMouse.x -= bounds.left;
+ ptMouse.y -= bounds.top;
+ event.SetParameter( kEventParamWindowMouseLocation, ptMouse );
+ }
+ }
+
+ HIViewRef targetView = NULL;
+ err = HIViewGetViewForMouseEvent( rootView, inEvent, &targetView );
+ //if (view->debugPrint)
+ // fprintf(stderr,"TView::WindowEventHandler root[%08X] viewRef[%08X] targetView[%08X]\n", rootView, view->GetViewRef(), targetView);
+ if ( targetView == view->GetViewRef() || event.GetKind() == kEventMouseDragged )
+ {
+ return view->HandleEvent( inCallRef, event );
+ }
+
+ return eventNotHandledErr;
+}
+
+pascal void TView::TimerEventHandler( EventLoopTimerRef inTimer, void* view )
+{
+ reinterpret_cast<TView*>( view )->TimerFired( inTimer );
+}
+
+//-----------------------------------------------------------------------------------
+// HandleEvent
+//-----------------------------------------------------------------------------------
+// Our object's virtual event handler method. I'm not sure if we need this these days.
+// We used to do various things with it, but those days are long gone...
+//
+OSStatus TView::HandleEvent(
+ EventHandlerCallRef inCallRef,
+ TCarbonEvent& inEvent )
+{
+#pragma unused( inCallRef )
+
+ OSStatus result = eventNotHandledErr;
+ HIPoint where;
+ OSType tag;
+ void * ptr;
+ Size size, outSize;
+ UInt32 features;
+ RgnHandle region = NULL;
+ ControlPartCode part;
+ RgnHandle invalRgn;
+
+ switch ( inEvent.GetClass() )
+ {
+ case kEventClassCommand:
+ {
+ HICommand command;
+
+ result = inEvent.GetParameter( kEventParamDirectObject, &command );
+ require_noerr( result, MissingParameter );
+
+ switch ( inEvent.GetKind() )
+ {
+ case kEventCommandProcess:
+ result = ProcessCommand( command );
+ break;
+
+ case kEventCommandUpdateStatus:
+ result = UpdateCommandStatus( command );
+ break;
+ }
+ }
+ break;
+
+ case kEventClassControl:
+ switch ( inEvent.GetKind() )
+ {
+ case kEventControlInitialize:
+ features = GetBehaviors();
+ inEvent.SetParameter( kEventParamControlFeatures, features );
+ result = noErr;
+ break;
+
+ case kEventControlDraw:
+ {
+ CGContextRef context = NULL;
+
+ inEvent.GetParameter( kEventParamRgnHandle, &region );
+ inEvent.GetParameter<CGContextRef>( kEventParamCGContextRef, typeCGContextRef, &context );
+
+ Draw( region, context );
+ result = noErr;
+ }
+ break;
+
+ case kEventControlHitTest:
+ inEvent.GetParameter<HIPoint>( kEventParamMouseLocation, typeHIPoint, &where );
+ part = HitTest( where );
+ inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, part );
+ result = noErr;
+ break;
+
+ case kEventControlGetPartRegion:
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part );
+ inEvent.GetParameter( kEventParamControlRegion, &region );
+ result = GetRegion( part, region );
+ break;
+
+ case kEventControlGetData:
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part );
+ inEvent.GetParameter<OSType>( kEventParamControlDataTag, typeEnumeration, &tag );
+ inEvent.GetParameter<Ptr>( kEventParamControlDataBuffer, typePtr, (Ptr*)&ptr );
+ inEvent.GetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, &size );
+
+ result = GetData( tag, part, size, &outSize, ptr );
+
+ if ( result == noErr )
+ verify_noerr( inEvent.SetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, outSize ) );
+ break;
+
+ case kEventControlSetData:
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part );
+ inEvent.GetParameter<OSType>( kEventParamControlDataTag, typeEnumeration, &tag );
+ inEvent.GetParameter<Ptr>( kEventParamControlDataBuffer, typePtr, (Ptr*)&ptr );
+ inEvent.GetParameter<Size>( kEventParamControlDataBufferSize, typeLongInteger, &size );
+
+ result = SetData( tag, part, size, ptr );
+ break;
+
+ case kEventControlGetOptimalBounds:
+ {
+ HISize size;
+ float floatBaseLine;
+
+ result = GetOptimalSize( &size, &floatBaseLine );
+ if ( result == noErr )
+ {
+ Rect bounds;
+ SInt16 baseLine;
+
+ GetControlBounds( GetViewRef(), &bounds );
+
+ bounds.bottom = bounds.top + (SInt16)size.height;
+ bounds.right = bounds.left + (SInt16)size.width;
+ baseLine = (SInt16)floatBaseLine;
+
+ inEvent.SetParameter( kEventParamControlOptimalBounds, bounds );
+ inEvent.SetParameter<SInt16>( kEventParamControlOptimalBaselineOffset, typeShortInteger, baseLine );
+ }
+ }
+ break;
+
+ case kEventControlBoundsChanged:
+ {
+ HIRect prevRect, currRect;
+ UInt32 attrs;
+
+ inEvent.GetParameter( kEventParamAttributes, &attrs );
+ inEvent.GetParameter( kEventParamOriginalBounds, &prevRect );
+ inEvent.GetParameter( kEventParamCurrentBounds, &currRect );
+ inEvent.GetParameter( kEventParamControlInvalRgn, &invalRgn );
+
+ result = BoundsChanged( attrs, prevRect, currRect, invalRgn );
+
+ if ( mouseEventHandler != NULL )
+ {
+ ActivateInterface( kMouse );
+ }
+
+ }
+ break;
+
+ case kEventControlHit:
+ {
+ UInt32 modifiers;
+
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &part );
+ inEvent.GetParameter( kEventParamKeyModifiers, &modifiers );
+
+ result = ControlHit( part, modifiers );
+ }
+ break;
+
+ case kEventControlHiliteChanged:
+ {
+ ControlPartCode prevPart, currPart;
+
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, &prevPart );
+ inEvent.GetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, &currPart );
+ inEvent.GetParameter( kEventParamControlInvalRgn, &invalRgn );
+
+ result = HiliteChanged( prevPart, currPart, invalRgn );
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnHilite )
+ Invalidate();
+ }
+ break;
+
+ case kEventControlActivate:
+ result = ActiveStateChanged();
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnActivate )
+ Invalidate();
+ break;
+
+ case kEventControlDeactivate:
+ result = ActiveStateChanged();
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnActivate )
+ Invalidate();
+ break;
+
+ case kEventControlValueFieldChanged:
+ result = ValueChanged();
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnValueChange )
+ Invalidate();
+ break;
+
+ case kEventControlTitleChanged:
+ result = TitleChanged();
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnTitleChange )
+ Invalidate();
+ break;
+
+ case kEventControlEnabledStateChanged:
+ result = EnabledStateChanged();
+
+ if ( GetAutoInvalidateFlags() & kAutoInvalidateOnEnable )
+ Invalidate();
+ break;
+
+ case kEventControlDragEnter:
+ case kEventControlDragLeave:
+ case kEventControlDragWithin:
+ {
+ DragRef drag;
+ bool likesDrag;
+
+ inEvent.GetParameter( kEventParamDragRef, &drag );
+
+ switch ( inEvent.GetKind() )
+ {
+ case kEventControlDragEnter:
+ likesDrag = DragEnter( drag );
+ // Why only if likesDrag? What if it doesn't? No parameter?
+ if ( likesDrag )
+ result = inEvent.SetParameter( kEventParamControlLikesDrag, likesDrag );
+ break;
+
+ case kEventControlDragLeave:
+ DragLeave( drag );
+ result = noErr;
+ break;
+
+ case kEventControlDragWithin:
+ DragWithin( drag );
+ result = noErr;
+ break;
+ }
+ }
+ break;
+
+ case kEventControlDragReceive:
+ {
+ DragRef drag;
+
+ inEvent.GetParameter( kEventParamDragRef, &drag );
+
+ result = DragReceive( drag );
+ }
+ break;
+
+ case kEventControlTrack:
+ {
+ ControlPartCode part;
+
+ result = Track( inEvent, &part );
+ if ( result == noErr )
+ verify_noerr( inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, part ) );
+ }
+ break;
+
+ case kEventControlGetSizeConstraints:
+ {
+ HISize minSize, maxSize;
+
+ result = GetSizeConstraints( &minSize, &maxSize );
+
+ if ( result == noErr )
+ {
+ verify_noerr( inEvent.SetParameter( kEventParamMinimumSize, minSize ) );
+ verify_noerr( inEvent.SetParameter( kEventParamMaximumSize, maxSize ) );
+ }
+ }
+ break;
+
+ case kEventControlSetFocusPart:
+ {
+ ControlPartCode desiredFocus;
+ RgnHandle invalidRgn;
+ Boolean focusEverything;
+ ControlPartCode actualFocus;
+
+ result = inEvent.GetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, &desiredFocus );
+ require_noerr( result, MissingParameter );
+
+ inEvent.GetParameter( kEventParamControlInvalRgn, &invalidRgn );
+
+ focusEverything = false; // a good default in case the parameter doesn't exist
+
+ inEvent.GetParameter( kEventParamControlFocusEverything, &focusEverything );
+
+ result = SetFocusPart( desiredFocus, invalidRgn, focusEverything, &actualFocus );
+
+ if ( result == noErr )
+ verify_noerr( inEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, actualFocus ) );
+ }
+ break;
+
+ case kEventControlOwningWindowChanged:
+ {
+ // If our owning window has changed, reactivate the mouse interface
+ if ( mouseEventHandler != NULL )
+ {
+ ActivateInterface( kMouse );
+ }
+ }
+ break;
+
+ case kEventControlContextualMenuClick:
+ {
+ HIPoint ptMouse;
+ inEvent.GetParameter( kEventParamMouseLocation, &ptMouse );
+ result = ContextualMenuClick( ptMouse );
+ }
+ break;
+
+ // some other kind of Control event
+ default:
+ break;
+ }
+ break;
+
+ case kEventClassTextInput:
+ result = TextInput( inEvent );
+ break;
+
+ case kEventClassMouse:
+ {
+ result = inEvent.GetParameter<HIPoint>( kEventParamWindowMouseLocation, typeHIPoint, &where );
+ HIViewConvertPoint( &where, NULL, fViewRef );
+
+ UInt32 inKeyModifiers;
+ result = inEvent.GetParameter( kEventParamKeyModifiers, &inKeyModifiers );
+ if( result != noErr )
+ inKeyModifiers = 0;
+ EventMouseButton inMouseButton = 0;
+ result = inEvent.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton, &inMouseButton );
+ if (noErr != result)
+ // assume no button is pressed if there is no button info
+ inMouseButton = 0;
+ UInt32 inClickCount;
+ result = inEvent.GetParameter( kEventParamClickCount, &inClickCount );
+ if( result != noErr )
+ inClickCount = 0;
+
+ switch ( inEvent.GetKind() )
+ {
+ case kEventMouseWheelMoved:
+ {
+ EventMouseWheelAxis inAxis;
+ result = inEvent.GetParameter<EventMouseWheelAxis>( kEventParamMouseWheelAxis, typeMouseWheelAxis, &inAxis );
+
+ SInt32 inDelta;
+ result = inEvent.GetParameter<SInt32>( kEventParamMouseWheelDelta, typeSInt32, &inDelta );
+
+ result = MouseWheelMoved( inAxis, inDelta, inKeyModifiers );
+ break;
+ }
+ case kEventMouseDown:
+ result = MouseDown( where, inKeyModifiers, inMouseButton, inClickCount, inEvent );
+ break;
+ case kEventMouseUp:
+ result = MouseUp( where, inKeyModifiers, inMouseButton, inClickCount );
+ break;
+ case kEventMouseExited:
+ result = MouseExited( where, inKeyModifiers, inMouseButton, inClickCount );
+ break;
+ case kEventMouseEntered:
+ result = MouseEntered( where, inKeyModifiers, inMouseButton, inClickCount );
+ break;
+ case kEventMouseMoved:
+ case kEventMouseDragged:
+ result = MouseDragged( where, inKeyModifiers, inMouseButton, inClickCount );
+ break;
+ default:;
+ }
+ break;
+ }
+ // some other event class
+ default:
+ break;
+ }
+
+MissingParameter:
+ return result;
+}
+
+//-----------------------------------------------------------------------------------
+// CreateInitializationEvent
+//-----------------------------------------------------------------------------------
+// Create a basic intialization event containing the parent control and bounds. At
+// present we set the bounds to empty and the parent to NULL. In theory, after creating
+// this event, any subclass could add its own parameter to receive in its
+// Initialize method.
+//
+EventRef TView::CreateInitializationEvent()
+{
+ OSStatus result = noErr;
+ EventRef event;
+
+ result = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize,
+ GetCurrentEventTime(), 0, &event );
+ require_noerr_action( result, CantCreateEvent, event = NULL );
+
+CantCreateEvent:
+ return event;
+}
+
+//-----------------------------------------------------------------------------------
+// Frame
+//-----------------------------------------------------------------------------------
+//
+HIRect TView::Frame()
+{
+ HIRect frame;
+
+ HIViewGetFrame( GetViewRef(), &frame );
+
+ return frame;
+}
+
+//-----------------------------------------------------------------------------------
+// SetFrame
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::SetFrame(
+ const HIRect& inFrame )
+{
+ OSStatus err;
+
+ err = HIViewSetFrame( GetViewRef(), &inFrame );
+
+ return err;
+}
+
+//-----------------------------------------------------------------------------------
+// Bounds
+//-----------------------------------------------------------------------------------
+//
+HIRect TView::Bounds()
+{
+ HIRect bounds;
+
+ HIViewGetBounds( GetViewRef(), &bounds );
+
+ return bounds;
+}
+
+//-----------------------------------------------------------------------------------
+// Show
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::Show()
+{
+ return HIViewSetVisible( GetViewRef(), true );
+}
+
+//-----------------------------------------------------------------------------------
+// Hide
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::Hide()
+{
+ return HIViewSetVisible( GetViewRef(), false );
+}
+
+//-----------------------------------------------------------------------------------
+// GetEventTarget
+//-----------------------------------------------------------------------------------
+//
+EventTargetRef TView::GetEventTarget()
+{
+ return HIObjectGetEventTarget( (HIObjectRef) GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// AddSubView
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::AddSubView(
+ TView* inSubView )
+{
+ return HIViewAddSubview( GetViewRef(), inSubView->GetViewRef() );;
+}
+
+//-----------------------------------------------------------------------------------
+// RemoveFromSuperView
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::RemoveFromSuperView()
+{
+ return HIViewRemoveFromSuperview( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// GetHilite
+//-----------------------------------------------------------------------------------
+//
+ControlPartCode TView::GetHilite()
+{
+ return GetControlHilite( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// GetValue
+//-----------------------------------------------------------------------------------
+//
+SInt32 TView::GetValue()
+{
+ return GetControl32BitValue( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// SetValue
+//-----------------------------------------------------------------------------------
+//
+void TView::SetValue(
+ SInt32 inValue )
+{
+ SetControl32BitValue( GetViewRef(), inValue );
+}
+
+//-----------------------------------------------------------------------------------
+// GetMinimum
+//-----------------------------------------------------------------------------------
+//
+SInt32 TView::GetMinimum()
+{
+ return GetControlMinimum( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// SetMinimum
+//-----------------------------------------------------------------------------------
+//
+void TView::SetMinimum(
+ SInt32 inMinimum )
+{
+ SetControlMinimum( GetViewRef(), inMinimum );
+}
+
+//-----------------------------------------------------------------------------------
+// GetMaximum
+//-----------------------------------------------------------------------------------
+//
+SInt32 TView::GetMaximum()
+{
+ return GetControlMaximum( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// SetMaximum
+//-----------------------------------------------------------------------------------
+//
+void TView::SetMaximum(
+ SInt32 inMaximum )
+{
+ SetControlMaximum( GetViewRef(), inMaximum );
+}
+
+//-----------------------------------------------------------------------------------
+// GetOwner
+//-----------------------------------------------------------------------------------
+//
+WindowRef TView::GetOwner()
+{
+ return GetControlOwner( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// Hilite
+//-----------------------------------------------------------------------------------
+//
+void TView::Hilite(
+ ControlPartCode inPart)
+{
+ return HiliteControl( GetViewRef(), inPart );
+}
+
+//-----------------------------------------------------------------------------------
+// Invalidate
+//-----------------------------------------------------------------------------------
+//
+OSStatus TView::Invalidate()
+{
+ return HIViewSetNeedsDisplay( GetViewRef(), true );
+}
+
+void TView::TimerFired( EventLoopTimerRef inTimer )
+{
+#pragma unused( inTimer )
+}
+
+
+//-----------------------------------------------------------------------------------
+// IsVisible
+//-----------------------------------------------------------------------------------
+//
+Boolean TView::IsVisible()
+{
+ return IsControlVisible( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// IsEnabled
+//-----------------------------------------------------------------------------------
+//
+Boolean TView::IsEnabled()
+{
+ return IsControlEnabled( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// IsActive
+//-----------------------------------------------------------------------------------
+//
+Boolean TView::IsActive()
+{
+ return IsControlActive( GetViewRef() );
+}
+
+//-----------------------------------------------------------------------------------
+// ActiveStateChanged
+//-----------------------------------------------------------------------------------
+// Default activation method. Subclasses should override as necessary. We do nothing
+// here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::ActiveStateChanged()
+{
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// ValueChanged
+//-----------------------------------------------------------------------------------
+// Default value changed method. Subclasses should override as necessary. We do
+// nothing here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::ValueChanged()
+{
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// TitleChanged
+//-----------------------------------------------------------------------------------
+// Default title changed method. Subclasses should override as necessary. We
+// do nothing here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::TitleChanged()
+{
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// EnabledStateChanged
+//-----------------------------------------------------------------------------------
+// Default enable method. Subclasses should override as necessary. We
+// do nothing here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::EnabledStateChanged()
+{
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// TextInput
+//-----------------------------------------------------------------------------------
+// Default text (Unicode) input method. Subclasses should override as necessary. We
+// do nothing here in the base class, so we return eventNotHandledErr.
+//
+OSStatus TView::TextInput(
+ TCarbonEvent& inEvent )
+{
+#pragma unused( inEvent )
+
+ return eventNotHandledErr;
+}
+
+//-----------------------------------------------------------------------------------
+// ChangeAutoInvalidateFlags
+//-----------------------------------------------------------------------------------
+// Change behavior for auto-invalidating views on certain actions.
+//
+void TView::ChangeAutoInvalidateFlags(
+ OptionBits inSetThese,
+ OptionBits inClearThese )
+{
+ fAutoInvalidateFlags = ( ( fAutoInvalidateFlags | inSetThese ) & ( ~inClearThese ) );
+}
diff --git a/scintilla/macosx/TView.h b/scintilla/macosx/TView.h
new file mode 100644
index 0000000..004b10d
--- /dev/null
+++ b/scintilla/macosx/TView.h
@@ -0,0 +1,286 @@
+/*
+ File: TView.h
+
+ Version: 1.0
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+*/
+
+#ifndef TView_H_
+#define TView_H_
+
+#include <Carbon/Carbon.h>
+
+#include "TCarbonEvent.h"
+#include "TRect.h"
+
+#define PURE_VIRTUAL 0
+
+class TView
+{
+public:
+ // Bounds and Frame
+ OSStatus SetFrame(
+ const HIRect& inBounds );
+ HIRect Frame();
+ HIRect Bounds();
+
+ // Visibility
+ OSStatus Show();
+ OSStatus Hide();
+
+ EventTargetRef GetEventTarget();
+
+ OSStatus AddSubView(
+ TView* inSubView );
+ OSStatus RemoveFromSuperView();
+
+ // Accessors
+ HIViewRef GetViewRef() const
+ { return fViewRef; }
+ void Hilite(
+ ControlPartCode inPart );
+ ControlPartCode GetHilite();
+ WindowRef GetOwner();
+ SInt32 GetValue();
+ void SetValue(
+ SInt32 inValue );
+ SInt32 GetMinimum();
+ void SetMinimum(
+ SInt32 inMinimum );
+ SInt32 GetMaximum();
+ void SetMaximum(
+ SInt32 inMaximum );
+
+ // State
+ Boolean IsVisible();
+ Boolean IsEnabled();
+ Boolean IsActive();
+
+ OSStatus Invalidate(); // was SetNeedsDisplay()
+
+ // A "fake" event handler
+ virtual void TimerFired( EventLoopTimerRef inTimer );
+
+protected:
+ // Autoinvalidation
+ enum {
+ kAutoInvalidateOnActivate = (1 << 0),
+ kAutoInvalidateOnHilite = (1 << 1),
+ kAutoInvalidateOnEnable = (1 << 2),
+ kAutoInvalidateOnValueChange = (1 << 3),
+ kAutoInvalidateOnTitleChange = (1 << 4)
+ };
+ void ChangeAutoInvalidateFlags(
+ OptionBits inSetFlags,
+ OptionBits inClearFlags );
+ OptionBits GetAutoInvalidateFlags()
+ { return fAutoInvalidateFlags; }
+
+ // Types
+ typedef OSStatus (*ConstructProc)(
+ ControlRef inBaseControl,
+ TView** outView );
+
+ // Construction/Destruction
+ TView( HIViewRef inControl );
+ virtual ~TView();
+
+ virtual ControlKind GetKind() = PURE_VIRTUAL;
+ virtual UInt32 GetBehaviors();
+
+ // Handlers
+ virtual OSStatus ActiveStateChanged();
+ virtual OSStatus BoundsChanged(
+ UInt32 inOptions,
+ const HIRect& inOriginalBounds,
+ const HIRect& inCurrentBounds,
+ RgnHandle inInvalRgn );
+ virtual OSStatus ControlHit(
+ ControlPartCode inPart,
+ UInt32 inModifiers );
+ virtual OSStatus EnabledStateChanged();
+ virtual void Draw(
+ RgnHandle inLimitRgn,
+ CGContextRef inContext );
+ virtual OSStatus GetData(
+ OSType inTag,
+ ControlPartCode inPart,
+ Size inSize,
+ Size* outSize,
+ void* inPtr );
+ virtual OSStatus GetRegion(
+ ControlPartCode inPart,
+ RgnHandle outRgn );
+ virtual OSStatus HiliteChanged(
+ ControlPartCode inOriginalPart,
+ ControlPartCode inCurrentPart,
+ RgnHandle inInvalRgn );
+ virtual ControlPartCode HitTest(
+ const HIPoint& inWhere );
+ virtual OSStatus Initialize(
+ TCarbonEvent& inEvent );
+ virtual OSStatus SetData(
+ OSType inTag,
+ ControlPartCode inPart,
+ Size inSize,
+ const void* inPtr );
+ virtual OSStatus SetFocusPart(
+ ControlPartCode inDesiredFocus,
+ RgnHandle inNnvalidRgn,
+ Boolean inFocusEverything,
+ ControlPartCode* outActualFocus );
+ virtual OSStatus TextInput(
+ TCarbonEvent& inEvent );
+ virtual OSStatus TitleChanged();
+ virtual OSStatus Track(
+ TCarbonEvent& inEvent,
+ ControlPartCode* outPartHit );
+ virtual OSStatus ValueChanged();
+
+ // Sizing
+ virtual OSStatus GetSizeConstraints(
+ HISize* outMin,
+ HISize* outMax );
+ virtual OSStatus GetOptimalSize(
+ HISize* outSize,
+ float* outBaseLine );
+
+ // Accessors
+ WindowRef GetWindowRef()
+ { return GetControlOwner( GetViewRef() ); }
+
+
+ // Drag and drop
+ virtual bool DragEnter(
+ DragRef inDrag );
+ virtual bool DragWithin(
+ DragRef inDrag );
+ virtual bool DragLeave(
+ DragRef inDrag );
+ virtual OSStatus DragReceive(
+ DragRef inDrag );
+
+ // Command processing
+ virtual OSStatus ProcessCommand(
+ const HICommand& inCommand );
+ virtual OSStatus UpdateCommandStatus(
+ const HICommand& inCommand );
+
+ // Mouse events
+ virtual OSStatus MouseDown(
+ HIPoint& inMouseLocation,
+ UInt32 inKeyModifiers,
+ EventMouseButton inMouseButton,
+ UInt32 inClickCount,
+ TCarbonEvent& inEvent);
+ virtual OSStatus MouseUp(
+ HIPoint& inMouseLocation,
+ UInt32 inKeyModifiers,
+ EventMouseButton inMouseButton,
+ UInt32 inClickCount );
+ virtual OSStatus MouseDragged(
+ HIPoint& inMouseLocation,
+ UInt32 inKeyModifiers,
+ EventMouseButton inMouseButton,
+ UInt32 inClickCount );
+ virtual OSStatus MouseEntered(
+ HIPoint& inMouseLocation,
+ UInt32 inKeyModifiers,
+ EventMouseButton inMouseButton,
+ UInt32 inClickCount );
+ virtual OSStatus MouseExited(
+ HIPoint& inMouseLocation,
+ UInt32 inKeyModifiers,
+ EventMouseButton inMouseButton,
+ UInt32 inClickCount );
+ virtual OSStatus MouseWheelMoved( EventMouseWheelAxis inAxis, SInt32 inDelta, UInt32 inKeyModifiers );
+ virtual OSStatus ContextualMenuClick( HIPoint& inMouseLocation );
+
+ // Utility
+ static OSStatus RegisterSubclass(
+ CFStringRef inID,
+ ConstructProc inProc );
+ static EventRef CreateInitializationEvent();
+ enum Interface {
+ kDragAndDrop = 1,
+ kKeyboardFocus,
+ kMouse,
+ kMouseTracking
+ };
+ virtual OSStatus ActivateInterface(
+ Interface inInterface );
+
+ OSStatus InstallTimer(
+ EventTimerInterval inFireDelay,
+ EventLoopTimerRef* outTimer );
+
+ // Debugging
+ virtual void PrintDebugInfo();
+ Boolean debugPrint;
+private:
+ static pascal OSStatus ObjectEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData );
+ static pascal OSStatus ViewEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData );
+ static pascal OSStatus WindowEventHandler(
+ EventHandlerCallRef inCallRef,
+ EventRef inEvent,
+ void* inUserData );
+ static pascal void TimerEventHandler(
+ EventLoopTimerRef inTimer,
+ void* inUserData );
+ OSStatus HandleEvent(
+ EventHandlerCallRef inCallRef,
+ TCarbonEvent& inEvent );
+
+ HIViewRef fViewRef;
+ EventHandlerRef fHandler;
+
+ EventHandlerRef mouseEventHandler;
+ OptionBits fAutoInvalidateFlags;
+
+};
+
+typedef TView* TViewPtr;
+
+#endif // TView_H_
diff --git a/scintilla/macosx/deps.mak b/scintilla/macosx/deps.mak
new file mode 100644
index 0000000..a03366b
--- /dev/null
+++ b/scintilla/macosx/deps.mak
@@ -0,0 +1,375 @@
+ExtInput.o: ExtInput.cxx ScintillaMacOSX.h TView.h TCarbonEvent.h TRect.h \
+ ../include/Platform.h ../include/Scintilla.h PlatMacOSX.h \
+ QuartzTextLayout.h QuartzTextStyle.h QuartzTextStyleAttribute.h \
+ ../include/ScintillaWidget.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../src/SVector.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
+ ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/AutoComplete.h ../src/ViewStyle.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \
+ ../src/ScintillaBase.h ScintillaCallTip.h ExtInput.h
+PlatMacOSX.o: PlatMacOSX.cxx QuartzTextLayout.h QuartzTextStyle.h \
+ QuartzTextStyleAttribute.h TCarbonEvent.h ../include/Platform.h \
+ ../include/Scintilla.h PlatMacOSX.h ../src/XPM.h \
+ ../include/ScintillaWidget.h
+ScintillaCallTip.o: ScintillaCallTip.cxx ScintillaMacOSX.h TView.h \
+ TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \
+ PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \
+ QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \
+ ../include/SciLexer.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
+ ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h
+ScintillaListBox.o: ScintillaListBox.cxx ScintillaMacOSX.h TView.h \
+ TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \
+ PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \
+ QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \
+ ../include/SciLexer.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
+ ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h \
+ ScintillaListBox.h
+ScintillaMacOSX.o: ScintillaMacOSX.cxx ScintillaMacOSX.h TView.h \
+ TCarbonEvent.h TRect.h ../include/Platform.h ../include/Scintilla.h \
+ PlatMacOSX.h QuartzTextLayout.h QuartzTextStyle.h \
+ QuartzTextStyleAttribute.h ../include/ScintillaWidget.h \
+ ../include/SciLexer.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
+ ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h ../src/ScintillaBase.h ScintillaCallTip.h \
+ ../src/UniConversion.h
+TCarbonEvent.o: TCarbonEvent.cxx TCarbonEvent.h
+TView.o: TView.cxx TView.h TCarbonEvent.h TRect.h
+AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../src/AutoComplete.h
+CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/CallTip.h
+CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/CellBuffer.h
+CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h
+ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h
+Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Decoration.h
+Document.o: ../src/Document.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/RESearch.h
+DocumentAccessor.o: ../src/DocumentAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/CellBuffer.h ../include/Scintilla.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h
+Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h
+ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h ../include/KeyWords.h \
+ ../src/ExternalLexer.h
+Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Indicator.h
+KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/KeyMap.h
+KeyWords.o: ../src/KeyWords.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAPDL.o: ../src/LexAPDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexASY.o: ../src/LexASY.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexAU3.o: ../src/LexAU3.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAVE.o: ../src/LexAVE.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAbaqus.o: ../src/LexAbaqus.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAda.o: ../src/LexAda.cxx ../include/Platform.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/PropSet.h ../include/KeyWords.h \
+ ../include/SciLexer.h
+LexAsm.o: ../src/LexAsm.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexAsn1.o: ../src/LexAsn1.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexBaan.o: ../src/LexBaan.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexBash.o: ../src/LexBash.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexBasic.o: ../src/LexBasic.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexBullant.o: ../src/LexBullant.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCLW.o: ../src/LexCLW.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCOBOL.o: ../src/LexCOBOL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexCPP.o: ../src/LexCPP.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexCSS.o: ../src/LexCSS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCaml.o: ../src/LexCaml.cxx ../include/Platform.h ../include/PropSet.h \
+ ../src/PropSetSimple.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCmake.o: ../src/LexCmake.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexConf.o: ../src/LexConf.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexCrontab.o: ../src/LexCrontab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCsound.o: ../src/LexCsound.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexD.o: ../src/LexD.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexEScript.o: ../src/LexEScript.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexEiffel.o: ../src/LexEiffel.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexErlang.o: ../src/LexErlang.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexFlagship.o: ../src/LexFlagship.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexForth.o: ../src/LexForth.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexFortran.o: ../src/LexFortran.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexGAP.o: ../src/LexGAP.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexGui4Cli.o: ../src/LexGui4Cli.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexHTML.o: ../src/LexHTML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexHaskell.o: ../src/LexHaskell.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/PropSetSimple.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexInno.o: ../src/LexInno.cxx ../include/Platform.h ../src/CharClassify.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexKix.o: ../src/LexKix.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexLisp.o: ../src/LexLisp.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexLout.o: ../src/LexLout.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexLua.o: ../src/LexLua.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexMMIXAL.o: ../src/LexMMIXAL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMPT.o: ../src/LexMPT.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexMSSQL.o: ../src/LexMSSQL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexMagik.o: ../src/LexMagik.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMatlab.o: ../src/LexMatlab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMetapost.o: ../src/LexMetapost.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexMySQL.o: ../src/LexMySQL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexNimrod.o: ../src/LexNimrod.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexNsis.o: ../src/LexNsis.cxx ../include/Platform.h ../src/CharClassify.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexOpal.o: ../src/LexOpal.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexOthers.o: ../src/LexOthers.cxx ../include/Platform.h \
+ ../src/CharClassify.h ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPB.o: ../src/LexPB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPLM.o: ../src/LexPLM.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexPOV.o: ../src/LexPOV.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPS.o: ../src/LexPS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPascal.o: ../src/LexPascal.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h \
+ ../src/CharacterSet.h
+LexPerl.o: ../src/LexPerl.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/CharacterSet.h
+LexPowerPro.o: ../src/LexPowerPro.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \
+ ../src/CharacterSet.h
+LexPowerShell.o: ../src/LexPowerShell.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexProgress.o: ../src/LexProgress.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPython.o: ../src/LexPython.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexR.o: ../src/LexR.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexRebol.o: ../src/LexRebol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexRuby.o: ../src/LexRuby.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexSML.o: ../src/LexSML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexSQL.o: ../src/LexSQL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexScriptol.o: ../src/LexScriptol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexSmalltalk.o: ../src/LexSmalltalk.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSorcus.o: ../src/LexSorcus.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSpecman.o: ../src/LexSpecman.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSpice.o: ../src/LexSpice.cxx ../include/Platform.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/PropSet.h \
+ ../include/KeyWords.h ../include/SciLexer.h
+LexTACL.o: ../src/LexTACL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexTADS3.o: ../src/LexTADS3.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexTAL.o: ../src/LexTAL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexTCL.o: ../src/LexTCL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexTeX.o: ../src/LexTeX.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h ../src/StyleContext.h
+LexVB.o: ../src/LexVB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexVHDL.o: ../src/LexVHDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexVerilog.o: ../src/LexVerilog.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexYAML.o: ../src/LexYAML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+PerLine.o: ../src/PerLine.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/CellBuffer.h ../src/PerLine.h
+PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
+ ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Selection.h \
+ ../src/PositionCache.h
+PropSet.o: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h \
+ ../src/PropSetSimple.h
+RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
+RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h
+ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h ../src/PropSetSimple.h \
+ ../include/SciLexer.h ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../include/KeyWords.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/Editor.h ../src/ScintillaBase.h
+Selection.o: ../src/Selection.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Selection.h
+Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Style.h
+StyleContext.o: ../src/StyleContext.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../src/StyleContext.h
+UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h
+ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h
+WindowAccessor.o: ../src/WindowAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h ../include/WindowAccessor.h \
+ ../include/Scintilla.h
+XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
diff --git a/scintilla/macosx/makefile b/scintilla/macosx/makefile
new file mode 100644
index 0000000..2eb0870
--- /dev/null
+++ b/scintilla/macosx/makefile
@@ -0,0 +1,115 @@
+# Make file for Scintilla on Mac OS X
+# Copyright 2002 by Evan Jones <ejones@uwaterloo.ca>
+# Based on the GTK makefile Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile assumes that Apple's version of GCC 3.1 is used and changes will be needed to use other compilers.
+# GNU make does not like \r\n line endings so should be saved to CVS in binary form.
+
+.SUFFIXES: .cxx .c .o .h .a
+CC = g++
+CCOMP = gcc
+LIBTOOL = libtool
+
+GCC_MAJOR := $(shell $(CC) -v 2>&1 | \
+ grep version | cut -d' ' -f3 | cut -d'.' -f1)
+
+# We call it "libscintilla" so when you add it to a Project Builder project,
+# Project Builder will link it correctly.
+STATICLIB=../bin/libscintilla.a
+DYNAMICLIB=../bin/libscintilla.dylib
+
+vpath %.h ../src ../include
+vpath %.cxx ../src
+
+INCLUDEDIRS=-I ../include -I ../src
+
+ifeq ($(GCC_MAJOR),3)
+# 10.4 will have GCC 4 or better, so this should only ever happen
+# on a 10.3 or older PPC box
+ARCHFLAGS=-arch ppc -faltivec -mcpu=7400 -mtune=7400 -mpowerpc -mpowerpc-gfxopt
+else
+ifndef NATIVE
+ARCH_BASE_FLAGS=/Developer/SDKs/MacOSX10.5.sdk -arch ppc -arch i386
+ARCHFLAGS=-isysroot $(ARCH_BASE_FLAGS)
+LINK_FLAGS=-Wl,-syslibroot,$(ARCH_BASE_FLAGS)
+DYN_FLAGS=$(LINK_FLAGS) -framework Carbon -bundle
+endif
+endif
+
+OPTIONS=-Wall -Wno-missing-braces -Wno-char-subscripts -DSCI_NAMESPACE -DMACOSX -DSCI_LEXER
+
+#DEBUG = 1
+
+ifdef DEBUG
+DFLAGS=-DDEBUG -g
+else
+DFLAGS=-DNDEBUG -Os
+endif
+
+ifdef CONTAINER_HANDLES_EVENTS
+CONTAINER=-DCONTAINER_HANDLES_EVENTS=1
+endif
+
+ifdef EXT_INPUT
+EXT_INPUT=-DEXT_INPUT
+EXTOBS=ExtInput.o
+endif
+
+.cxx.o:
+ $(CC) $(CXXFLAGS) $(OPTIONS) $(DFLAGS) $(CONTAINER) $(ARCHFLAGS) $(EXT_INPUT) $(INCLUDEDIRS) -c $<
+.c.o:
+ $(CCOMP) $(CXXFLAGS) $(OPTIONS) $(DFLAGS) $(CONTAINER) $(ARCHFLAGS) $(EXT_INPUT) $(INCLUDEDIRS) -w -c $<
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**LEXOBJS=\\\n\(\*.o \)
+LEXOBJS=\
+LexAbaqus.o LexAda.o LexAPDL.o LexAsm.o LexAsn1.o LexASY.o LexAU3.o LexAVE.o \
+LexBaan.o LexBash.o LexBasic.o LexBullant.o LexCaml.o LexCLW.o LexCmake.o \
+LexCOBOL.o LexConf.o LexCPP.o LexCrontab.o LexCsound.o LexCSS.o LexD.o \
+LexEiffel.o LexErlang.o LexEScript.o LexFlagship.o LexForth.o LexFortran.o \
+LexGAP.o LexGui4Cli.o LexHaskell.o LexHTML.o LexInno.o LexKix.o LexLisp.o \
+LexLout.o LexLua.o LexMagik.o LexMarkdown.o LexMatlab.o LexMetapost.o \
+LexMMIXAL.o LexMPT.o LexMSSQL.o LexMySQL.o LexNimrod.o LexNsis.o LexOpal.o \
+LexOthers.o LexPascal.o LexPB.o LexPerl.o LexPLM.o LexPOV.o LexPowerPro.o \
+LexPowerShell.o LexProgress.o LexPS.o LexPython.o LexR.o LexRebol.o LexRuby.o \
+LexScriptol.o LexSmalltalk.o LexSML.o LexSorcus.o LexSpecman.o LexSpice.o \
+LexSQL.o LexTACL.o LexTADS3.o LexTAL.o LexTCL.o LexTeX.o LexVB.o LexVerilog.o \
+LexVHDL.o LexYAML.o
+#--Autogenerated -- end of automatically generated section
+
+# The LEXOBJS have to be treated specially as the functions in them are not called from external code
+
+all: $(STATICLIB) $(LEXOBJS)
+
+shared: $(DYNAMICLIB) $(LEXOBJS)
+
+clean:
+ rm -f *.o $(COMPLIB)
+
+deps:
+ $(CC) -MM -DSCI_NAMESPACE -DMACOSX -DSCI_LEXER $(CXXFLAGS) $(INCLUDEDIRS) *.cxx ../src/*.cxx >deps.mak
+
+COMPLIB=DocumentAccessor.o WindowAccessor.o KeyWords.o StyleContext.o \
+ CharClassify.o Decoration.o Document.o PerLine.o CallTip.o PositionCache.o \
+ ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSet.o PlatMacOSX.o \
+ KeyMap.o LineMarker.o ScintillaMacOSX.o CellBuffer.o ViewStyle.o \
+ RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
+ TCarbonEvent.o TView.o ScintillaCallTip.o $(EXTOBS) \
+ $(LEXOBJS)
+
+$(STATICLIB): $(COMPLIB)
+ $(LIBTOOL) -static -o $@ $^
+
+$(DYNAMICLIB): $(COMPLIB)
+ $(CC) -dynamic -o $@ $(DYN_FLAGS) $^
+
+# Generate header files from Scintilla.iface
+../include/Scintilla_gen.h: ../include/HFacer.py ../include/Face.py ../include/Scintilla.iface
+ cd ../include && python HFacer.py
+../include/SciLexer_gen.h: ../include/HFacer.py ../include/Face.py ../include/Scintilla.iface
+ cd ../include && python HFacer.py
+../include/Scintilla.h: ../include/Scintilla_gen.h
+../include/SciLexer.h: ../include/SciLexer_gen.h
+
+# Automatically generate header dependencies with "make deps"
+include deps.mak
diff --git a/scintilla/src/AutoComplete.cxx b/scintilla/src/AutoComplete.cxx
new file mode 100644
index 0000000..e7d6164
--- /dev/null
+++ b/scintilla/src/AutoComplete.cxx
@@ -0,0 +1,178 @@
+// Scintilla source code edit control
+/** @file AutoComplete.cxx
+ ** Defines the auto completion list box.
+ **/
+// 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 <stdio.h>
+
+#include "Platform.h"
+
+#include "CharClassify.h"
+#include "AutoComplete.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+AutoComplete::AutoComplete() :
+ active(false),
+ separator(' '),
+ typesep('?'),
+ ignoreCase(false),
+ chooseSingle(false),
+ lb(0),
+ posStart(0),
+ startLen(0),
+ cancelAtStartPos(true),
+ autoHide(true),
+ dropRestOfWord(false) {
+ lb = ListBox::Allocate();
+ stopChars[0] = '\0';
+ fillUpChars[0] = '\0';
+}
+
+AutoComplete::~AutoComplete() {
+ if (lb) {
+ lb->Destroy();
+ delete lb;
+ lb = 0;
+ }
+}
+
+bool AutoComplete::Active() const {
+ return active;
+}
+
+void AutoComplete::Start(Window &parent, int ctrlID,
+ int position, Point location, int startLen_,
+ int lineHeight, bool unicodeMode) {
+ if (active) {
+ Cancel();
+ }
+ lb->Create(parent, ctrlID, location, lineHeight, unicodeMode);
+ lb->Clear();
+ active = true;
+ startLen = startLen_;
+ posStart = position;
+}
+
+void AutoComplete::SetStopChars(const char *stopChars_) {
+ strncpy(stopChars, stopChars_, sizeof(stopChars));
+ stopChars[sizeof(stopChars) - 1] = '\0';
+}
+
+bool AutoComplete::IsStopChar(char ch) {
+ return ch && strchr(stopChars, ch);
+}
+
+void AutoComplete::SetFillUpChars(const char *fillUpChars_) {
+ strncpy(fillUpChars, fillUpChars_, sizeof(fillUpChars));
+ fillUpChars[sizeof(fillUpChars) - 1] = '\0';
+}
+
+bool AutoComplete::IsFillUpChar(char ch) {
+ return ch && strchr(fillUpChars, ch);
+}
+
+void AutoComplete::SetSeparator(char separator_) {
+ separator = separator_;
+}
+
+char AutoComplete::GetSeparator() const {
+ return separator;
+}
+
+void AutoComplete::SetTypesep(char separator_) {
+ typesep = separator_;
+}
+
+char AutoComplete::GetTypesep() const {
+ return typesep;
+}
+
+void AutoComplete::SetList(const char *list) {
+ lb->SetList(list, separator, typesep);
+}
+
+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;
+ }
+}
+
+
+void AutoComplete::Move(int delta) {
+ int count = lb->Length();
+ int current = lb->GetSelection();
+ current += delta;
+ if (current >= count)
+ current = count - 1;
+ if (current < 0)
+ current = 0;
+ lb->Select(current);
+}
+
+void AutoComplete::Select(const char *word) {
+ size_t lenWord = strlen(word);
+ int location = -1;
+ const int maxItemLen=1000;
+ char item[maxItemLen];
+ int start = 0; // lower bound of the api array block to search
+ int end = lb->Length() - 1; // upper bound of the api array block to search
+ while ((start <= end) && (location == -1)) { // Binary searching loop
+ int pivot = (start + end) / 2;
+ lb->GetValue(pivot, item, maxItemLen);
+ int cond;
+ if (ignoreCase)
+ cond = CompareNCaseInsensitive(word, item, lenWord);
+ else
+ cond = strncmp(word, item, lenWord);
+ if (!cond) {
+ // Find first match
+ while (pivot > start) {
+ lb->GetValue(pivot-1, item, maxItemLen);
+ if (ignoreCase)
+ cond = CompareNCaseInsensitive(word, item, lenWord);
+ else
+ cond = strncmp(word, item, lenWord);
+ if (0 != cond)
+ break;
+ --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) {
+ start = pivot + 1;
+ }
+ }
+ if (location == -1 && autoHide)
+ Cancel();
+ else
+ lb->Select(location);
+}
+
diff --git a/scintilla/src/AutoComplete.h b/scintilla/src/AutoComplete.h
new file mode 100644
index 0000000..258a9f5
--- /dev/null
+++ b/scintilla/src/AutoComplete.h
@@ -0,0 +1,78 @@
+// Scintilla source code edit control
+/** @file AutoComplete.h
+ ** Defines the auto completion list box.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef AUTOCOMPLETE_H
+#define AUTOCOMPLETE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class AutoComplete {
+ bool active;
+ char stopChars[256];
+ char fillUpChars[256];
+ char separator;
+ char typesep; // Type seperator
+
+public:
+ bool ignoreCase;
+ bool chooseSingle;
+ ListBox *lb;
+ int posStart;
+ int startLen;
+ /// Should autocompletion be canceled if editor's currentPos <= startPos?
+ bool cancelAtStartPos;
+ bool autoHide;
+ bool dropRestOfWord;
+
+ AutoComplete();
+ ~AutoComplete();
+
+ /// Is the auto completion list displayed?
+ bool Active() const;
+
+ /// Display the auto completion list positioned to be near a character 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
+ void SetStopChars(const char *stopChars_);
+ bool IsStopChar(char ch);
+
+ /// The fillup chars are characters which, when typed, fill up the selected word
+ void SetFillUpChars(const char *fillUpChars_);
+ bool IsFillUpChar(char ch);
+
+ /// The separator character is used when interpreting the list in SetList
+ void SetSeparator(char separator_);
+ char GetSeparator() const;
+
+ /// The typesep character is used for seperating the word from the type
+ void SetTypesep(char separator_);
+ char GetTypesep() const;
+
+ /// The list string contains a sequence of words separated by the separator character
+ void SetList(const char *list);
+
+ void Show(bool show);
+ void Cancel();
+
+ /// Move the current list element by delta, scrolling appropriately
+ void Move(int delta);
+
+ /// Select a list element that starts with word as the current element
+ void Select(const char *word);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/CallTip.cxx b/scintilla/src/CallTip.cxx
new file mode 100644
index 0000000..45eff35
--- /dev/null
+++ b/scintilla/src/CallTip.cxx
@@ -0,0 +1,327 @@
+// Scintilla source code edit control
+/** @file CallTip.cxx
+ ** Code for displaying call tips.
+ **/
+// Copyright 1998-2001 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 "Platform.h"
+
+#include "Scintilla.h"
+#include "CallTip.h"
+#include <stdio.h>
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static const int insetX = 5; // text inset in x from calltip border
+static const int widthArrow = 14;
+
+CallTip::CallTip() {
+ wCallTip = 0;
+ inCallTipMode = false;
+ posStartCallTip = 0;
+ val = 0;
+ rectUp = PRectangle(0,0,0,0);
+ rectDown = PRectangle(0,0,0,0);
+ lineHeight = 1;
+ startHighlight = 0;
+ endHighlight = 0;
+ tabSize = 0;
+ useStyleCallTip = false; // for backwards compatibility
+
+#ifdef __APPLE__
+ // proper apple colours for the default
+ colourBG.desired = ColourDesired(0xff, 0xff, 0xc6);
+ colourUnSel.desired = ColourDesired(0, 0, 0);
+#else
+ colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
+ colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
+#endif
+ colourSel.desired = ColourDesired(0, 0, 0x80);
+ colourShade.desired = ColourDesired(0, 0, 0);
+ colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
+}
+
+CallTip::~CallTip() {
+ font.Release();
+ wCallTip.Destroy();
+ delete []val;
+ val = 0;
+}
+
+void CallTip::RefreshColourPalette(Palette &pal, bool want) {
+ pal.WantFind(colourBG, want);
+ pal.WantFind(colourUnSel, want);
+ pal.WantFind(colourSel, want);
+ pal.WantFind(colourShade, want);
+ pal.WantFind(colourLight, want);
+}
+
+// Although this test includes 0, we should never see a \0 character.
+static bool IsArrowCharacter(char ch) {
+ return (ch == 0) || (ch == '\001') || (ch == '\002');
+}
+
+// We ignore tabs unless a tab width has been set.
+bool CallTip::IsTabCharacter(char ch) const {
+ return (tabSize > 0) && (ch == '\t');
+}
+
+int CallTip::NextTabPos(int x) {
+ if (tabSize > 0) { // paranoia... not called unless this is true
+ x -= insetX; // position relative to text
+ x = (x + tabSize) / tabSize; // tab "number"
+ return tabSize*x + insetX; // position of next tab
+ } else {
+ return x + 1; // arbitrary
+ }
+}
+
+// Draw a section of the call tip that does not include \n in one colour.
+// The text may include up to numEnds tabs or arrow characters.
+void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
+ int posStart, int posEnd, int ytext, PRectangle rcClient,
+ bool highlight, bool draw) {
+ s += posStart;
+ int len = posEnd - posStart;
+
+ // Divide the text into sections that are all text, or that are
+ // single arrows or single tab characters (if tabSize > 0).
+ int maxEnd = 0;
+ const int numEnds = 10;
+ int ends[numEnds + 2];
+ for (int i=0; i<len; i++) {
+ if ((maxEnd < numEnds) &&
+ (IsArrowCharacter(s[i]) || IsTabCharacter(s[i])) ) {
+ if (i > 0)
+ ends[maxEnd++] = i;
+ ends[maxEnd++] = i+1;
+ }
+ }
+ ends[maxEnd++] = len;
+ int startSeg = 0;
+ int xEnd;
+ for (int seg = 0; seg<maxEnd; seg++) {
+ int endSeg = ends[seg];
+ if (endSeg > startSeg) {
+ if (IsArrowCharacter(s[startSeg])) {
+ bool upArrow = s[startSeg] == '\001';
+ rcClient.left = x;
+ rcClient.right = rcClient.left + widthArrow;
+ if (draw) {
+ const int halfWidth = widthArrow / 2 - 3;
+ const int centreX = rcClient.left + widthArrow / 2 - 1;
+ const int centreY = (rcClient.top + rcClient.bottom) / 2;
+ surface->FillRectangle(rcClient, colourBG.allocated);
+ PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1,
+ rcClient.right - 2, rcClient.bottom - 1);
+ surface->FillRectangle(rcClientInner, colourUnSel.allocated);
+
+ if (upArrow) { // Up arrow
+ Point pts[] = {
+ Point(centreX - halfWidth, centreY + halfWidth / 2),
+ Point(centreX + halfWidth, centreY + halfWidth / 2),
+ Point(centreX, centreY - halfWidth + halfWidth / 2),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ colourBG.allocated, colourBG.allocated);
+ } else { // Down arrow
+ Point pts[] = {
+ Point(centreX - halfWidth, centreY - halfWidth / 2),
+ Point(centreX + halfWidth, centreY - halfWidth / 2),
+ Point(centreX, centreY + halfWidth - halfWidth / 2),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ colourBG.allocated, colourBG.allocated);
+ }
+ }
+ xEnd = rcClient.right;
+ offsetMain = xEnd;
+ if (upArrow) {
+ rectUp = rcClient;
+ } else {
+ rectDown = rcClient;
+ }
+ } else if (IsTabCharacter(s[startSeg])) {
+ xEnd = NextTabPos(x);
+ } else {
+ xEnd = x + surface->WidthText(font, s + startSeg, endSeg - startSeg);
+ if (draw) {
+ rcClient.left = x;
+ rcClient.right = xEnd;
+ surface->DrawTextTransparent(rcClient, font, ytext,
+ s+startSeg, endSeg - startSeg,
+ highlight ? colourSel.allocated : colourUnSel.allocated);
+ }
+ }
+ x = xEnd;
+ startSeg = endSeg;
+ }
+ }
+}
+
+int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
+ PRectangle rcClientPos = wCallTip.GetClientPosition();
+ PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
+ rcClientPos.bottom - rcClientPos.top);
+ PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
+
+ // To make a nice small call tip window, it is only sized to fit most normal characters without accents
+ int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);
+
+ // For each line...
+ // Draw the definition in three parts: before highlight, highlighted, after highlight
+ int ytext = rcClient.top + ascent + 1;
+ rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
+ char *chunkVal = val;
+ bool moreChunks = true;
+ int maxWidth = 0;
+
+ while (moreChunks) {
+ char *chunkEnd = strchr(chunkVal, '\n');
+ if (chunkEnd == NULL) {
+ chunkEnd = chunkVal + strlen(chunkVal);
+ moreChunks = false;
+ }
+ int chunkOffset = chunkVal - val;
+ int chunkLength = chunkEnd - chunkVal;
+ int chunkEndOffset = chunkOffset + chunkLength;
+ int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
+ thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
+ thisStartHighlight -= chunkOffset;
+ int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
+ thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
+ thisEndHighlight -= chunkOffset;
+ rcClient.top = ytext - ascent - 1;
+
+ int x = insetX; // start each line at this inset
+
+ DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
+ ytext, rcClient, false, draw);
+ DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
+ ytext, rcClient, true, draw);
+ DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
+ ytext, rcClient, false, draw);
+
+ chunkVal = chunkEnd + 1;
+ ytext += lineHeight;
+ rcClient.bottom += lineHeight;
+ maxWidth = Platform::Maximum(maxWidth, x);
+ }
+ return maxWidth;
+}
+
+void CallTip::PaintCT(Surface *surfaceWindow) {
+ if (!val)
+ return;
+ PRectangle rcClientPos = wCallTip.GetClientPosition();
+ PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
+ rcClientPos.bottom - rcClientPos.top);
+ PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
+
+ surfaceWindow->FillRectangle(rcClient, colourBG.allocated);
+
+ offsetMain = insetX; // initial alignment assuming no arrows
+ PaintContents(surfaceWindow, true);
+
+#ifndef __APPLE__
+ // OSX doesn't put borders on "help tags"
+ // Draw a raised border around the edges of the window
+ surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
+ surfaceWindow->PenColour(colourShade.allocated);
+ surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
+ surfaceWindow->LineTo(rcClientSize.right - 1, 0);
+ surfaceWindow->PenColour(colourLight.allocated);
+ surfaceWindow->LineTo(0, 0);
+ surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
+#endif
+}
+
+void CallTip::MouseClick(Point pt) {
+ clickPlace = 0;
+ if (rectUp.Contains(pt))
+ clickPlace = 1;
+ if (rectDown.Contains(pt))
+ clickPlace = 2;
+}
+
+PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
+ const char *faceName, int size,
+ int codePage_, int characterSet, Window &wParent) {
+ clickPlace = 0;
+ delete []val;
+ val = 0;
+ val = new char[strlen(defn) + 1];
+ strcpy(val, defn);
+ codePage = codePage_;
+ Surface *surfaceMeasure = Surface::Allocate();
+ if (!surfaceMeasure)
+ return PRectangle();
+ surfaceMeasure->Init(wParent.GetID());
+ surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
+ surfaceMeasure->SetDBCSMode(codePage);
+ startHighlight = 0;
+ endHighlight = 0;
+ inCallTipMode = true;
+ posStartCallTip = pos;
+ int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
+ font.Create(faceName, characterSet, deviceHeight, false, false);
+ // Look for multiple lines in the text
+ // Only support \n here - simply means container must avoid \r!
+ int numLines = 1;
+ const char *newline;
+ const char *look = val;
+ rectUp = PRectangle(0,0,0,0);
+ rectDown = PRectangle(0,0,0,0);
+ offsetMain = insetX; // changed to right edge of any arrows
+ int width = PaintContents(surfaceMeasure, false) + insetX;
+ while ((newline = strchr(look, '\n')) != NULL) {
+ look = newline + 1;
+ numLines++;
+ }
+ lineHeight = surfaceMeasure->Height(font);
+
+ // Extra line for border and an empty line at top and bottom. The returned
+ // rectangle is aligned to the right edge of the last arrow encountered in
+ // the tip text, else to the tip text left edge.
+ int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
+ delete surfaceMeasure;
+ return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
+}
+
+void CallTip::CallTipCancel() {
+ inCallTipMode = false;
+ if (wCallTip.Created()) {
+ wCallTip.Destroy();
+ }
+}
+
+void CallTip::SetHighlight(int start, int end) {
+ // Avoid flashing by checking something has really changed
+ if ((start != startHighlight) || (end != endHighlight)) {
+ startHighlight = start;
+ endHighlight = end;
+ if (wCallTip.Created()) {
+ wCallTip.InvalidateAll();
+ }
+ }
+}
+
+// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
+// use of the STYLE_CALLTIP.
+void CallTip::SetTabSize(int tabSz) {
+ tabSize = tabSz;
+ useStyleCallTip = true;
+}
+
+// It might be better to have two access functions for this and to use
+// them for all settings of colours.
+void CallTip::SetForeBack(const ColourPair &fore, const ColourPair &back) {
+ colourBG = back;
+ colourUnSel = fore;
+}
diff --git a/scintilla/src/CallTip.h b/scintilla/src/CallTip.h
new file mode 100644
index 0000000..21b48ad
--- /dev/null
+++ b/scintilla/src/CallTip.h
@@ -0,0 +1,87 @@
+// Scintilla source code edit control
+/** @file CallTip.h
+ ** Interface to the call tip control.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CALLTIP_H
+#define CALLTIP_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class CallTip {
+ int startHighlight; // character offset to start and...
+ int endHighlight; // ...end of highlighted text
+ char *val;
+ Font font;
+ PRectangle rectUp; // rectangle of last up angle in the tip
+ PRectangle rectDown; // rectangle of last down arrow in the tip
+ int lineHeight; // vertical line spacing
+ int offsetMain; // The alignment point of the call tip
+ int tabSize; // Tab size in pixels, <=0 no TAB expand
+ bool useStyleCallTip; // if true, STYLE_CALLTIP should be used
+
+ // Private so CallTip objects can not be copied
+ CallTip(const CallTip &);
+ CallTip &operator=(const CallTip &);
+ void DrawChunk(Surface *surface, int &x, const char *s,
+ int posStart, int posEnd, int ytext, PRectangle rcClient,
+ bool highlight, bool draw);
+ int PaintContents(Surface *surfaceWindow, bool draw);
+ bool IsTabCharacter(char c) const;
+ int NextTabPos(int x);
+
+public:
+ Window wCallTip;
+ Window wDraw;
+ bool inCallTipMode;
+ int posStartCallTip;
+ ColourPair colourBG;
+ ColourPair colourUnSel;
+ ColourPair colourSel;
+ ColourPair colourShade;
+ ColourPair colourLight;
+ int codePage;
+ int clickPlace;
+
+ CallTip();
+ ~CallTip();
+
+ /// Claim or accept palette entries for the colours required to paint a calltip.
+ void RefreshColourPalette(Palette &pal, bool want);
+
+ void PaintCT(Surface *surfaceWindow);
+
+ void MouseClick(Point pt);
+
+ /// Setup the calltip and return a rectangle of the area required.
+ PRectangle CallTipStart(int pos, Point pt, const char *defn,
+ const char *faceName, int size, int codePage_,
+ int characterSet, Window &wParent);
+
+ void CallTipCancel();
+
+ /// Set a range of characters to be displayed in a highlight style.
+ /// Commonly used to highlight the current parameter.
+ void SetHighlight(int start, int end);
+
+ /// Set the tab size in pixels for the call tip. 0 or -ve means no tab expand.
+ void SetTabSize(int tabSz);
+
+ /// Used to determine which STYLE_xxxx to use for call tip information
+ bool UseStyleCallTip() const { return useStyleCallTip;}
+
+ // Modify foreground and background colours
+ void SetForeBack(const ColourPair &fore, const ColourPair &back);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/CellBuffer.cxx b/scintilla/src/CellBuffer.cxx
new file mode 100644
index 0000000..079d00a
--- /dev/null
+++ b/scintilla/src/CellBuffer.cxx
@@ -0,0 +1,656 @@
+// Scintilla source code edit control
+/** @file CellBuffer.cxx
+ ** Manages a buffer of cells.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "CellBuffer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+LineVector::LineVector() : starts(256), perLine(0) {
+ Init();
+}
+
+LineVector::~LineVector() {
+ starts.DeleteAll();
+}
+
+void LineVector::Init() {
+ starts.DeleteAll();
+ if (perLine) {
+ perLine->Init();
+ }
+}
+
+void LineVector::SetPerLine(PerLine *pl) {
+ perLine = pl;
+}
+
+void LineVector::InsertText(int line, int delta) {
+ starts.InsertText(line, delta);
+}
+
+void LineVector::InsertLine(int line, int position, bool lineStart) {
+ starts.InsertPartition(line, position);
+ if (perLine) {
+ if ((line > 0) && lineStart)
+ line--;
+ perLine->InsertLine(line);
+ }
+}
+
+void LineVector::SetLineStart(int line, int position) {
+ starts.SetPartitionStartPosition(line, position);
+}
+
+void LineVector::RemoveLine(int line) {
+ starts.RemovePartition(line);
+ if (perLine) {
+ perLine->RemoveLine(line);
+ }
+}
+
+int LineVector::LineFromPosition(int pos) const {
+ return starts.PartitionFromPosition(pos);
+}
+
+Action::Action() {
+ at = startAction;
+ position = 0;
+ data = 0;
+ lenData = 0;
+ mayCoalesce = false;
+}
+
+Action::~Action() {
+ Destroy();
+}
+
+void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) {
+ delete []data;
+ position = position_;
+ at = at_;
+ data = data_;
+ lenData = lenData_;
+ mayCoalesce = mayCoalesce_;
+}
+
+void Action::Destroy() {
+ delete []data;
+ data = 0;
+}
+
+void Action::Grab(Action *source) {
+ delete []data;
+
+ position = source->position;
+ at = source->at;
+ data = source->data;
+ lenData = source->lenData;
+ mayCoalesce = source->mayCoalesce;
+
+ // Ownership of source data transferred to this
+ source->position = 0;
+ source->at = startAction;
+ source->data = 0;
+ source->lenData = 0;
+ source->mayCoalesce = true;
+}
+
+// The undo history stores a sequence of user operations that represent the user's view of the
+// commands executed on the text.
+// Each user operation contains a sequence of text insertion and text deletion actions.
+// All the user operations are stored in a list of individual actions with 'start' actions used
+// as delimiters between user operations.
+// Initially there is one start action in the history.
+// As each action is performed, it is recorded in the history. The action may either become
+// part of the current user operation or may start a new user operation. If it is to be part of the
+// current operation, then it overwrites the current last action. If it is to be part of a new
+// operation, it is appended after the current last action.
+// After writing the new action, a new start action is appended at the end of the history.
+// The decision of whether to start a new user operation is based upon two factors. If a
+// compound operation has been explicitly started by calling BeginUndoAction and no matching
+// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
+// operation. If there is no outstanding BeginUndoAction call then a new operation is started
+// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
+// Sequences that look like typing or deletion are coalesced into a single user operation.
+
+UndoHistory::UndoHistory() {
+
+ lenActions = 100;
+ actions = new Action[lenActions];
+ maxAction = 0;
+ currentAction = 0;
+ undoSequenceDepth = 0;
+ savePoint = 0;
+
+ actions[currentAction].Create(startAction);
+}
+
+UndoHistory::~UndoHistory() {
+ delete []actions;
+ actions = 0;
+}
+
+void UndoHistory::EnsureUndoRoom() {
+ // Have to test that there is room for 2 more actions in the array
+ // as two actions may be created by the calling function
+ if (currentAction >= (lenActions - 2)) {
+ // Run out of undo nodes so extend the array
+ int lenActionsNew = lenActions * 2;
+ Action *actionsNew = new Action[lenActionsNew];
+ for (int act = 0; act <= currentAction; act++)
+ actionsNew[act].Grab(&actions[act]);
+ delete []actions;
+ lenActions = lenActionsNew;
+ actions = actionsNew;
+ }
+}
+
+void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData,
+ bool &startSequence, bool mayCoalesce) {
+ EnsureUndoRoom();
+ //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
+ //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
+ // actions[currentAction - 1].position, actions[currentAction - 1].lenData);
+ if (currentAction < savePoint) {
+ savePoint = -1;
+ }
+ int oldCurrentAction = currentAction;
+ if (currentAction >= 1) {
+ if (0 == undoSequenceDepth) {
+ // Top level actions may not always be coalesced
+ int targetAct = -1;
+ const Action *actPrevious = &(actions[currentAction + targetAct]);
+ // Container actions may forward the coalesce state of Scintilla Actions.
+ while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) {
+ targetAct--;
+ actPrevious = &(actions[currentAction + targetAct]);
+ }
+ // See if current action can be coalesced into previous action
+ // Will work if both are inserts or deletes and position is same
+ if (currentAction == savePoint) {
+ currentAction++;
+ } else if (!actions[currentAction].mayCoalesce) {
+ // Not allowed to coalesce if this set
+ currentAction++;
+ } else if (!mayCoalesce || !actPrevious->mayCoalesce) {
+ currentAction++;
+ } else if (at == containerAction || actions[currentAction].at == containerAction) {
+ ; // A coalescible containerAction
+ } else if ((at != actPrevious->at) && (actPrevious->at != startAction)) {
+ currentAction++;
+ } else if ((at == insertAction) &&
+ (position != (actPrevious->position + actPrevious->lenData))) {
+ // Insertions must be immediately after to coalesce
+ currentAction++;
+ } else if (at == removeAction) {
+ if ((lengthData == 1) || (lengthData == 2)) {
+ if ((position + lengthData) == actPrevious->position) {
+ ; // Backspace -> OK
+ } else if (position == actPrevious->position) {
+ ; // Delete -> OK
+ } else {
+ // Removals must be at same position to coalesce
+ currentAction++;
+ }
+ } else {
+ // Removals must be of one character to coalesce
+ currentAction++;
+ }
+ } else {
+ // Action coalesced.
+ }
+
+ } else {
+ // Actions not at top level are always coalesced unless this is after return to top level
+ if (!actions[currentAction].mayCoalesce)
+ currentAction++;
+ }
+ } else {
+ currentAction++;
+ }
+ startSequence = oldCurrentAction != currentAction;
+ actions[currentAction].Create(at, position, data, lengthData, mayCoalesce);
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+}
+
+void UndoHistory::BeginUndoAction() {
+ EnsureUndoRoom();
+ if (undoSequenceDepth == 0) {
+ if (actions[currentAction].at != startAction) {
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+ }
+ actions[currentAction].mayCoalesce = false;
+ }
+ undoSequenceDepth++;
+}
+
+void UndoHistory::EndUndoAction() {
+ PLATFORM_ASSERT(undoSequenceDepth > 0);
+ EnsureUndoRoom();
+ undoSequenceDepth--;
+ if (0 == undoSequenceDepth) {
+ if (actions[currentAction].at != startAction) {
+ currentAction++;
+ actions[currentAction].Create(startAction);
+ maxAction = currentAction;
+ }
+ actions[currentAction].mayCoalesce = false;
+ }
+}
+
+void UndoHistory::DropUndoSequence() {
+ undoSequenceDepth = 0;
+}
+
+void UndoHistory::DeleteUndoHistory() {
+ for (int i = 1; i < maxAction; i++)
+ actions[i].Destroy();
+ maxAction = 0;
+ currentAction = 0;
+ actions[currentAction].Create(startAction);
+ savePoint = 0;
+}
+
+void UndoHistory::SetSavePoint() {
+ savePoint = currentAction;
+}
+
+bool UndoHistory::IsSavePoint() const {
+ return savePoint == currentAction;
+}
+
+bool UndoHistory::CanUndo() const {
+ return (currentAction > 0) && (maxAction > 0);
+}
+
+int UndoHistory::StartUndo() {
+ // Drop any trailing startAction
+ if (actions[currentAction].at == startAction && currentAction > 0)
+ currentAction--;
+
+ // Count the steps in this action
+ int act = currentAction;
+ while (actions[act].at != startAction && act > 0) {
+ act--;
+ }
+ return currentAction - act;
+}
+
+const Action &UndoHistory::GetUndoStep() const {
+ return actions[currentAction];
+}
+
+void UndoHistory::CompletedUndoStep() {
+ currentAction--;
+}
+
+bool UndoHistory::CanRedo() const {
+ return maxAction > currentAction;
+}
+
+int UndoHistory::StartRedo() {
+ // Drop any leading startAction
+ if (actions[currentAction].at == startAction && currentAction < maxAction)
+ currentAction++;
+
+ // Count the steps in this action
+ int act = currentAction;
+ while (actions[act].at != startAction && act < maxAction) {
+ act++;
+ }
+ return act - currentAction;
+}
+
+const Action &UndoHistory::GetRedoStep() const {
+ return actions[currentAction];
+}
+
+void UndoHistory::CompletedRedoStep() {
+ currentAction++;
+}
+
+CellBuffer::CellBuffer() {
+ readOnly = false;
+ collectingUndo = true;
+}
+
+CellBuffer::~CellBuffer() {
+}
+
+char CellBuffer::CharAt(int position) const {
+ return substance.ValueAt(position);
+}
+
+void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const {
+ if (lengthRetrieve < 0)
+ return;
+ if (position < 0)
+ return;
+ if ((position + lengthRetrieve) > substance.Length()) {
+ Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position,
+ lengthRetrieve, substance.Length());
+ return;
+ }
+
+ for (int i=0; i<lengthRetrieve; i++) {
+ *buffer++ = substance.ValueAt(position + i);
+ }
+}
+
+char CellBuffer::StyleAt(int position) const {
+ return style.ValueAt(position);
+}
+
+const char *CellBuffer::BufferPointer() {
+ return substance.BufferPointer();
+}
+
+// The char* returned is to an allocation owned by the undo history
+const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) {
+ char *data = 0;
+ // InsertString and DeleteChars are the bottleneck though which all changes occur
+ if (!readOnly) {
+ if (collectingUndo) {
+ // Save into the undo/redo stack, but only the characters - not the formatting
+ // This takes up about half load time
+ data = new char[insertLength];
+ for (int i = 0; i < insertLength; i++) {
+ data[i] = s[i];
+ }
+ uh.AppendAction(insertAction, position, data, insertLength, startSequence);
+ }
+
+ BasicInsertString(position, s, insertLength);
+ }
+ return data;
+}
+
+bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) {
+ styleValue &= mask;
+ char curVal = style.ValueAt(position);
+ if ((curVal & mask) != styleValue) {
+ style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) {
+ bool changed = false;
+ PLATFORM_ASSERT(lengthStyle == 0 ||
+ (lengthStyle > 0 && lengthStyle + position <= style.Length()));
+ while (lengthStyle--) {
+ char curVal = style.ValueAt(position);
+ if ((curVal & mask) != styleValue) {
+ style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
+ changed = true;
+ }
+ position++;
+ }
+ return changed;
+}
+
+// The char* returned is to an allocation owned by the undo history
+const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) {
+ // InsertString and DeleteChars are the bottleneck though which all changes occur
+ PLATFORM_ASSERT(deleteLength > 0);
+ char *data = 0;
+ if (!readOnly) {
+ if (collectingUndo) {
+ // Save into the undo/redo stack, but only the characters - not the formatting
+ data = new char[deleteLength];
+ for (int i = 0; i < deleteLength; i++) {
+ data[i] = substance.ValueAt(position + i);
+ }
+ uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
+ }
+
+ BasicDeleteChars(position, deleteLength);
+ }
+ return data;
+}
+
+int CellBuffer::Length() const {
+ return substance.Length();
+}
+
+void CellBuffer::Allocate(int newSize) {
+ substance.ReAllocate(newSize);
+ style.ReAllocate(newSize);
+}
+
+void CellBuffer::SetPerLine(PerLine *pl) {
+ lv.SetPerLine(pl);
+}
+
+int CellBuffer::Lines() const {
+ return lv.Lines();
+}
+
+int CellBuffer::LineStart(int line) const {
+ if (line < 0)
+ return 0;
+ else if (line >= Lines())
+ return Length();
+ else
+ return lv.LineStart(line);
+}
+
+bool CellBuffer::IsReadOnly() const {
+ return readOnly;
+}
+
+void CellBuffer::SetReadOnly(bool set) {
+ readOnly = set;
+}
+
+void CellBuffer::SetSavePoint() {
+ uh.SetSavePoint();
+}
+
+bool CellBuffer::IsSavePoint() {
+ return uh.IsSavePoint();
+}
+
+// Without undo
+
+void CellBuffer::InsertLine(int line, int position, bool lineStart) {
+ lv.InsertLine(line, position, lineStart);
+}
+
+void CellBuffer::RemoveLine(int line) {
+ lv.RemoveLine(line);
+}
+
+void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
+ if (insertLength == 0)
+ return;
+ PLATFORM_ASSERT(insertLength > 0);
+
+ substance.InsertFromArray(position, s, 0, insertLength);
+ style.InsertValue(position, insertLength, 0);
+
+ int lineInsert = lv.LineFromPosition(position) + 1;
+ bool atLineStart = lv.LineStart(lineInsert-1) == position;
+ // Point all the lines after the insertion point further along in the buffer
+ lv.InsertText(lineInsert-1, insertLength);
+ char chPrev = substance.ValueAt(position - 1);
+ char chAfter = substance.ValueAt(position + insertLength);
+ if (chPrev == '\r' && chAfter == '\n') {
+ // Splitting up a crlf pair at position
+ InsertLine(lineInsert, position, false);
+ lineInsert++;
+ }
+ char ch = ' ';
+ for (int i = 0; i < insertLength; i++) {
+ ch = s[i];
+ if (ch == '\r') {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ } else if (ch == '\n') {
+ if (chPrev == '\r') {
+ // Patch up what was end of line
+ lv.SetLineStart(lineInsert - 1, (position + i) + 1);
+ } else {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
+ }
+ chPrev = ch;
+ }
+ // Joining two lines where last insertion is cr and following substance starts with lf
+ if (chAfter == '\n') {
+ if (ch == '\r') {
+ // End of line already in buffer so drop the newly created one
+ RemoveLine(lineInsert - 1);
+ }
+ }
+}
+
+void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
+ if (deleteLength == 0)
+ return;
+
+ if ((position == 0) && (deleteLength == substance.Length())) {
+ // If whole buffer is being deleted, faster to reinitialise lines data
+ // than to delete each line.
+ lv.Init();
+ } else {
+ // Have to fix up line positions before doing deletion as looking at text in buffer
+ // to work out which lines have been removed
+
+ int lineRemove = lv.LineFromPosition(position) + 1;
+ lv.InsertText(lineRemove-1, - (deleteLength));
+ char chPrev = substance.ValueAt(position - 1);
+ char chBefore = chPrev;
+ char chNext = substance.ValueAt(position);
+ bool ignoreNL = false;
+ if (chPrev == '\r' && chNext == '\n') {
+ // Move back one
+ lv.SetLineStart(lineRemove, position);
+ lineRemove++;
+ ignoreNL = true; // First \n is not real deletion
+ }
+
+ char ch = chNext;
+ for (int i = 0; i < deleteLength; i++) {
+ chNext = substance.ValueAt(position + i + 1);
+ if (ch == '\r') {
+ if (chNext != '\n') {
+ RemoveLine(lineRemove);
+ }
+ } else if (ch == '\n') {
+ if (ignoreNL) {
+ ignoreNL = false; // Further \n are real deletions
+ } else {
+ RemoveLine(lineRemove);
+ }
+ }
+
+ ch = chNext;
+ }
+ // May have to fix up end if last deletion causes cr to be next to lf
+ // or removes one of a crlf pair
+ char chAfter = substance.ValueAt(position + deleteLength);
+ if (chBefore == '\r' && chAfter == '\n') {
+ // Using lineRemove-1 as cr ended line before start of deletion
+ RemoveLine(lineRemove - 1);
+ lv.SetLineStart(lineRemove - 1, position + 1);
+ }
+ }
+ substance.DeleteRange(position, deleteLength);
+ style.DeleteRange(position, deleteLength);
+}
+
+bool CellBuffer::SetUndoCollection(bool collectUndo) {
+ collectingUndo = collectUndo;
+ uh.DropUndoSequence();
+ return collectingUndo;
+}
+
+bool CellBuffer::IsCollectingUndo() const {
+ return collectingUndo;
+}
+
+void CellBuffer::BeginUndoAction() {
+ uh.BeginUndoAction();
+}
+
+void CellBuffer::EndUndoAction() {
+ uh.EndUndoAction();
+}
+
+void CellBuffer::AddUndoAction(int token, bool mayCoalesce) {
+ bool startSequence;
+ uh.AppendAction(containerAction, token, 0, 0, startSequence, mayCoalesce);
+}
+
+void CellBuffer::DeleteUndoHistory() {
+ uh.DeleteUndoHistory();
+}
+
+bool CellBuffer::CanUndo() {
+ return uh.CanUndo();
+}
+
+int CellBuffer::StartUndo() {
+ return uh.StartUndo();
+}
+
+const Action &CellBuffer::GetUndoStep() const {
+ return uh.GetUndoStep();
+}
+
+void CellBuffer::PerformUndoStep() {
+ const Action &actionStep = uh.GetUndoStep();
+ if (actionStep.at == insertAction) {
+ BasicDeleteChars(actionStep.position, actionStep.lenData);
+ } else if (actionStep.at == removeAction) {
+ BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
+ }
+ uh.CompletedUndoStep();
+}
+
+bool CellBuffer::CanRedo() {
+ return uh.CanRedo();
+}
+
+int CellBuffer::StartRedo() {
+ return uh.StartRedo();
+}
+
+const Action &CellBuffer::GetRedoStep() const {
+ return uh.GetRedoStep();
+}
+
+void CellBuffer::PerformRedoStep() {
+ const Action &actionStep = uh.GetRedoStep();
+ if (actionStep.at == insertAction) {
+ BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
+ } else if (actionStep.at == removeAction) {
+ BasicDeleteChars(actionStep.position, actionStep.lenData);
+ }
+ uh.CompletedRedoStep();
+}
+
diff --git a/scintilla/src/CellBuffer.h b/scintilla/src/CellBuffer.h
new file mode 100644
index 0000000..3e5da88
--- /dev/null
+++ b/scintilla/src/CellBuffer.h
@@ -0,0 +1,208 @@
+// Scintilla source code edit control
+/** @file CellBuffer.h
+ ** Manages the text of the document.
+ **/
+// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CELLBUFFER_H
+#define CELLBUFFER_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+// Interface to per-line data that wants to see each line insertion and deletion
+class PerLine {
+public:
+ virtual ~PerLine() {}
+ virtual void Init()=0;
+ virtual void InsertLine(int)=0;
+ virtual void RemoveLine(int)=0;
+};
+
+/**
+ * The line vector contains information about each of the lines in a cell buffer.
+ */
+class LineVector {
+
+ Partitioning starts;
+ PerLine *perLine;
+
+public:
+
+ LineVector();
+ ~LineVector();
+ void Init();
+ void SetPerLine(PerLine *pl);
+
+ void InsertText(int line, int delta);
+ void InsertLine(int line, int position, bool lineStart);
+ void SetLineStart(int line, int position);
+ void RemoveLine(int line);
+ int Lines() const {
+ return starts.Partitions();
+ }
+ int LineFromPosition(int pos) const;
+ int LineStart(int line) const {
+ return starts.PositionFromPartition(line);
+ }
+
+ int MarkValue(int line);
+ int AddMark(int line, int marker);
+ void MergeMarkers(int pos);
+ void DeleteMark(int line, int markerNum, bool all);
+ void DeleteMarkFromHandle(int markerHandle);
+ int LineFromHandle(int markerHandle);
+
+ void ClearLevels();
+ int SetLevel(int line, int level);
+ int GetLevel(int line);
+
+ int SetLineState(int line, int state);
+ int GetLineState(int line);
+ int GetMaxLineState();
+
+};
+
+enum actionType { insertAction, removeAction, startAction, containerAction };
+
+/**
+ * Actions are used to store all the information required to perform one undo/redo step.
+ */
+class Action {
+public:
+ actionType at;
+ int position;
+ char *data;
+ int lenData;
+ bool mayCoalesce;
+
+ Action();
+ ~Action();
+ void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true);
+ void Destroy();
+ void Grab(Action *source);
+};
+
+/**
+ *
+ */
+class UndoHistory {
+ Action *actions;
+ int lenActions;
+ int maxAction;
+ int currentAction;
+ int undoSequenceDepth;
+ int savePoint;
+
+ void EnsureUndoRoom();
+
+public:
+ UndoHistory();
+ ~UndoHistory();
+
+ void AppendAction(actionType at, int position, char *data, int length, bool &startSequence, bool mayCoalesce=true);
+
+ void BeginUndoAction();
+ void EndUndoAction();
+ void DropUndoSequence();
+ void DeleteUndoHistory();
+
+ /// The save point is a marker in the undo stack where the container has stated that
+ /// the buffer was saved. Undo and redo can move over the save point.
+ void SetSavePoint();
+ bool IsSavePoint() const;
+
+ /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
+ /// called that many times. Similarly for redo.
+ bool CanUndo() const;
+ int StartUndo();
+ const Action &GetUndoStep() const;
+ void CompletedUndoStep();
+ bool CanRedo() const;
+ int StartRedo();
+ const Action &GetRedoStep() const;
+ void CompletedRedoStep();
+};
+
+/**
+ * Holder for an expandable array of characters that supports undo and line markers.
+ * Based on article "Data Structures in a Bit-Mapped Text Editor"
+ * by Wilfred J. Hansen, Byte January 1987, page 183.
+ */
+class CellBuffer {
+private:
+ SplitVector<char> substance;
+ SplitVector<char> style;
+ bool readOnly;
+
+ bool collectingUndo;
+ UndoHistory uh;
+
+ LineVector lv;
+
+public:
+
+ CellBuffer();
+ ~CellBuffer();
+
+ /// Retrieving positions outside the range of the buffer works and returns 0
+ char CharAt(int position) const;
+ void GetCharRange(char *buffer, int position, int lengthRetrieve) const;
+ char StyleAt(int position) const;
+ const char *BufferPointer();
+
+ int Length() const;
+ void Allocate(int newSize);
+ void SetPerLine(PerLine *pl);
+ int Lines() const;
+ int LineStart(int line) const;
+ int LineFromPosition(int pos) const { return lv.LineFromPosition(pos); }
+ void InsertLine(int line, int position, bool lineStart);
+ void RemoveLine(int line);
+ const char *InsertString(int position, const char *s, int insertLength, bool &startSequence);
+
+ /// 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.
+ bool SetStyleAt(int position, char styleValue, char mask='\377');
+ bool SetStyleFor(int position, int length, char styleValue, char mask);
+
+ const char *DeleteChars(int position, int deleteLength, bool &startSequence);
+
+ bool IsReadOnly() const;
+ void SetReadOnly(bool set);
+
+ /// The save point is a marker in the undo stack where the container has stated that
+ /// the buffer was saved. Undo and redo can move over the save point.
+ void SetSavePoint();
+ bool IsSavePoint();
+
+ /// Actions without undo
+ void BasicInsertString(int position, const char *s, int insertLength);
+ void BasicDeleteChars(int position, int deleteLength);
+
+ bool SetUndoCollection(bool collectUndo);
+ bool IsCollectingUndo() const;
+ void BeginUndoAction();
+ void EndUndoAction();
+ void AddUndoAction(int token, bool mayCoalesce);
+ void DeleteUndoHistory();
+
+ /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
+ /// called that many times. Similarly for redo.
+ bool CanUndo();
+ int StartUndo();
+ const Action &GetUndoStep() const;
+ void PerformUndoStep();
+ bool CanRedo();
+ int StartRedo();
+ const Action &GetRedoStep() const;
+ void PerformRedoStep();
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/CharClassify.cxx b/scintilla/src/CharClassify.cxx
new file mode 100644
index 0000000..c2857b7
--- /dev/null
+++ b/scintilla/src/CharClassify.cxx
@@ -0,0 +1,78 @@
+// Scintilla source code edit control
+/** @file CharClassify.cxx
+ ** Character classifications used by Document and RESearch.
+ **/
+// Copyright 2006 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "CharClassify.h"
+
+// Shut up annoying Visual C++ warnings:
+#ifdef _MSC_VER
+#pragma warning(disable: 4514)
+#endif
+
+CharClassify::CharClassify() {
+ SetDefaultCharClasses(true);
+}
+
+void CharClassify::SetDefaultCharClasses(bool includeWordClass) {
+ // Initialize all char classes to default values
+ for (int ch = 0; ch < 256; ch++) {
+ if (ch == '\r' || ch == '\n')
+ charClass[ch] = ccNewLine;
+ else if (ch < 0x20 || ch == ' ')
+ charClass[ch] = ccSpace;
+ else if (includeWordClass && (ch >= 0x80 || isalnum(ch) || ch == '_'))
+ charClass[ch] = ccWord;
+ else
+ charClass[ch] = ccPunctuation;
+ }
+}
+
+void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) {
+ // Apply the newCharClass to the specifed chars
+ if (chars) {
+ while (*chars) {
+ charClass[*chars] = static_cast<unsigned char>(newCharClass);
+ chars++;
+ }
+ }
+}
+
+int CompareCaseInsensitive(const char *a, const char *b) {
+ while (*a && *b) {
+ if (*a != *b) {
+ char upperA = MakeUpperCase(*a);
+ char upperB = MakeUpperCase(*b);
+ if (upperA != upperB)
+ return upperA - upperB;
+ }
+ a++;
+ b++;
+ }
+ // Either *a or *b is nul
+ return *a - *b;
+}
+
+int CompareNCaseInsensitive(const char *a, const char *b, size_t len) {
+ while (*a && *b && len) {
+ if (*a != *b) {
+ char upperA = MakeUpperCase(*a);
+ char upperB = MakeUpperCase(*b);
+ if (upperA != upperB)
+ return upperA - upperB;
+ }
+ a++;
+ b++;
+ len--;
+ }
+ if (len == 0)
+ return 0;
+ else
+ // Either *a or *b is nul
+ return *a - *b;
+}
diff --git a/scintilla/src/CharClassify.h b/scintilla/src/CharClassify.h
new file mode 100644
index 0000000..947b1a3
--- /dev/null
+++ b/scintilla/src/CharClassify.h
@@ -0,0 +1,37 @@
+// Scintilla source code edit control
+/** @file CharClassify.h
+ ** Character classifications used by Document and RESearch.
+ **/
+// Copyright 2006-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CHARCLASSIFY_H
+#define CHARCLASSIFY_H
+
+class CharClassify {
+public:
+ CharClassify();
+
+ enum cc { ccSpace, ccNewLine, ccWord, ccPunctuation };
+ void SetDefaultCharClasses(bool includeWordClass);
+ void SetCharClasses(const unsigned char *chars, cc newCharClass);
+ cc GetClass(unsigned char ch) const { return static_cast<cc>(charClass[ch]);}
+ bool IsWord(unsigned char ch) const { return static_cast<cc>(charClass[ch]) == ccWord;}
+
+private:
+ enum { maxChar=256 };
+ unsigned char charClass[maxChar]; // not type cc to save space
+};
+
+// These functions are implemented because each platform calls them something different.
+int CompareCaseInsensitive(const char *a, const char *b);
+int CompareNCaseInsensitive(const char *a, const char *b, size_t len);
+
+inline char MakeUpperCase(char ch) {
+ if (ch < 'a' || ch > 'z')
+ return ch;
+ else
+ return static_cast<char>(ch - 'a' + 'A');
+}
+
+#endif
diff --git a/scintilla/src/CharacterSet.h b/scintilla/src/CharacterSet.h
new file mode 100644
index 0000000..761b644
--- /dev/null
+++ b/scintilla/src/CharacterSet.h
@@ -0,0 +1,59 @@
+// Scintilla source code edit control
+/** @file CharacterSet.h
+ ** Encapsulates a set of characters. Used to test if a character is within a set.
+ **/
+// Copyright 2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+class CharacterSet {
+ int size;
+ bool valueAfter;
+ bool *bset;
+public:
+ enum setBase {
+ setNone=0,
+ setLower=1,
+ setUpper=2,
+ setDigits=4,
+ setAlpha=setLower|setUpper,
+ setAlphaNum=setAlpha|setDigits
+ };
+ CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) {
+ size = size_;
+ valueAfter = valueAfter_;
+ bset = new bool[size];
+ for (int i=0; i < size; i++) {
+ bset[i] = false;
+ }
+ AddString(initialSet);
+ if (base & setLower)
+ AddString("abcdefghijklmnopqrstuvwxyz");
+ if (base & setUpper)
+ AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ if (base & setDigits)
+ AddString("0123456789");
+ }
+ ~CharacterSet() {
+ delete []bset;
+ bset = 0;
+ size = 0;
+ }
+ void Add(int val) {
+ PLATFORM_ASSERT(val >= 0);
+ PLATFORM_ASSERT(val < size);
+ bset[val] = true;
+ }
+ void AddString(const char *CharacterSet) {
+ for (const char *cp=CharacterSet; *cp; cp++) {
+ int val = static_cast<unsigned char>(*cp);
+ PLATFORM_ASSERT(val >= 0);
+ PLATFORM_ASSERT(val < size);
+ bset[val] = true;
+ }
+ }
+ bool Contains(int val) const {
+ PLATFORM_ASSERT(val >= 0);
+ if (val < 0) return false;
+ return (val < size) ? bset[val] : valueAfter;
+ }
+};
diff --git a/scintilla/src/ContractionState.cxx b/scintilla/src/ContractionState.cxx
new file mode 100644
index 0000000..5782182
--- /dev/null
+++ b/scintilla/src/ContractionState.cxx
@@ -0,0 +1,251 @@
+// Scintilla source code edit control
+/** @file ContractionState.cxx
+ ** Manages visibility of lines for folding and wrapping.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
+ //InsertLine(0);
+}
+
+ContractionState::~ContractionState() {
+ Clear();
+}
+
+void ContractionState::EnsureData() {
+ if (OneToOne()) {
+ visible = new RunStyles();
+ expanded = new RunStyles();
+ heights = new RunStyles();
+ displayLines = new Partitioning(4);
+ InsertLines(0, linesInDocument);
+ }
+}
+
+void ContractionState::Clear() {
+ delete visible;
+ visible = 0;
+ delete expanded;
+ expanded = 0;
+ delete heights;
+ heights = 0;
+ delete displayLines;
+ displayLines = 0;
+ linesInDocument = 1;
+}
+
+int ContractionState::LinesInDoc() const {
+ if (OneToOne()) {
+ return linesInDocument;
+ } else {
+ return displayLines->Partitions() - 1;
+ }
+}
+
+int ContractionState::LinesDisplayed() const {
+ if (OneToOne()) {
+ return linesInDocument;
+ } else {
+ return displayLines->PositionFromPartition(LinesInDoc());
+ }
+}
+
+int ContractionState::DisplayFromDoc(int lineDoc) const {
+ if (OneToOne()) {
+ return lineDoc;
+ } else {
+ if (lineDoc > displayLines->Partitions())
+ lineDoc = displayLines->Partitions();
+ return displayLines->PositionFromPartition(lineDoc);
+ }
+}
+
+int ContractionState::DocFromDisplay(int lineDisplay) const {
+ if (OneToOne()) {
+ return lineDisplay;
+ } else {
+ if (lineDisplay <= 0) {
+ return 0;
+ }
+ if (lineDisplay > LinesDisplayed()) {
+ return displayLines->PartitionFromPosition(LinesDisplayed());
+ }
+ int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
+ PLATFORM_ASSERT(GetVisible(lineDoc));
+ return lineDoc;
+ }
+}
+
+void ContractionState::InsertLine(int lineDoc) {
+ if (OneToOne()) {
+ linesInDocument++;
+ } else {
+ visible->InsertSpace(lineDoc, 1);
+ visible->SetValueAt(lineDoc, 1);
+ expanded->InsertSpace(lineDoc, 1);
+ expanded->SetValueAt(lineDoc, 1);
+ heights->InsertSpace(lineDoc, 1);
+ heights->SetValueAt(lineDoc, 1);
+ int lineDisplay = DisplayFromDoc(lineDoc);
+ displayLines->InsertPartition(lineDoc, lineDisplay);
+ displayLines->InsertText(lineDoc, 1);
+ }
+}
+
+void ContractionState::InsertLines(int lineDoc, int lineCount) {
+ for (int l = 0; l < lineCount; l++) {
+ InsertLine(lineDoc + l);
+ }
+ Check();
+}
+
+void ContractionState::DeleteLine(int lineDoc) {
+ if (OneToOne()) {
+ linesInDocument--;
+ } else {
+ if (GetVisible(lineDoc)) {
+ displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
+ }
+ displayLines->RemovePartition(lineDoc);
+ visible->DeleteRange(lineDoc, 1);
+ expanded->DeleteRange(lineDoc, 1);
+ heights->DeleteRange(lineDoc, 1);
+ }
+}
+
+void ContractionState::DeleteLines(int lineDoc, int lineCount) {
+ for (int l = 0; l < lineCount; l++) {
+ DeleteLine(lineDoc);
+ }
+ Check();
+}
+
+bool ContractionState::GetVisible(int lineDoc) const {
+ if (OneToOne()) {
+ return true;
+ } else {
+ if (lineDoc >= visible->Length())
+ return true;
+ return visible->ValueAt(lineDoc) == 1;
+ }
+}
+
+bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
+ if (OneToOne() && visible_) {
+ return false;
+ } else {
+ EnsureData();
+ int delta = 0;
+ Check();
+ if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
+ for (int line = lineDocStart; line <= lineDocEnd; line++) {
+ if (GetVisible(line) != visible_) {
+ int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
+ visible->SetValueAt(line, visible_ ? 1 : 0);
+ displayLines->InsertText(line, difference);
+ delta += difference;
+ }
+ }
+ } else {
+ return false;
+ }
+ Check();
+ return delta != 0;
+ }
+}
+
+bool ContractionState::GetExpanded(int lineDoc) const {
+ if (OneToOne()) {
+ return true;
+ } else {
+ Check();
+ return expanded->ValueAt(lineDoc) == 1;
+ }
+}
+
+bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
+ if (OneToOne() && expanded_) {
+ return false;
+ } else {
+ EnsureData();
+ if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
+ expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
+ Check();
+ return true;
+ } else {
+ Check();
+ return false;
+ }
+ }
+}
+
+int ContractionState::GetHeight(int lineDoc) const {
+ if (OneToOne()) {
+ return 1;
+ } else {
+ return heights->ValueAt(lineDoc);
+ }
+}
+
+// Set the number of display lines needed for this line.
+// Return true if this is a change.
+bool ContractionState::SetHeight(int lineDoc, int height) {
+ if (OneToOne() && (height == 1)) {
+ return false;
+ } else {
+ EnsureData();
+ if (GetHeight(lineDoc) != height) {
+ if (GetVisible(lineDoc)) {
+ displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
+ }
+ heights->SetValueAt(lineDoc, height);
+ Check();
+ return true;
+ } else {
+ Check();
+ return false;
+ }
+ }
+}
+
+void ContractionState::ShowAll() {
+ int lines = LinesInDoc();
+ Clear();
+ linesInDocument = lines;
+}
+
+// Debugging checks
+
+void ContractionState::Check() const {
+#ifdef CHECK_CORRECTNESS
+ for (int vline = 0; vline < LinesDisplayed(); vline++) {
+ const int lineDoc = DocFromDisplay(vline);
+ PLATFORM_ASSERT(GetVisible(lineDoc));
+ }
+ for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
+ const int displayThis = DisplayFromDoc(lineDoc);
+ const int displayNext = DisplayFromDoc(lineDoc + 1);
+ const int height = displayNext - displayThis;
+ PLATFORM_ASSERT(height >= 0);
+ if (GetVisible(lineDoc)) {
+ PLATFORM_ASSERT(GetHeight(lineDoc) == height);
+ } else {
+ PLATFORM_ASSERT(0 == height);
+ }
+ }
+#endif
+}
diff --git a/scintilla/src/ContractionState.h b/scintilla/src/ContractionState.h
new file mode 100644
index 0000000..20a9856
--- /dev/null
+++ b/scintilla/src/ContractionState.h
@@ -0,0 +1,66 @@
+// Scintilla source code edit control
+/** @file ContractionState.h
+ ** Manages visibility of lines for folding and wrapping.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CONTRACTIONSTATE_H
+#define CONTRACTIONSTATE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class ContractionState {
+ // These contain 1 element for every document line.
+ RunStyles *visible;
+ RunStyles *expanded;
+ RunStyles *heights;
+ Partitioning *displayLines;
+ int linesInDocument;
+
+ void EnsureData();
+
+ bool OneToOne() const {
+ // True when each document line is exactly one display line so need for
+ // complex data structures.
+ return visible == 0;
+ }
+
+public:
+ ContractionState();
+ virtual ~ContractionState();
+
+ void Clear();
+
+ int LinesInDoc() const;
+ int LinesDisplayed() const;
+ int DisplayFromDoc(int lineDoc) const;
+ int DocFromDisplay(int lineDisplay) const;
+
+ void InsertLine(int lineDoc);
+ void InsertLines(int lineDoc, int lineCount);
+ void DeleteLine(int lineDoc);
+ void DeleteLines(int lineDoc, int lineCount);
+
+ bool GetVisible(int lineDoc) const;
+ bool SetVisible(int lineDocStart, int lineDocEnd, bool visible);
+
+ bool GetExpanded(int lineDoc) const;
+ bool SetExpanded(int lineDoc, bool expanded);
+
+ int GetHeight(int lineDoc) const;
+ bool SetHeight(int lineDoc, int height);
+
+ void ShowAll();
+ void Check() const;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/Decoration.cxx b/scintilla/src/Decoration.cxx
new file mode 100644
index 0000000..cb84e26
--- /dev/null
+++ b/scintilla/src/Decoration.cxx
@@ -0,0 +1,188 @@
+/** @file Decoration.cxx
+ ** Visual elements added over text.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "Decoration.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) {
+}
+
+Decoration::~Decoration() {
+}
+
+bool Decoration::Empty() {
+ return rs.starts->Partitions() == 1;
+}
+
+DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0),
+ lengthDocument(0), root(0), clickNotified(false) {
+}
+
+DecorationList::~DecorationList() {
+ Decoration *deco = root;
+ while (deco) {
+ Decoration *decoNext = deco->next;
+ delete deco;
+ deco = decoNext;
+ }
+ root = 0;
+ current = 0;
+}
+
+Decoration *DecorationList::DecorationFromIndicator(int indicator) {
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ if (deco->indicator == indicator) {
+ return deco;
+ }
+ }
+ return 0;
+}
+
+Decoration *DecorationList::Create(int indicator, int length) {
+ currentIndicator = indicator;
+ Decoration *decoNew = new Decoration(indicator);
+ decoNew->rs.InsertSpace(0, length);
+
+ Decoration *decoPrev = 0;
+ Decoration *deco = root;
+
+ while (deco && (deco->indicator < indicator)) {
+ decoPrev = deco;
+ deco = deco->next;
+ }
+ if (decoPrev == 0) {
+ decoNew->next = root;
+ root = decoNew;
+ } else {
+ decoNew->next = deco;
+ decoPrev->next = decoNew;
+ }
+ return decoNew;
+}
+
+void DecorationList::Delete(int indicator) {
+ Decoration *decoToDelete = 0;
+ if (root) {
+ if (root->indicator == indicator) {
+ decoToDelete = root;
+ root = root->next;
+ } else {
+ Decoration *deco=root;
+ while (deco->next && !decoToDelete) {
+ if (deco->next && deco->next->indicator == indicator) {
+ decoToDelete = deco->next;
+ deco->next = decoToDelete->next;
+ } else {
+ deco = deco->next;
+ }
+ }
+ }
+ }
+ if (decoToDelete) {
+ delete decoToDelete;
+ current = 0;
+ }
+}
+
+void DecorationList::SetCurrentIndicator(int indicator) {
+ currentIndicator = indicator;
+ current = DecorationFromIndicator(indicator);
+ currentValue = 1;
+}
+
+void DecorationList::SetCurrentValue(int value) {
+ currentValue = value ? value : 1;
+}
+
+bool DecorationList::FillRange(int &position, int value, int &fillLength) {
+ if (!current) {
+ current = DecorationFromIndicator(currentIndicator);
+ if (!current) {
+ current = Create(currentIndicator, lengthDocument);
+ }
+ }
+ bool changed = current->rs.FillRange(position, value, fillLength);
+ if (current->Empty()) {
+ Delete(currentIndicator);
+ }
+ return changed;
+}
+
+void DecorationList::InsertSpace(int position, int insertLength) {
+ lengthDocument += insertLength;
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ deco->rs.InsertSpace(position, insertLength);
+ }
+}
+
+void DecorationList::DeleteRange(int position, int deleteLength) {
+ lengthDocument -= deleteLength;
+ Decoration *deco;
+ for (deco=root; deco; deco = deco->next) {
+ deco->rs.DeleteRange(position, deleteLength);
+ }
+ DeleteAnyEmpty();
+}
+
+void DecorationList::DeleteAnyEmpty() {
+ Decoration *deco = root;
+ while (deco) {
+ if (deco->Empty()) {
+ Delete(deco->indicator);
+ deco = root;
+ } else {
+ deco = deco->next;
+ }
+ }
+}
+
+int DecorationList::AllOnFor(int position) {
+ int mask = 0;
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ if (deco->rs.ValueAt(position)) {
+ mask |= 1 << deco->indicator;
+ }
+ }
+ return mask;
+}
+
+int DecorationList::ValueAt(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.ValueAt(position);
+ }
+ return 0;
+}
+
+int DecorationList::Start(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.StartRun(position);
+ }
+ return 0;
+}
+
+int DecorationList::End(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.EndRun(position);
+ }
+ return 0;
+}
diff --git a/scintilla/src/Decoration.h b/scintilla/src/Decoration.h
new file mode 100644
index 0000000..2b75f97
--- /dev/null
+++ b/scintilla/src/Decoration.h
@@ -0,0 +1,64 @@
+/** @file Decoration.h
+ ** Visual elements added over text.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef DECORATION_H
+#define DECORATION_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class Decoration {
+public:
+ Decoration *next;
+ RunStyles rs;
+ int indicator;
+
+ Decoration(int indicator_);
+ ~Decoration();
+
+ bool Empty();
+};
+
+class DecorationList {
+ int currentIndicator;
+ int currentValue;
+ Decoration *current;
+ int lengthDocument;
+ Decoration *DecorationFromIndicator(int indicator);
+ Decoration *Create(int indicator, int length);
+ void Delete(int indicator);
+ void DeleteAnyEmpty();
+public:
+ Decoration *root;
+ bool clickNotified;
+
+ DecorationList();
+ ~DecorationList();
+
+ void SetCurrentIndicator(int indicator);
+ int GetCurrentIndicator() const { return currentIndicator; }
+
+ void SetCurrentValue(int value);
+ int GetCurrentValue() const { return currentValue; }
+
+ // Returns true if some values may have changed
+ bool FillRange(int &position, int value, int &fillLength);
+
+ void InsertSpace(int position, int insertLength);
+ void DeleteRange(int position, int deleteLength);
+
+ int AllOnFor(int position);
+ int ValueAt(int indicator, int position);
+ int Start(int indicator, int position);
+ int End(int indicator, int position);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx
new file mode 100644
index 0000000..4ed22d4
--- /dev/null
+++ b/scintilla/src/Document.cxx
@@ -0,0 +1,1920 @@
+// Scintilla source code edit control
+/** @file Document.cxx
+ ** Text document that handles notifications, DBCS, styling, words and end of line.
+ **/
+// 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 <stdio.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+
+// With Borland C++ 5.5, including <string> includes Windows.h leading to defining
+// FindText to FindTextA which makes calls here to Document::FindText fail.
+#ifdef __BORLANDC__
+#ifdef FindText
+#undef FindText
+#endif
+#endif
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "CellBuffer.h"
+#include "PerLine.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "RESearch.h"
+#include "UniConversion.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// This is ASCII specific but is safe with chars >= 0x80
+static inline bool isspacechar(unsigned char ch) {
+ return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+static inline bool IsPunctuation(char ch) {
+ return isascii(ch) && ispunct(ch);
+}
+
+static inline bool IsADigit(char ch) {
+ return isascii(ch) && isdigit(ch);
+}
+
+static inline bool IsLowerCase(char ch) {
+ return isascii(ch) && islower(ch);
+}
+
+static inline bool IsUpperCase(char ch) {
+ return isascii(ch) && isupper(ch);
+}
+
+Document::Document() {
+ refCount = 0;
+#ifdef unix
+ eolMode = SC_EOL_LF;
+#else
+ eolMode = SC_EOL_CRLF;
+#endif
+ dbcsCodePage = 0;
+ stylingBits = 5;
+ stylingBitsMask = 0x1F;
+ stylingMask = 0;
+ endStyled = 0;
+ styleClock = 0;
+ enteredModification = 0;
+ enteredStyling = 0;
+ enteredReadOnlyCount = 0;
+ tabInChars = 8;
+ indentInChars = 0;
+ actualIndentInChars = 8;
+ useTabs = true;
+ tabIndents = true;
+ backspaceUnindents = false;
+ watchers = 0;
+ lenWatchers = 0;
+
+ matchesValid = false;
+ regex = 0;
+
+ perLineData[ldMarkers] = new LineMarkers();
+ perLineData[ldLevels] = new LineLevels();
+ perLineData[ldState] = new LineState();
+ perLineData[ldMargin] = new LineAnnotation();
+ perLineData[ldAnnotation] = new LineAnnotation();
+
+ cb.SetPerLine(this);
+}
+
+Document::~Document() {
+ for (int i = 0; i < lenWatchers; i++) {
+ watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
+ }
+ delete []watchers;
+ for (int j=0; j<ldSize; j++) {
+ delete perLineData[j];
+ perLineData[j] = 0;
+ }
+ watchers = 0;
+ lenWatchers = 0;
+ delete regex;
+ regex = 0;
+}
+
+void Document::Init() {
+ for (int j=0; j<ldSize; j++) {
+ if (perLineData[j])
+ perLineData[j]->Init();
+ }
+}
+
+void Document::InsertLine(int line) {
+ for (int j=0; j<ldSize; j++) {
+ if (perLineData[j])
+ perLineData[j]->InsertLine(line);
+ }
+}
+
+void Document::RemoveLine(int line) {
+ for (int j=0; j<ldSize; j++) {
+ if (perLineData[j])
+ perLineData[j]->RemoveLine(line);
+ }
+}
+
+// Increase reference count and return its previous value.
+int Document::AddRef() {
+ return refCount++;
+}
+
+// Decrease reference count and return its previous value.
+// Delete the document if reference count reaches zero.
+int Document::Release() {
+ int curRefCount = --refCount;
+ if (curRefCount == 0)
+ delete this;
+ return curRefCount;
+}
+
+void Document::SetSavePoint() {
+ cb.SetSavePoint();
+ NotifySavePoint(true);
+}
+
+int Document::GetMark(int line) {
+ return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkValue(line);
+}
+
+int Document::AddMark(int line, int markerNum) {
+ if (line <= LinesTotal()) {
+ int prev = static_cast<LineMarkers *>(perLineData[ldMarkers])->
+ AddMark(line, markerNum, LinesTotal());
+ DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+ NotifyModified(mh);
+ return prev;
+ } else {
+ return 0;
+ }
+}
+
+void Document::AddMarkSet(int line, int valueSet) {
+ unsigned int m = valueSet;
+ for (int i = 0; m; i++, m >>= 1)
+ if (m & 1)
+ static_cast<LineMarkers *>(perLineData[ldMarkers])->
+ AddMark(line, i, LinesTotal());
+ DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+ NotifyModified(mh);
+}
+
+void Document::DeleteMark(int line, int markerNum) {
+ static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false);
+ DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+ NotifyModified(mh);
+}
+
+void Document::DeleteMarkFromHandle(int markerHandle) {
+ static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle);
+ DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+ mh.line = -1;
+ NotifyModified(mh);
+}
+
+void Document::DeleteAllMarks(int markerNum) {
+ for (int line = 0; line < LinesTotal(); line++) {
+ static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true);
+ }
+ DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+ mh.line = -1;
+ NotifyModified(mh);
+}
+
+int Document::LineFromHandle(int markerHandle) {
+ return static_cast<LineMarkers *>(perLineData[ldMarkers])->LineFromHandle(markerHandle);
+}
+
+int Document::LineStart(int line) const {
+ return cb.LineStart(line);
+}
+
+int Document::LineEnd(int line) const {
+ if (line == LinesTotal() - 1) {
+ return LineStart(line + 1);
+ } else {
+ int position = LineStart(line + 1) - 1;
+ // When line terminator is CR+LF, may need to go back one more
+ if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
+ position--;
+ }
+ return position;
+ }
+}
+
+int Document::LineFromPosition(int pos) const {
+ return cb.LineFromPosition(pos);
+}
+
+int Document::LineEndPosition(int position) const {
+ return LineEnd(LineFromPosition(position));
+}
+
+bool Document::IsLineEndPosition(int position) const {
+ return LineEnd(LineFromPosition(position)) == position;
+}
+
+int Document::VCHomePosition(int position) const {
+ int line = LineFromPosition(position);
+ int startPosition = LineStart(line);
+ int endLine = LineEnd(line);
+ int startText = startPosition;
+ while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t'))
+ startText++;
+ if (position == startText)
+ return startPosition;
+ else
+ return startText;
+}
+
+int Document::SetLevel(int line, int level) {
+ int prev = static_cast<LineLevels *>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());
+ if (prev != level) {
+ DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
+ LineStart(line), 0, 0, 0, line);
+ mh.foldLevelNow = level;
+ mh.foldLevelPrev = prev;
+ NotifyModified(mh);
+ }
+ return prev;
+}
+
+int Document::GetLevel(int line) const {
+ return static_cast<LineLevels *>(perLineData[ldLevels])->GetLevel(line);
+}
+
+void Document::ClearLevels() {
+ static_cast<LineLevels *>(perLineData[ldLevels])->ClearLevels();
+}
+
+static bool IsSubordinate(int levelStart, int levelTry) {
+ if (levelTry & SC_FOLDLEVELWHITEFLAG)
+ return true;
+ else
+ return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK);
+}
+
+int Document::GetLastChild(int lineParent, int level) {
+ if (level == -1)
+ level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK;
+ int maxLine = LinesTotal();
+ int lineMaxSubord = lineParent;
+ while (lineMaxSubord < maxLine - 1) {
+ EnsureStyledTo(LineStart(lineMaxSubord + 2));
+ if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1)))
+ break;
+ lineMaxSubord++;
+ }
+ if (lineMaxSubord > lineParent) {
+ if (level > (GetLevel(lineMaxSubord + 1) & SC_FOLDLEVELNUMBERMASK)) {
+ // Have chewed up some whitespace that belongs to a parent so seek back
+ if (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG) {
+ lineMaxSubord--;
+ }
+ }
+ }
+ return lineMaxSubord;
+}
+
+int Document::GetFoldParent(int line) {
+ int level = GetLevel(line) & SC_FOLDLEVELNUMBERMASK;
+ int lineLook = line - 1;
+ while ((lineLook > 0) && (
+ (!(GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG)) ||
+ ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) >= level))
+ ) {
+ lineLook--;
+ }
+ if ((GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG) &&
+ ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) < level)) {
+ return lineLook;
+ } else {
+ return -1;
+ }
+}
+
+int Document::ClampPositionIntoDocument(int pos) {
+ return Platform::Clamp(pos, 0, Length());
+}
+
+bool Document::IsCrLf(int pos) {
+ if (pos < 0)
+ return false;
+ if (pos >= (Length() - 1))
+ return false;
+ return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n');
+}
+
+static const int maxBytesInDBCSCharacter=5;
+
+int Document::LenChar(int pos) {
+ if (pos < 0) {
+ return 1;
+ } else if (IsCrLf(pos)) {
+ return 2;
+ } else if (SC_CP_UTF8 == dbcsCodePage) {
+ unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
+ if (ch < 0x80)
+ return 1;
+ int len = 2;
+ if (ch >= (0x80 + 0x40 + 0x20 + 0x10))
+ len = 4;
+ else if (ch >= (0x80 + 0x40 + 0x20))
+ len = 3;
+ int lengthDoc = Length();
+ if ((pos + len) > lengthDoc)
+ return lengthDoc -pos;
+ else
+ return len;
+ } else if (dbcsCodePage) {
+ char mbstr[maxBytesInDBCSCharacter+1];
+ int i;
+ for (i=0; i<Platform::DBCSCharMaxLength(); i++) {
+ mbstr[i] = cb.CharAt(pos+i);
+ }
+ mbstr[i] = '\0';
+ return Platform::DBCSCharLength(dbcsCodePage, mbstr);
+ } else {
+ return 1;
+ }
+}
+
+static bool IsTrailByte(int ch) {
+ return (ch >= 0x80) && (ch < (0x80 + 0x40));
+}
+
+static int BytesFromLead(int leadByte) {
+ if (leadByte > 0xF4) {
+ // Characters longer than 4 bytes not possible in current UTF-8
+ return 0;
+ } else if (leadByte >= 0xF0) {
+ return 4;
+ } else if (leadByte >= 0xE0) {
+ return 3;
+ } else if (leadByte >= 0xC2) {
+ return 2;
+ }
+ return 0;
+}
+
+bool Document::InGoodUTF8(int pos, int &start, int &end) {
+ int lead = pos;
+ while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1))))
+ lead--;
+ start = 0;
+ if (lead > 0) {
+ start = lead-1;
+ }
+ int leadByte = static_cast<unsigned char>(cb.CharAt(start));
+ int bytes = BytesFromLead(leadByte);
+ if (bytes == 0) {
+ return false;
+ } else {
+ int trailBytes = bytes - 1;
+ int len = pos - lead + 1;
+ if (len > trailBytes)
+ // pos too far from lead
+ return false;
+ // Check that there are enough trails for this lead
+ int trail = pos + 1;
+ while ((trail-lead<trailBytes) && (trail < Length())) {
+ if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) {
+ return false;
+ }
+ trail++;
+ }
+ end = start + bytes;
+ return true;
+ }
+}
+
+// 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.
+// When displaying DBCS text such as Japanese.
+// If moving, move the position in the indicated direction.
+int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
+ //Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir);
+ // If out of range, just return minimum/maximum value.
+ if (pos <= 0)
+ return 0;
+ if (pos >= Length())
+ return Length();
+
+ // PLATFORM_ASSERT(pos > 0 && pos < Length());
+ if (checkLineEnd && IsCrLf(pos - 1)) {
+ if (moveDir > 0)
+ return pos + 1;
+ else
+ return pos - 1;
+ }
+
+ // Not between CR and LF
+
+ if (dbcsCodePage) {
+ if (SC_CP_UTF8 == dbcsCodePage) {
+ unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
+ int startUTF = pos;
+ int endUTF = pos;
+ if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {
+ // ch is a trail byte within a UTF-8 character
+ if (moveDir > 0)
+ pos = endUTF;
+ else
+ pos = startUTF;
+ }
+ } else {
+ // Anchor DBCS calculations at start of line because start of line can
+ // not be a DBCS trail byte.
+ int posCheck = LineStart(LineFromPosition(pos));
+ while (posCheck < pos) {
+ char mbstr[maxBytesInDBCSCharacter+1];
+ int i;
+ for (i=0; i<Platform::DBCSCharMaxLength(); i++) {
+ mbstr[i] = cb.CharAt(posCheck+i);
+ }
+ mbstr[i] = '\0';
+
+ int mbsize = Platform::DBCSCharLength(dbcsCodePage, mbstr);
+ if (posCheck + mbsize == pos) {
+ return pos;
+ } else if (posCheck + mbsize > pos) {
+ if (moveDir > 0) {
+ return posCheck + mbsize;
+ } else {
+ return posCheck;
+ }
+ }
+ posCheck += mbsize;
+ }
+ }
+ }
+
+ return pos;
+}
+
+void Document::ModifiedAt(int pos) {
+ if (endStyled > pos)
+ endStyled = pos;
+}
+
+void Document::CheckReadOnly() {
+ if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
+ enteredReadOnlyCount++;
+ NotifyModifyAttempt();
+ enteredReadOnlyCount--;
+ }
+}
+
+// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt.
+// SetStyleAt does not change the persistent state of a document
+
+bool Document::DeleteChars(int pos, int len) {
+ if (len == 0)
+ return false;
+ if ((pos + len) > Length())
+ return false;
+ CheckReadOnly();
+ if (enteredModification != 0) {
+ return false;
+ } else {
+ enteredModification++;
+ if (!cb.IsReadOnly()) {
+ NotifyModified(
+ DocModification(
+ SC_MOD_BEFOREDELETE | SC_PERFORMED_USER,
+ pos, len,
+ 0, 0));
+ int prevLinesTotal = LinesTotal();
+ bool startSavePoint = cb.IsSavePoint();
+ bool startSequence = false;
+ const char *text = cb.DeleteChars(pos, len, startSequence);
+ if (startSavePoint && cb.IsCollectingUndo())
+ NotifySavePoint(!startSavePoint);
+ if ((pos < Length()) || (pos == 0))
+ ModifiedAt(pos);
+ else
+ ModifiedAt(pos-1);
+ NotifyModified(
+ DocModification(
+ SC_MOD_DELETETEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
+ pos, len,
+ LinesTotal() - prevLinesTotal, text));
+ }
+ enteredModification--;
+ }
+ return !cb.IsReadOnly();
+}
+
+/**
+ * Insert a string with a length.
+ */
+bool Document::InsertString(int position, const char *s, int insertLength) {
+ if (insertLength <= 0) {
+ return false;
+ }
+ CheckReadOnly();
+ if (enteredModification != 0) {
+ return false;
+ } else {
+ enteredModification++;
+ if (!cb.IsReadOnly()) {
+ NotifyModified(
+ DocModification(
+ SC_MOD_BEFOREINSERT | SC_PERFORMED_USER,
+ position, insertLength,
+ 0, s));
+ int prevLinesTotal = LinesTotal();
+ bool startSavePoint = cb.IsSavePoint();
+ bool startSequence = false;
+ const char *text = cb.InsertString(position, s, insertLength, startSequence);
+ if (startSavePoint && cb.IsCollectingUndo())
+ NotifySavePoint(!startSavePoint);
+ ModifiedAt(position);
+ NotifyModified(
+ DocModification(
+ SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
+ position, insertLength,
+ LinesTotal() - prevLinesTotal, text));
+ }
+ enteredModification--;
+ }
+ return !cb.IsReadOnly();
+}
+
+int Document::Undo() {
+ int newPos = -1;
+ CheckReadOnly();
+ if (enteredModification == 0) {
+ enteredModification++;
+ 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 if (action.at == containerAction) {
+ DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO);
+ dm.token = action.position;
+ NotifyModified(dm);
+ } else {
+ NotifyModified(DocModification(
+ SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
+ }
+ cb.PerformUndoStep();
+ int cellPosition = action.position;
+ if (action.at != containerAction) {
+ 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 if (action.at == insertAction) {
+ 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));
+ }
+
+ bool endSavePoint = cb.IsSavePoint();
+ if (startSavePoint != endSavePoint)
+ NotifySavePoint(endSavePoint);
+ }
+ enteredModification--;
+ }
+ return newPos;
+}
+
+int Document::Redo() {
+ int newPos = -1;
+ CheckReadOnly();
+ if (enteredModification == 0) {
+ enteredModification++;
+ 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 if (action.at == containerAction) {
+ DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_REDO);
+ dm.token = action.position;
+ NotifyModified(dm);
+ } else {
+ NotifyModified(DocModification(
+ SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
+ }
+ cb.PerformRedoStep();
+ if (action.at != containerAction) {
+ ModifiedAt(action.position);
+ newPos = action.position;
+ }
+
+ int modFlags = SC_PERFORMED_REDO;
+ if (action.at == insertAction) {
+ newPos += action.lenData;
+ modFlags |= SC_MOD_INSERTTEXT;
+ } else if (action.at == removeAction) {
+ 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));
+ }
+
+ bool endSavePoint = cb.IsSavePoint();
+ if (startSavePoint != endSavePoint)
+ NotifySavePoint(endSavePoint);
+ }
+ enteredModification--;
+ }
+ return newPos;
+}
+
+/**
+ * Insert a single character.
+ */
+bool Document::InsertChar(int pos, char ch) {
+ char chs[1];
+ chs[0] = ch;
+ return InsertString(pos, chs, 1);
+}
+
+/**
+ * Insert a null terminated string.
+ */
+bool Document::InsertCString(int position, const char *s) {
+ return InsertString(position, s, strlen(s));
+}
+
+void Document::ChangeChar(int pos, char ch) {
+ DeleteChars(pos, 1);
+ InsertChar(pos, ch);
+}
+
+void Document::DelChar(int pos) {
+ DeleteChars(pos, LenChar(pos));
+}
+
+void Document::DelCharBack(int pos) {
+ if (pos <= 0) {
+ return;
+ } else if (IsCrLf(pos - 2)) {
+ DeleteChars(pos - 2, 2);
+ } else if (dbcsCodePage) {
+ int startChar = MovePositionOutsideChar(pos - 1, -1, false);
+ DeleteChars(startChar, pos - startChar);
+ } else {
+ DeleteChars(pos - 1, 1);
+ }
+}
+
+static bool isindentchar(char ch) {
+ return (ch == ' ') || (ch == '\t');
+}
+
+static int NextTab(int pos, int tabSize) {
+ return ((pos / tabSize) + 1) * tabSize;
+}
+
+static void CreateIndentation(char *linebuf, int length, int indent, int tabSize, bool insertSpaces) {
+ length--; // ensure space for \0
+ if (!insertSpaces) {
+ while ((indent >= tabSize) && (length > 0)) {
+ *linebuf++ = '\t';
+ indent -= tabSize;
+ length--;
+ }
+ }
+ while ((indent > 0) && (length > 0)) {
+ *linebuf++ = ' ';
+ indent--;
+ length--;
+ }
+ *linebuf = '\0';
+}
+
+int Document::GetLineIndentation(int line) {
+ int indent = 0;
+ if ((line >= 0) && (line < LinesTotal())) {
+ int lineStart = LineStart(line);
+ int length = Length();
+ for (int i = lineStart; i < length; i++) {
+ char ch = cb.CharAt(i);
+ if (ch == ' ')
+ indent++;
+ else if (ch == '\t')
+ indent = NextTab(indent, tabInChars);
+ else
+ return indent;
+ }
+ }
+ return indent;
+}
+
+void Document::SetLineIndentation(int line, int indent) {
+ int indentOfLine = GetLineIndentation(line);
+ if (indent < 0)
+ indent = 0;
+ if (indent != indentOfLine) {
+ char linebuf[1000];
+ CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs);
+ int thisLineStart = LineStart(line);
+ int indentPos = GetLineIndentPosition(line);
+ UndoGroup ug(this);
+ DeleteChars(thisLineStart, indentPos - thisLineStart);
+ InsertCString(thisLineStart, linebuf);
+ }
+}
+
+int Document::GetLineIndentPosition(int line) const {
+ if (line < 0)
+ return 0;
+ int pos = LineStart(line);
+ int length = Length();
+ while ((pos < length) && isindentchar(cb.CharAt(pos))) {
+ pos++;
+ }
+ return pos;
+}
+
+int Document::GetColumn(int pos) {
+ int column = 0;
+ int line = LineFromPosition(pos);
+ if ((line >= 0) && (line < LinesTotal())) {
+ for (int i = LineStart(line); i < pos;) {
+ char ch = cb.CharAt(i);
+ if (ch == '\t') {
+ column = NextTab(column, tabInChars);
+ i++;
+ } else if (ch == '\r') {
+ return column;
+ } else if (ch == '\n') {
+ return column;
+ } else if (i >= Length()) {
+ return column;
+ } else {
+ column++;
+ i = MovePositionOutsideChar(i + 1, 1, false);
+ }
+ }
+ }
+ return column;
+}
+
+int Document::FindColumn(int line, int column) {
+ int position = LineStart(line);
+ if ((line >= 0) && (line < LinesTotal())) {
+ int columnCurrent = 0;
+ while ((columnCurrent < column) && (position < Length())) {
+ char ch = cb.CharAt(position);
+ if (ch == '\t') {
+ columnCurrent = NextTab(columnCurrent, tabInChars);
+ position++;
+ } else if (ch == '\r') {
+ return position;
+ } else if (ch == '\n') {
+ return position;
+ } else {
+ columnCurrent++;
+ position = MovePositionOutsideChar(position + 1, 1, false);
+ }
+ }
+ }
+ return position;
+}
+
+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) {
+ if (LineStart(line) < LineEnd(line)) {
+ SetLineIndentation(line, indentOfLine + IndentSize());
+ }
+ } else {
+ SetLineIndentation(line, indentOfLine - IndentSize());
+ }
+ }
+}
+
+// Convert line endings for a piece of text to a particular mode.
+// Stop at len or when a NUL is found.
+// Caller must delete the returned pointer.
+char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode) {
+ char *dest = new char[2 * len + 1];
+ const char *sptr = s;
+ char *dptr = dest;
+ for (size_t i = 0; (i < len) && (*sptr != '\0'); i++) {
+ if (*sptr == '\n' || *sptr == '\r') {
+ if (eolMode == SC_EOL_CR) {
+ *dptr++ = '\r';
+ } else if (eolMode == SC_EOL_LF) {
+ *dptr++ = '\n';
+ } else { // eolMode == SC_EOL_CRLF
+ *dptr++ = '\r';
+ *dptr++ = '\n';
+ }
+ if ((*sptr == '\r') && (i+1 < len) && (*(sptr+1) == '\n')) {
+ i++;
+ sptr++;
+ }
+ sptr++;
+ } else {
+ *dptr++ = *sptr++;
+ }
+ }
+ *dptr++ = '\0';
+ *pLenOut = (dptr - dest) - 1;
+ return dest;
+}
+
+void Document::ConvertLineEnds(int eolModeSet) {
+ UndoGroup ug(this);
+
+ for (int pos = 0; pos < Length(); pos++) {
+ if (cb.CharAt(pos) == '\r') {
+ if (cb.CharAt(pos + 1) == '\n') {
+ // CRLF
+ if (eolModeSet == SC_EOL_CR) {
+ DeleteChars(pos + 1, 1); // Delete the LF
+ } else if (eolModeSet == SC_EOL_LF) {
+ DeleteChars(pos, 1); // Delete the CR
+ } else {
+ pos++;
+ }
+ } else {
+ // CR
+ if (eolModeSet == SC_EOL_CRLF) {
+ InsertString(pos + 1, "\n", 1); // Insert LF
+ pos++;
+ } else if (eolModeSet == SC_EOL_LF) {
+ InsertString(pos, "\n", 1); // Insert LF
+ DeleteChars(pos + 1, 1); // Delete CR
+ }
+ }
+ } else if (cb.CharAt(pos) == '\n') {
+ // LF
+ if (eolModeSet == SC_EOL_CRLF) {
+ InsertString(pos, "\r", 1); // Insert CR
+ pos++;
+ } else if (eolModeSet == SC_EOL_CR) {
+ InsertString(pos, "\r", 1); // Insert CR
+ DeleteChars(pos + 1, 1); // Delete LF
+ }
+ }
+ }
+
+}
+
+bool Document::IsWhiteLine(int line) const {
+ int currentChar = LineStart(line);
+ int endLine = LineEnd(line);
+ while (currentChar < endLine) {
+ if (cb.CharAt(currentChar) != ' ' && cb.CharAt(currentChar) != '\t') {
+ return false;
+ }
+ ++currentChar;
+ }
+ return true;
+}
+
+int Document::ParaUp(int pos) {
+ int line = LineFromPosition(pos);
+ line--;
+ while (line >= 0 && IsWhiteLine(line)) { // skip empty lines
+ line--;
+ }
+ 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);
+}
+
+CharClassify::cc Document::WordCharClass(unsigned char ch) {
+ if ((SC_CP_UTF8 == dbcsCodePage) && (ch >= 0x80))
+ return CharClassify::ccWord;
+ return charClass.GetClass(ch);
+}
+
+/**
+ * Used by commmands that want to select whole words.
+ * Finds the start of word at pos when delta < 0 or the end of the word when delta >= 0.
+ */
+int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) {
+ CharClassify::cc ccStart = CharClassify::ccWord;
+ if (delta < 0) {
+ if (!onlyWordCharacters)
+ ccStart = WordCharClass(cb.CharAt(pos-1));
+ while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart))
+ pos--;
+ } else {
+ if (!onlyWordCharacters && pos < Length())
+ ccStart = WordCharClass(cb.CharAt(pos));
+ while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart))
+ pos++;
+ }
+ return MovePositionOutsideChar(pos, delta, true);
+}
+
+/**
+ * Find the start of the next word in either a forward (delta >= 0) or backwards direction
+ * (delta < 0).
+ * This is looking for a transition between character classes although there is also some
+ * additional movement to transit white space.
+ * Used by cursor movement by word commands.
+ */
+int Document::NextWordStart(int pos, int delta) {
+ if (delta < 0) {
+ while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace))
+ pos--;
+ if (pos > 0) {
+ CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1));
+ while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) {
+ pos--;
+ }
+ }
+ } else {
+ CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos));
+ while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart))
+ pos++;
+ while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace))
+ pos++;
+ }
+ return pos;
+}
+
+/**
+ * Find the end of the next word in either a forward (delta >= 0) or backwards direction
+ * (delta < 0).
+ * This is looking for a transition between character classes although there is also some
+ * additional movement to transit white space.
+ * Used by cursor movement by word commands.
+ */
+int Document::NextWordEnd(int pos, int delta) {
+ if (delta < 0) {
+ if (pos > 0) {
+ CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1));
+ if (ccStart != CharClassify::ccSpace) {
+ while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == ccStart) {
+ pos--;
+ }
+ }
+ while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace) {
+ pos--;
+ }
+ }
+ } else {
+ while (pos < Length() && WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace) {
+ pos++;
+ }
+ if (pos < Length()) {
+ CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos));
+ while (pos < Length() && WordCharClass(cb.CharAt(pos)) == ccStart) {
+ pos++;
+ }
+ }
+ }
+ return pos;
+}
+
+/**
+ * Check that the character at the given position is a word or punctuation character and that
+ * the previous character is of a different character class.
+ */
+bool Document::IsWordStartAt(int pos) {
+ if (pos > 0) {
+ CharClassify::cc ccPos = WordCharClass(CharAt(pos));
+ return (ccPos == CharClassify::ccWord || ccPos == CharClassify::ccPunctuation) &&
+ (ccPos != WordCharClass(CharAt(pos - 1)));
+ }
+ return true;
+}
+
+/**
+ * Check that the character at the given position is a word or punctuation character and that
+ * the next character is of a different character class.
+ */
+bool Document::IsWordEndAt(int pos) {
+ if (pos < Length()) {
+ CharClassify::cc ccPrev = WordCharClass(CharAt(pos-1));
+ return (ccPrev == CharClassify::ccWord || ccPrev == CharClassify::ccPunctuation) &&
+ (ccPrev != WordCharClass(CharAt(pos)));
+ }
+ return true;
+}
+
+/**
+ * Check that the given range is has transitions between character classes at both
+ * ends and where the characters on the inside are word or punctuation characters.
+ */
+bool Document::IsWordAt(int start, int end) {
+ return IsWordStartAt(start) && IsWordEndAt(end);
+}
+
+static inline char MakeLowerCase(char ch) {
+ if (ch < 'A' || ch > 'Z')
+ return ch;
+ else
+ return static_cast<char>(ch - 'A' + 'a');
+}
+
+static bool GoodTrailByte(int v) {
+ return (v >= 0x80) && (v < 0xc0);
+}
+
+size_t Document::ExtractChar(int pos, char *bytes) {
+ unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
+ size_t widthChar = UTF8CharLength(ch);
+ bytes[0] = ch;
+ for (size_t i=1; i<widthChar; i++) {
+ bytes[i] = cb.CharAt(pos+i);
+ if (!GoodTrailByte(static_cast<unsigned char>(bytes[i]))) { // Bad byte
+ widthChar = 1;
+ }
+ }
+ return widthChar;
+}
+
+CaseFolderTable::CaseFolderTable() {
+ for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
+ mapping[iChar] = static_cast<char>(iChar);
+ }
+}
+
+CaseFolderTable::~CaseFolderTable() {
+}
+
+size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if (lenMixed > sizeFolded) {
+ return 0;
+ } else {
+ for (size_t i=0; i<lenMixed; i++) {
+ folded[i] = mapping[static_cast<unsigned char>(mixed[i])];
+ }
+ return lenMixed;
+ }
+}
+
+void CaseFolderTable::SetTranslation(char ch, char chTranslation) {
+ mapping[static_cast<unsigned char>(ch)] = chTranslation;
+}
+
+void CaseFolderTable::StandardASCII() {
+ for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
+ if (iChar >= 'A' && iChar <= 'Z') {
+ mapping[iChar] = static_cast<char>(iChar - 'A' + 'a');
+ } else {
+ mapping[iChar] = static_cast<char>(iChar);
+ }
+ }
+}
+
+bool Document::MatchesWordOptions(bool word, bool wordStart, int pos, int length) {
+ return (!word && !wordStart) ||
+ (word && IsWordAt(pos, pos + length)) ||
+ (wordStart && IsWordStartAt(pos));
+}
+
+/**
+ * Find text in document, supporting both forward and backward
+ * searches (just pass minPos > maxPos to do a backward search)
+ * Has not been tested with backwards DBCS searches yet.
+ */
+long Document::FindText(int minPos, int maxPos, const char *search,
+ bool caseSensitive, bool word, bool wordStart, bool regExp, int flags,
+ int *length, CaseFolder *pcf) {
+ if (regExp) {
+ if (!regex)
+ regex = CreateRegexSearch(&charClass);
+ return regex->FindText(this, minPos, maxPos, search, caseSensitive, word, wordStart, flags, length);
+ } else {
+
+ const bool forward = minPos <= maxPos;
+ const int increment = forward ? 1 : -1;
+
+ // Range endpoints should not be inside DBCS characters, but just in case, move them.
+ const int startPos = MovePositionOutsideChar(minPos, increment, false);
+ const int endPos = MovePositionOutsideChar(maxPos, increment, false);
+
+ // Compute actual search ranges needed
+ const int lengthFind = (*length == -1) ? static_cast<int>(strlen(search)) : *length;
+ const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos;
+
+ //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
+ const int limitPos = Platform::Maximum(startPos, endPos);
+ int pos = forward ? startPos : (startPos - 1);
+ if (caseSensitive) {
+ while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+ bool found = (pos + lengthFind) <= limitPos;
+ for (int indexSearch = 0; (indexSearch < lengthFind) && found; indexSearch++) {
+ found = CharAt(pos + indexSearch) == search[indexSearch];
+ }
+ if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) {
+ return pos;
+ }
+ pos += increment;
+ if (dbcsCodePage && (pos >= 0)) {
+ // Have to use >= 0 as otherwise next statement would change
+ // -1 to 0 and make loop infinite.
+ // Ensure trying to match from start of character
+ pos = MovePositionOutsideChar(pos, increment, false);
+ }
+ }
+ } else if (SC_CP_UTF8 == dbcsCodePage) {
+ const size_t maxBytesCharacter = 4;
+ const size_t maxFoldingExpansion = 4;
+ std::vector<char> searchThing(lengthFind * maxBytesCharacter * maxFoldingExpansion + 1);
+ const int lenSearch = pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind);
+ while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+ int widthFirstCharacter = 0;
+ int indexDocument = 0;
+ int indexSearch = 0;
+ bool characterMatches = true;
+ while (characterMatches &&
+ ((pos + indexDocument) < limitPos) &&
+ (indexSearch < lenSearch)) {
+ char bytes[maxBytesCharacter + 1];
+ bytes[maxBytesCharacter] = 0;
+ const int widthChar = ExtractChar(pos + indexDocument, bytes);
+ if (!widthFirstCharacter)
+ widthFirstCharacter = widthChar;
+ char folded[maxBytesCharacter * maxFoldingExpansion + 1];
+ const int lenFlat = pcf->Fold(folded, sizeof(folded), bytes, widthChar);
+ folded[lenFlat] = 0;
+ // Does folded match the buffer
+ characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat);
+ indexDocument += widthChar;
+ indexSearch += lenFlat;
+ }
+ if (characterMatches && (indexSearch == static_cast<int>(lenSearch))) {
+ if (MatchesWordOptions(word, wordStart, pos, indexDocument)) {
+ *length = indexDocument;
+ return pos;
+ }
+ }
+ if (forward) {
+ pos += widthFirstCharacter;
+ } else {
+ pos--;
+ if (pos > 0) {
+ // Ensure trying to match from start of character
+ pos = MovePositionOutsideChar(pos, increment, false);
+ }
+ }
+ }
+ } else {
+ CaseFolderTable caseFolder;
+ std::vector<char> searchThing(lengthFind + 1);
+ pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind);
+ while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+ bool found = (pos + lengthFind) <= limitPos;
+ for (int indexSearch = 0; (indexSearch < lengthFind) && found; indexSearch++) {
+ char ch = CharAt(pos + indexSearch);
+ char folded[2];
+ pcf->Fold(folded, sizeof(folded), &ch, 1);
+ found = folded[0] == searchThing[indexSearch];
+ }
+ if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) {
+ return pos;
+ }
+ pos += increment;
+ if (dbcsCodePage && (pos >= 0)) {
+ // Ensure trying to match from start of character
+ pos = MovePositionOutsideChar(pos, increment, false);
+ }
+ }
+ }
+ }
+ //Platform::DebugPrintf("Not found\n");
+ return -1;
+}
+
+const char *Document::SubstituteByPosition(const char *text, int *length) {
+ return regex->SubstituteByPosition(this, text, length);
+}
+
+int Document::LinesTotal() const {
+ return cb.Lines();
+}
+
+void Document::ChangeCase(Range r, bool makeUpperCase) {
+ for (int pos = r.start; pos < r.end;) {
+ int len = LenChar(pos);
+ if (len == 1) {
+ char ch = CharAt(pos);
+ if (makeUpperCase) {
+ if (IsLowerCase(ch)) {
+ ChangeChar(pos, static_cast<char>(MakeUpperCase(ch)));
+ }
+ } else {
+ if (IsUpperCase(ch)) {
+ ChangeChar(pos, static_cast<char>(MakeLowerCase(ch)));
+ }
+ }
+ }
+ pos += len;
+ }
+}
+
+void Document::SetDefaultCharClasses(bool includeWordClass) {
+ charClass.SetDefaultCharClasses(includeWordClass);
+}
+
+void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass) {
+ charClass.SetCharClasses(chars, newCharClass);
+}
+
+void Document::SetStylingBits(int bits) {
+ stylingBits = bits;
+ stylingBitsMask = (1 << stylingBits) - 1;
+}
+
+void Document::StartStyling(int position, char mask) {
+ stylingMask = mask;
+ endStyled = position;
+}
+
+bool Document::SetStyleFor(int length, char style) {
+ if (enteredStyling != 0) {
+ return false;
+ } else {
+ enteredStyling++;
+ style &= stylingMask;
+ int prevEndStyled = endStyled;
+ if (cb.SetStyleFor(endStyled, length, style, stylingMask)) {
+ DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
+ prevEndStyled, length);
+ NotifyModified(mh);
+ }
+ endStyled += length;
+ enteredStyling--;
+ return true;
+ }
+}
+
+bool Document::SetStyles(int length, const char *styles) {
+ if (enteredStyling != 0) {
+ return false;
+ } else {
+ enteredStyling++;
+ bool didChange = false;
+ 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;
+ endMod = endStyled;
+ }
+ }
+ if (didChange) {
+ DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
+ startMod, endMod - startMod + 1);
+ NotifyModified(mh);
+ }
+ enteredStyling--;
+ return true;
+ }
+}
+
+void Document::EnsureStyledTo(int pos) {
+ if ((enteredStyling == 0) && (pos > GetEndStyled())) {
+ IncrementStyleClock();
+ // Ask the watchers to style, and stop as soon as one responds.
+ for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) {
+ watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos);
+ }
+ }
+}
+
+int Document::SetLineState(int line, int state) {
+ int statePrevious = static_cast<LineState *>(perLineData[ldState])->SetLineState(line, state);
+ if (state != statePrevious) {
+ DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
+ NotifyModified(mh);
+ }
+ return statePrevious;
+}
+
+int Document::GetLineState(int line) const {
+ return static_cast<LineState *>(perLineData[ldState])->GetLineState(line);
+}
+
+int Document::GetMaxLineState() {
+ return static_cast<LineState *>(perLineData[ldState])->GetMaxLineState();
+}
+
+StyledText Document::MarginStyledText(int line) {
+ LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldMargin]);
+ return StyledText(pla->Length(line), pla->Text(line),
+ pla->MultipleStyles(line), pla->Style(line), pla->Styles(line));
+}
+
+void Document::MarginSetText(int line, const char *text) {
+ static_cast<LineAnnotation *>(perLineData[ldMargin])->SetText(line, text);
+ DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line);
+ NotifyModified(mh);
+}
+
+void Document::MarginSetStyle(int line, int style) {
+ static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyle(line, style);
+}
+
+void Document::MarginSetStyles(int line, const unsigned char *styles) {
+ static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyles(line, styles);
+}
+
+int Document::MarginLength(int line) const {
+ return static_cast<LineAnnotation *>(perLineData[ldMargin])->Length(line);
+}
+
+void Document::MarginClearAll() {
+ int maxEditorLine = LinesTotal();
+ for (int l=0; l<maxEditorLine; l++)
+ MarginSetText(l, 0);
+ // Free remaining data
+ static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll();
+}
+
+bool Document::AnnotationAny() const {
+ return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->AnySet();
+}
+
+StyledText Document::AnnotationStyledText(int line) {
+ LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]);
+ return StyledText(pla->Length(line), pla->Text(line),
+ pla->MultipleStyles(line), pla->Style(line), pla->Styles(line));
+}
+
+void Document::AnnotationSetText(int line, const char *text) {
+ const int linesBefore = AnnotationLines(line);
+ static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetText(line, text);
+ const int linesAfter = AnnotationLines(line);
+ DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line);
+ mh.annotationLinesAdded = linesAfter - linesBefore;
+ NotifyModified(mh);
+}
+
+void Document::AnnotationSetStyle(int line, int style) {
+ static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyle(line, style);
+}
+
+void Document::AnnotationSetStyles(int line, const unsigned char *styles) {
+ static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyles(line, styles);
+}
+
+int Document::AnnotationLength(int line) const {
+ return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Length(line);
+}
+
+int Document::AnnotationLines(int line) const {
+ return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Lines(line);
+}
+
+void Document::AnnotationClearAll() {
+ int maxEditorLine = LinesTotal();
+ for (int l=0; l<maxEditorLine; l++)
+ AnnotationSetText(l, 0);
+ // Free remaining data
+ static_cast<LineAnnotation *>(perLineData[ldAnnotation])->ClearAll();
+}
+
+void Document::IncrementStyleClock() {
+ styleClock = (styleClock + 1) % 0x100000;
+}
+
+void Document::DecorationFillRange(int position, int value, int fillLength) {
+ if (decorations.FillRange(position, value, fillLength)) {
+ DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER,
+ position, fillLength);
+ NotifyModified(mh);
+ }
+}
+
+bool Document::AddWatcher(DocWatcher *watcher, void *userData) {
+ for (int i = 0; i < lenWatchers; i++) {
+ if ((watchers[i].watcher == watcher) &&
+ (watchers[i].userData == userData))
+ return false;
+ }
+ WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers + 1];
+ for (int j = 0; j < lenWatchers; j++)
+ pwNew[j] = watchers[j];
+ pwNew[lenWatchers].watcher = watcher;
+ pwNew[lenWatchers].userData = userData;
+ delete []watchers;
+ watchers = pwNew;
+ lenWatchers++;
+ return true;
+}
+
+bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) {
+ for (int i = 0; i < lenWatchers; i++) {
+ if ((watchers[i].watcher == watcher) &&
+ (watchers[i].userData == userData)) {
+ if (lenWatchers == 1) {
+ delete []watchers;
+ watchers = 0;
+ lenWatchers = 0;
+ } else {
+ WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers];
+ for (int j = 0; j < lenWatchers - 1; j++) {
+ pwNew[j] = (j < i) ? watchers[j] : watchers[j + 1];
+ }
+ delete []watchers;
+ watchers = pwNew;
+ lenWatchers--;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void Document::NotifyModifyAttempt() {
+ for (int i = 0; i < lenWatchers; i++) {
+ watchers[i].watcher->NotifyModifyAttempt(this, watchers[i].userData);
+ }
+}
+
+void Document::NotifySavePoint(bool atSavePoint) {
+ for (int i = 0; i < lenWatchers; i++) {
+ watchers[i].watcher->NotifySavePoint(this, watchers[i].userData, atSavePoint);
+ }
+}
+
+void Document::NotifyModified(DocModification mh) {
+ if (mh.modificationType & SC_MOD_INSERTTEXT) {
+ decorations.InsertSpace(mh.position, mh.length);
+ } else if (mh.modificationType & SC_MOD_DELETETEXT) {
+ decorations.DeleteRange(mh.position, mh.length);
+ }
+ for (int i = 0; i < lenWatchers; i++) {
+ watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
+ }
+}
+
+bool Document::IsWordPartSeparator(char ch) {
+ return (WordCharClass(ch) == CharClassify::ccWord) && IsPunctuation(ch);
+}
+
+int Document::WordPartLeft(int pos) {
+ if (pos > 0) {
+ --pos;
+ char startChar = cb.CharAt(pos);
+ if (IsWordPartSeparator(startChar)) {
+ while (pos > 0 && IsWordPartSeparator(cb.CharAt(pos))) {
+ --pos;
+ }
+ }
+ if (pos > 0) {
+ startChar = cb.CharAt(pos);
+ --pos;
+ if (IsLowerCase(startChar)) {
+ while (pos > 0 && IsLowerCase(cb.CharAt(pos)))
+ --pos;
+ if (!IsUpperCase(cb.CharAt(pos)) && !IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsUpperCase(startChar)) {
+ while (pos > 0 && IsUpperCase(cb.CharAt(pos)))
+ --pos;
+ if (!IsUpperCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsADigit(startChar)) {
+ while (pos > 0 && IsADigit(cb.CharAt(pos)))
+ --pos;
+ if (!IsADigit(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsPunctuation(startChar)) {
+ while (pos > 0 && IsPunctuation(cb.CharAt(pos)))
+ --pos;
+ if (!IsPunctuation(cb.CharAt(pos)))
+ ++pos;
+ } else if (isspacechar(startChar)) {
+ while (pos > 0 && isspacechar(cb.CharAt(pos)))
+ --pos;
+ if (!isspacechar(cb.CharAt(pos)))
+ ++pos;
+ } else if (!isascii(startChar)) {
+ while (pos > 0 && !isascii(cb.CharAt(pos)))
+ --pos;
+ if (isascii(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ ++pos;
+ }
+ }
+ }
+ return pos;
+}
+
+int Document::WordPartRight(int pos) {
+ char startChar = cb.CharAt(pos);
+ int length = Length();
+ if (IsWordPartSeparator(startChar)) {
+ while (pos < length && IsWordPartSeparator(cb.CharAt(pos)))
+ ++pos;
+ startChar = cb.CharAt(pos);
+ }
+ if (!isascii(startChar)) {
+ while (pos < length && !isascii(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsLowerCase(startChar)) {
+ while (pos < length && IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsUpperCase(startChar)) {
+ if (IsLowerCase(cb.CharAt(pos + 1))) {
+ ++pos;
+ while (pos < length && IsLowerCase(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ while (pos < length && IsUpperCase(cb.CharAt(pos)))
+ ++pos;
+ }
+ if (IsLowerCase(cb.CharAt(pos)) && IsUpperCase(cb.CharAt(pos - 1)))
+ --pos;
+ } else if (IsADigit(startChar)) {
+ while (pos < length && IsADigit(cb.CharAt(pos)))
+ ++pos;
+ } else if (IsPunctuation(startChar)) {
+ while (pos < length && IsPunctuation(cb.CharAt(pos)))
+ ++pos;
+ } else if (isspacechar(startChar)) {
+ while (pos < length && isspacechar(cb.CharAt(pos)))
+ ++pos;
+ } else {
+ ++pos;
+ }
+ return pos;
+}
+
+bool IsLineEndChar(char c) {
+ return (c == '\n' || c == '\r');
+}
+
+int Document::ExtendStyleRange(int pos, int delta, bool singleLine) {
+ int sStart = cb.StyleAt(pos);
+ if (delta < 0) {
+ while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+ pos--;
+ pos++;
+ } else {
+ while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+ pos++;
+ }
+ 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, true);
+ 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;
+}
+
+/**
+ * Implementation of RegexSearchBase for the default built-in regular expression engine
+ */
+class BuiltinRegex : public RegexSearchBase {
+public:
+ BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {}
+
+ virtual ~BuiltinRegex() {
+ delete substituted;
+ }
+
+ virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool word, bool wordStart, int flags,
+ int *length);
+
+ virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length);
+
+private:
+ RESearch search;
+ char *substituted;
+};
+
+// Define a way for the Regular Expression code to access the document
+class DocumentIndexer : public CharacterIndexer {
+ Document *pdoc;
+ int end;
+public:
+ DocumentIndexer(Document *pdoc_, int end_) :
+ pdoc(pdoc_), end(end_) {
+ }
+
+ virtual ~DocumentIndexer() {
+ }
+
+ virtual char CharAt(int index) {
+ if (index < 0 || index >= end)
+ return 0;
+ else
+ return pdoc->CharAt(index);
+ }
+};
+
+long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool, bool, int flags,
+ int *length) {
+ bool posix = (flags & SCFIND_POSIX) != 0;
+ int increment = (minPos <= maxPos) ? 1 : -1;
+
+ int startPos = minPos;
+ int endPos = maxPos;
+
+ // Range endpoints should not be inside DBCS characters, but just in case, move them.
+ startPos = doc->MovePositionOutsideChar(startPos, 1, false);
+ endPos = doc->MovePositionOutsideChar(endPos, 1, false);
+
+ const char *errmsg = search.Compile(s, *length, caseSensitive, posix);
+ if (errmsg) {
+ return -1;
+ }
+ // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
+ // Replace first '.' with '-' in each property file variable reference:
+ // Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
+ // Replace: $(\1-\2)
+ int lineRangeStart = doc->LineFromPosition(startPos);
+ int lineRangeEnd = doc->LineFromPosition(endPos);
+ if ((increment == 1) &&
+ (startPos >= doc->LineEnd(lineRangeStart)) &&
+ (lineRangeStart < lineRangeEnd)) {
+ // the start position is at end of line or between line end characters.
+ lineRangeStart++;
+ startPos = doc->LineStart(lineRangeStart);
+ }
+ int pos = -1;
+ int lenRet = 0;
+ char searchEnd = s[*length - 1];
+ int lineRangeBreak = lineRangeEnd + increment;
+ for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
+ int startOfLine = doc->LineStart(line);
+ int endOfLine = doc->LineEnd(line);
+ if (increment == 1) {
+ if (line == lineRangeStart) {
+ if ((startPos != startOfLine) && (s[0] == '^'))
+ continue; // Can't match start of line if start position after start of line
+ startOfLine = startPos;
+ }
+ if (line == lineRangeEnd) {
+ if ((endPos != endOfLine) && (searchEnd == '$'))
+ continue; // Can't match end of line if end position before end of line
+ endOfLine = endPos;
+ }
+ } else {
+ if (line == lineRangeEnd) {
+ if ((endPos != startOfLine) && (s[0] == '^'))
+ continue; // Can't match start of line if end position after start of line
+ startOfLine = endPos;
+ }
+ if (line == lineRangeStart) {
+ if ((startPos != endOfLine) && (searchEnd == '$'))
+ continue; // Can't match end of line if start position before end of line
+ endOfLine = startPos;
+ }
+ }
+
+ DocumentIndexer di(doc, endOfLine);
+ int success = search.Execute(di, startOfLine, endOfLine);
+ if (success) {
+ pos = search.bopat[0];
+ lenRet = search.eopat[0] - search.bopat[0];
+ if (increment == -1) {
+ // Check for the last match on this line.
+ int repetitions = 1000; // Break out of infinite loop
+ while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
+ success = search.Execute(di, pos+1, endOfLine);
+ if (success) {
+ if (search.eopat[0] <= minPos) {
+ pos = search.bopat[0];
+ lenRet = search.eopat[0] - search.bopat[0];
+ } else {
+ success = 0;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ *length = lenRet;
+ return pos;
+}
+
+const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) {
+ delete []substituted;
+ substituted = 0;
+ DocumentIndexer di(doc, doc->Length());
+ if (!search.GrabMatches(di))
+ return 0;
+ unsigned int lenResult = 0;
+ for (int i = 0; i < *length; i++) {
+ if (text[i] == '\\') {
+ if (text[i + 1] >= '1' && text[i + 1] <= '9') {
+ unsigned int patNum = text[i + 1] - '0';
+ lenResult += search.eopat[patNum] - search.bopat[patNum];
+ i++;
+ } else {
+ switch (text[i + 1]) {
+ case 'a':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'v':
+ case '\\':
+ i++;
+ }
+ lenResult++;
+ }
+ } else {
+ lenResult++;
+ }
+ }
+ substituted = new char[lenResult + 1];
+ char *o = substituted;
+ for (int j = 0; j < *length; j++) {
+ if (text[j] == '\\') {
+ if (text[j + 1] >= '1' && text[j + 1] <= '9') {
+ unsigned int patNum = text[j + 1] - '0';
+ unsigned int len = search.eopat[patNum] - search.bopat[patNum];
+ if (search.pat[patNum]) // Will be null if try for a match that did not occur
+ memcpy(o, search.pat[patNum], len);
+ o += len;
+ j++;
+ } else {
+ j++;
+ switch (text[j]) {
+ case 'a':
+ *o++ = '\a';
+ break;
+ case 'b':
+ *o++ = '\b';
+ break;
+ case 'f':
+ *o++ = '\f';
+ break;
+ case 'n':
+ *o++ = '\n';
+ break;
+ case 'r':
+ *o++ = '\r';
+ break;
+ case 't':
+ *o++ = '\t';
+ break;
+ case 'v':
+ *o++ = '\v';
+ break;
+ case '\\':
+ *o++ = '\\';
+ break;
+ default:
+ *o++ = '\\';
+ j--;
+ }
+ }
+ } else {
+ *o++ = text[j];
+ }
+ }
+ *o = '\0';
+ *length = lenResult;
+ return substituted;
+}
+
+#ifndef SCI_OWNREGEX
+
+#ifdef SCI_NAMESPACE
+
+RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) {
+ return new BuiltinRegex(charClassTable);
+}
+
+#else
+
+RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) {
+ return new BuiltinRegex(charClassTable);
+}
+
+#endif
+
+#endif
diff --git a/scintilla/src/Document.h b/scintilla/src/Document.h
new file mode 100644
index 0000000..ceb2c6d
--- /dev/null
+++ b/scintilla/src/Document.h
@@ -0,0 +1,426 @@
+// Scintilla source code edit control
+/** @file Document.h
+ ** Text document that handles notifications, DBCS, styling, words and end of line.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef DOCUMENT_H
+#define DOCUMENT_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ * A Position is a position within a document between two characters or at the beginning or end.
+ * Sometimes used as a character index where it identifies the character after the position.
+ */
+typedef int Position;
+const Position invalidPosition = -1;
+
+/**
+ * The range class represents a range of text in a document.
+ * The two values are not sorted as one end may be more significant than the other
+ * as is the case for the selection where the end position is the position of the caret.
+ * If either position is invalidPosition then the range is invalid and most operations will fail.
+ */
+class Range {
+public:
+ Position start;
+ Position end;
+
+ Range(Position pos=0) :
+ start(pos), end(pos) {
+ }
+ Range(Position start_, Position end_) :
+ start(start_), end(end_) {
+ }
+
+ bool Valid() const {
+ return (start != invalidPosition) && (end != invalidPosition);
+ }
+
+ // Is the position within the range?
+ bool Contains(Position pos) const {
+ if (start < end) {
+ return (pos >= start && pos <= end);
+ } else {
+ return (pos <= start && pos >= end);
+ }
+ }
+
+ // Is the character after pos within the range?
+ bool ContainsCharacter(Position pos) const {
+ if (start < end) {
+ return (pos >= start && pos < end);
+ } else {
+ return (pos < start && pos >= end);
+ }
+ }
+
+ bool Contains(Range other) const {
+ return Contains(other.start) && Contains(other.end);
+ }
+
+ bool Overlaps(Range other) const {
+ return
+ Contains(other.start) ||
+ Contains(other.end) ||
+ other.Contains(start) ||
+ other.Contains(end);
+ }
+};
+
+class DocWatcher;
+class DocModification;
+class Document;
+
+/**
+ * Interface class for regular expression searching
+ */
+class RegexSearchBase {
+public:
+ virtual ~RegexSearchBase() {}
+
+ virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0;
+
+ ///@return String with the substitutions, must remain valid until the next call or destruction
+ virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0;
+};
+
+/// Factory function for RegexSearchBase
+extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);
+
+struct StyledText {
+ size_t length;
+ const char *text;
+ bool multipleStyles;
+ size_t style;
+ const unsigned char *styles;
+ StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) :
+ length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
+ }
+ // Return number of bytes from start to before '\n' or end of text.
+ // Return 1 when start is outside text
+ size_t LineLength(size_t start) const {
+ size_t cur = start;
+ while ((cur < length) && (text[cur] != '\n'))
+ cur++;
+ return cur-start;
+ }
+ size_t StyleAt(size_t i) const {
+ return multipleStyles ? styles[i] : style;
+ }
+};
+
+class CaseFolder {
+public:
+ virtual ~CaseFolder() {
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0;
+};
+
+class CaseFolderTable : public CaseFolder {
+protected:
+ char mapping[256];
+public:
+ CaseFolderTable();
+ virtual ~CaseFolderTable();
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed);
+ void SetTranslation(char ch, char chTranslation);
+ void StandardASCII();
+};
+
+/**
+ */
+class Document : PerLine {
+
+public:
+ /** Used to pair watcher pointer with user data. */
+ class WatcherWithUserData {
+ public:
+ DocWatcher *watcher;
+ void *userData;
+ WatcherWithUserData() {
+ watcher = 0;
+ userData = 0;
+ }
+ };
+
+ enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation };
+private:
+ int refCount;
+ CellBuffer cb;
+ CharClassify charClass;
+ char stylingMask;
+ int endStyled;
+ int styleClock;
+ int enteredModification;
+ int enteredStyling;
+ int enteredReadOnlyCount;
+
+ WatcherWithUserData *watchers;
+ int lenWatchers;
+
+ // ldSize is not real data - it is for dimensions and loops
+ enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
+ PerLine *perLineData[ldSize];
+
+ bool matchesValid;
+ RegexSearchBase *regex;
+
+public:
+ int stylingBits;
+ int stylingBitsMask;
+
+ int eolMode;
+ /// Can also be SC_CP_UTF8 to enable UTF-8 mode
+ int dbcsCodePage;
+ int tabInChars;
+ int indentInChars;
+ int actualIndentInChars;
+ bool useTabs;
+ bool tabIndents;
+ bool backspaceUnindents;
+
+ DecorationList decorations;
+
+ Document();
+ virtual ~Document();
+
+ int AddRef();
+ int Release();
+
+ virtual void Init();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ int LineFromPosition(int pos) const;
+ int ClampPositionIntoDocument(int pos);
+ bool IsCrLf(int pos);
+ int LenChar(int pos);
+ bool InGoodUTF8(int pos, int &start, int &end);
+ int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
+
+ // Gateways to modifying document
+ void ModifiedAt(int pos);
+ void CheckReadOnly();
+ bool DeleteChars(int pos, int len);
+ bool InsertString(int position, const char *s, int insertLength);
+ int Undo();
+ int Redo();
+ bool CanUndo() { return cb.CanUndo(); }
+ bool CanRedo() { return cb.CanRedo(); }
+ void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
+ bool SetUndoCollection(bool collectUndo) {
+ return cb.SetUndoCollection(collectUndo);
+ }
+ bool IsCollectingUndo() { return cb.IsCollectingUndo(); }
+ void BeginUndoAction() { cb.BeginUndoAction(); }
+ void EndUndoAction() { cb.EndUndoAction(); }
+ void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
+ void SetSavePoint();
+ bool IsSavePoint() { return cb.IsSavePoint(); }
+ const char *BufferPointer() { return cb.BufferPointer(); }
+
+ int GetLineIndentation(int line);
+ void SetLineIndentation(int line, int indent);
+ int GetLineIndentPosition(int line) const;
+ int GetColumn(int position);
+ int FindColumn(int line, int column);
+ void Indent(bool forwards, int lineBottom, int lineTop);
+ static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode);
+ void ConvertLineEnds(int eolModeSet);
+ void SetReadOnly(bool set) { cb.SetReadOnly(set); }
+ bool IsReadOnly() { return cb.IsReadOnly(); }
+
+ bool InsertChar(int pos, char ch);
+ bool InsertCString(int position, const char *s);
+ void ChangeChar(int pos, char ch);
+ void DelChar(int pos);
+ void DelCharBack(int pos);
+
+ char CharAt(int position) { return cb.CharAt(position); }
+ void GetCharRange(char *buffer, int position, int lengthRetrieve) const {
+ cb.GetCharRange(buffer, position, lengthRetrieve);
+ }
+ char StyleAt(int position) const { return cb.StyleAt(position); }
+ int GetMark(int 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);
+ int LineFromHandle(int markerHandle);
+ int LineStart(int line) const;
+ int LineEnd(int line) const;
+ int LineEndPosition(int position) const;
+ bool IsLineEndPosition(int position) const;
+ int VCHomePosition(int position) const;
+
+ int SetLevel(int line, int level);
+ int GetLevel(int line) const;
+ void ClearLevels();
+ int GetLastChild(int lineParent, int level=-1);
+ int GetFoldParent(int line);
+
+ void Indent(bool forwards);
+ int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
+ int NextWordStart(int pos, int delta);
+ int NextWordEnd(int pos, int delta);
+ int Length() const { return cb.Length(); }
+ void Allocate(int newSize) { cb.Allocate(newSize); }
+ size_t ExtractChar(int pos, char *bytes);
+ bool MatchesWordOptions(bool word, bool wordStart, int pos, int length);
+ long FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word,
+ bool wordStart, bool regExp, int flags, int *length, CaseFolder *pcf);
+ const char *SubstituteByPosition(const char *text, int *length);
+ int LinesTotal() const;
+
+ void ChangeCase(Range r, bool makeUpperCase);
+
+ void SetDefaultCharClasses(bool includeWordClass);
+ void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
+ void SetStylingBits(int bits);
+ void StartStyling(int position, char mask);
+ bool SetStyleFor(int length, char style);
+ bool SetStyles(int length, const char *styles);
+ int GetEndStyled() { return endStyled; }
+ void EnsureStyledTo(int pos);
+ int GetStyleClock() { return styleClock; }
+ void IncrementStyleClock();
+ void DecorationFillRange(int position, int value, int fillLength);
+
+ int SetLineState(int line, int state);
+ int GetLineState(int line) const;
+ int GetMaxLineState();
+
+ StyledText MarginStyledText(int line);
+ void MarginSetStyle(int line, int style);
+ void MarginSetStyles(int line, const unsigned char *styles);
+ void MarginSetText(int line, const char *text);
+ int MarginLength(int line) const;
+ void MarginClearAll();
+
+ bool AnnotationAny() const;
+ StyledText AnnotationStyledText(int line);
+ void AnnotationSetText(int line, const char *text);
+ void AnnotationSetStyle(int line, int style);
+ void AnnotationSetStyles(int line, const unsigned char *styles);
+ int AnnotationLength(int line) const;
+ int AnnotationLines(int line) const;
+ void AnnotationClearAll();
+
+ bool AddWatcher(DocWatcher *watcher, void *userData);
+ bool RemoveWatcher(DocWatcher *watcher, void *userData);
+ const WatcherWithUserData *GetWatchers() const { return watchers; }
+ int GetLenWatchers() const { return lenWatchers; }
+
+ bool IsWordPartSeparator(char ch);
+ int WordPartLeft(int pos);
+ int WordPartRight(int pos);
+ int ExtendStyleRange(int pos, int delta, bool singleLine = false);
+ bool IsWhiteLine(int line) const;
+ int ParaUp(int pos);
+ int ParaDown(int pos);
+ int IndentSize() { return actualIndentInChars; }
+ int BraceMatch(int position, int maxReStyle);
+
+private:
+ CharClassify::cc WordCharClass(unsigned char ch);
+ bool IsWordStartAt(int pos);
+ bool IsWordEndAt(int pos);
+ bool IsWordAt(int start, int end);
+
+ void NotifyModifyAttempt();
+ void NotifySavePoint(bool atSavePoint);
+ void NotifyModified(DocModification mh);
+};
+
+class UndoGroup {
+ Document *pdoc;
+ bool groupNeeded;
+public:
+ UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
+ pdoc(pdoc_), groupNeeded(groupNeeded_) {
+ if (groupNeeded) {
+ pdoc->BeginUndoAction();
+ }
+ }
+ ~UndoGroup() {
+ if (groupNeeded) {
+ pdoc->EndUndoAction();
+ }
+ }
+ bool Needed() const {
+ return groupNeeded;
+ }
+};
+
+
+/**
+ * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
+ * scope of the change.
+ * If the DocWatcher is a document view then this can be used to optimise screen updating.
+ */
+class DocModification {
+public:
+ int modificationType;
+ int position;
+ int length;
+ int linesAdded; /**< Negative if lines deleted. */
+ const char *text; /**< Only valid for changes to text, not for changes to style. */
+ int line;
+ int foldLevelNow;
+ int foldLevelPrev;
+ int annotationLinesAdded;
+ int token;
+
+ DocModification(int modificationType_, int position_=0, int length_=0,
+ int linesAdded_=0, const char *text_=0, int line_=0) :
+ modificationType(modificationType_),
+ position(position_),
+ length(length_),
+ linesAdded(linesAdded_),
+ text(text_),
+ line(line_),
+ foldLevelNow(0),
+ foldLevelPrev(0),
+ annotationLinesAdded(0),
+ token(0) {}
+
+ DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
+ modificationType(modificationType_),
+ position(act.position),
+ length(act.lenData),
+ linesAdded(linesAdded_),
+ text(act.data),
+ line(0),
+ foldLevelNow(0),
+ foldLevelPrev(0),
+ annotationLinesAdded(0),
+ token(0) {}
+};
+
+/**
+ * A class that wants to receive notifications from a Document must be derived from DocWatcher
+ * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
+ */
+class DocWatcher {
+public:
+ virtual ~DocWatcher() {}
+
+ virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
+ virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
+ virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
+ virtual void NotifyDeleted(Document *doc, void *userData) = 0;
+ virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/DocumentAccessor.cxx b/scintilla/src/DocumentAccessor.cxx
new file mode 100644
index 0000000..6c59002
--- /dev/null
+++ b/scintilla/src/DocumentAccessor.cxx
@@ -0,0 +1,199 @@
+// Scintilla source code edit control
+/** @file DocumentAccessor.cxx
+ ** Rapid easy access to contents of a Scintilla.
+ **/
+// Copyright 1998-2001 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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "DocumentAccessor.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "CellBuffer.h"
+#include "Scintilla.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+DocumentAccessor::~DocumentAccessor() {
+}
+
+bool DocumentAccessor::InternalIsLeadByte(char ch) {
+ if (SC_CP_UTF8 == codePage)
+ // For lexing, all characters >= 0x80 are treated the
+ // same so none is considered a lead byte.
+ return false;
+ else
+ return Platform::IsDBCSLeadByte(codePage, ch);
+}
+
+void DocumentAccessor::Fill(int position) {
+ if (lenDoc == -1)
+ lenDoc = pdoc->Length();
+ startPos = position - slopSize;
+ if (startPos + bufferSize > lenDoc)
+ startPos = lenDoc - bufferSize;
+ if (startPos < 0)
+ startPos = 0;
+ endPos = startPos + bufferSize;
+ if (endPos > lenDoc)
+ endPos = lenDoc;
+
+ pdoc->GetCharRange(buf, startPos, endPos-startPos);
+ buf[endPos-startPos] = '\0';
+}
+
+bool DocumentAccessor::Match(int pos, const char *s) {
+ for (int i=0; *s; i++) {
+ if (*s != SafeGetCharAt(pos+i))
+ return false;
+ s++;
+ }
+ return true;
+}
+
+char DocumentAccessor::StyleAt(int position) {
+ // Mask off all bits which aren't in the 'mask'.
+ return static_cast<char>(pdoc->StyleAt(position) & mask);
+}
+
+int DocumentAccessor::GetLine(int position) {
+ return pdoc->LineFromPosition(position);
+}
+
+int DocumentAccessor::LineStart(int line) {
+ return pdoc->LineStart(line);
+}
+
+int DocumentAccessor::LevelAt(int line) {
+ return pdoc->GetLevel(line);
+}
+
+int DocumentAccessor::Length() {
+ if (lenDoc == -1)
+ lenDoc = pdoc->Length();
+ return lenDoc;
+}
+
+int DocumentAccessor::GetLineState(int line) {
+ return pdoc->GetLineState(line);
+}
+
+int DocumentAccessor::SetLineState(int line, int state) {
+ return pdoc->SetLineState(line, 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;
+}
+
+void DocumentAccessor::StartSegment(unsigned int pos) {
+ startSeg = pos;
+}
+
+void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) {
+ // Only perform styling if non empty range
+ if (pos != startSeg - 1) {
+ PLATFORM_ASSERT(pos >= startSeg);
+ if (pos < startSeg) {
+ return;
+ }
+
+ if (validLen + (pos - startSeg + 1) >= bufferSize)
+ Flush();
+ if (validLen + (pos - startSeg + 1) >= bufferSize) {
+ // Too big for buffer so send directly
+ pdoc->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
+ } else {
+ if (chAttr != chWhile)
+ chFlags = 0;
+ chAttr |= chFlags;
+ for (unsigned int i = startSeg; i <= pos; i++) {
+ PLATFORM_ASSERT((startPosStyling + validLen) < Length());
+ styleBuf[validLen++] = static_cast<char>(chAttr);
+ }
+ }
+ }
+ startSeg = pos+1;
+}
+
+void DocumentAccessor::SetLevel(int line, int level) {
+ pdoc->SetLevel(line, level);
+}
+
+void DocumentAccessor::Flush() {
+ startPos = extremePosition;
+ lenDoc = -1;
+ if (validLen > 0) {
+ pdoc->SetStyles(validLen, styleBuf);
+ startPosStyling += validLen;
+ validLen = 0;
+ }
+}
+
+int DocumentAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
+ int end = Length();
+ int spaceFlags = 0;
+
+ // Determines the indentation level of the current line and also checks for consistent
+ // indentation compared to the previous line.
+ // Indentation is judged consistent when the indentation whitespace of each line lines
+ // the same or the indentation of one line is a prefix of the other.
+
+ int pos = LineStart(line);
+ char ch = (*this)[pos];
+ int indent = 0;
+ bool inPrevPrefix = line > 0;
+ int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
+ while ((ch == ' ' || ch == '\t') && (pos < end)) {
+ if (inPrevPrefix) {
+ char chPrev = (*this)[posPrev++];
+ if (chPrev == ' ' || chPrev == '\t') {
+ if (chPrev != ch)
+ spaceFlags |= wsInconsistent;
+ } else {
+ inPrevPrefix = false;
+ }
+ }
+ if (ch == ' ') {
+ spaceFlags |= wsSpace;
+ indent++;
+ } else { // Tab
+ spaceFlags |= wsTab;
+ if (spaceFlags & wsSpace)
+ spaceFlags |= wsSpaceTab;
+ indent = (indent / 8 + 1) * 8;
+ }
+ ch = (*this)[++pos];
+ }
+
+ *flags = spaceFlags;
+ indent += SC_FOLDLEVELBASE;
+ // if completely empty line or the start of a comment...
+ if ((ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ||
+ (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)))
+ return indent | SC_FOLDLEVELWHITEFLAG;
+ else
+ return indent;
+}
+
+void DocumentAccessor::IndicatorFill(int start, int end, int indicator, int value) {
+ pdoc->decorations.SetCurrentIndicator(indicator);
+ pdoc->DecorationFillRange(start, value, end - start);
+}
diff --git a/scintilla/src/DocumentAccessor.h b/scintilla/src/DocumentAccessor.h
new file mode 100644
index 0000000..5e1f434
--- /dev/null
+++ b/scintilla/src/DocumentAccessor.h
@@ -0,0 +1,77 @@
+// Scintilla source code edit control
+/** @file DocumentAccessor.h
+ ** Implementation of BufferAccess and StylingAccess on a Scintilla
+ ** rapid easy access to contents of a Scintilla.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class Document;
+
+/**
+ */
+
+class DocumentAccessor : public Accessor {
+ // Private so DocumentAccessor objects can not be copied
+ DocumentAccessor(const DocumentAccessor &source);
+ DocumentAccessor &operator=(const DocumentAccessor &);
+
+protected:
+ Document *pdoc;
+ PropertyGet &props;
+ WindowID id;
+ int lenDoc;
+
+ char styleBuf[bufferSize];
+ int validLen;
+ char chFlags;
+ char chWhile;
+ unsigned int startSeg;
+ int startPosStyling;
+ int mask;
+
+ bool InternalIsLeadByte(char ch);
+ void Fill(int position);
+
+public:
+ DocumentAccessor(Document *pdoc_, PropertyGet &props_, WindowID id_=0) :
+ Accessor(), pdoc(pdoc_), props(props_), id(id_),
+ lenDoc(-1), validLen(0), chFlags(0), chWhile(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);
+ char StyleAt(int position);
+ int GetLine(int position);
+ int LineStart(int line);
+ int LevelAt(int line);
+ int Length();
+ void Flush();
+ int GetLineState(int line);
+ int SetLineState(int line, int state);
+ int GetPropertyInt(const char *key, int defaultValue=0) {
+ return props.GetInt(key, defaultValue);
+ }
+ char *GetProperties() {
+ return props.ToString();
+ }
+ WindowID GetWindow() { return id; }
+
+ void StartAt(unsigned int start, char chMask=31);
+ void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }
+ unsigned int GetStartSegment() { return startSeg; }
+ void StartSegment(unsigned int pos);
+ void ColourTo(unsigned int pos, int chAttr);
+ void SetLevel(int line, int level);
+ int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
+ void IndicatorFill(int start, int end, int indicator, int value);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx
new file mode 100644
index 0000000..36a0099
--- /dev/null
+++ b/scintilla/src/Editor.cxx
@@ -0,0 +1,8694 @@
+// Scintilla source code edit control
+/** @file Editor.cxx
+ ** Main code for the edit control.
+ **/
+// Copyright 1998-2004 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 <stdio.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <memory>
+
+// With Borland C++ 5.5, including <string> includes Windows.h leading to defining
+// FindText to FindTextA which makes calls here to Document::FindText fail.
+#ifdef __BORLANDC__
+#ifdef FindText
+#undef FindText
+#endif
+#endif
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+ 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) {}
+
+Timer::Timer() :
+ ticking(false), ticksToWait(0), tickerID(0) {}
+
+Idler::Idler() :
+ state(false), idlerID(0) {}
+
+static inline bool IsControlCharacter(int ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+Editor::Editor() {
+ ctrlID = 0;
+
+ stylesValid = false;
+
+ printMagnification = 0;
+ printColourMode = SC_PRINT_NORMAL;
+ printWrapState = eWrapWord;
+ cursorMode = SC_CURSORNORMAL;
+ controlCharSymbol = 0; /* Draw the control characters */
+
+ hasFocus = false;
+ hideSelection = false;
+ inOverstrike = false;
+ errorStatus = 0;
+ mouseDownCaptures = true;
+
+ bufferedDraw = true;
+ twoPhaseDraw = true;
+
+ lastClickTime = 0;
+ dwellDelay = SC_TIME_FOREVER;
+ ticksToDwell = SC_TIME_FOREVER;
+ dwelling = false;
+ ptMouseLast.x = 0;
+ ptMouseLast.y = 0;
+ inDragDrop = ddNone;
+ dropWentOutside = false;
+ posDrag = SelectionPosition(invalidPosition);
+ posDrop = SelectionPosition(invalidPosition);
+ selectionType = selChar;
+
+ lastXChosen = 0;
+ lineAnchor = 0;
+ originalAnchorPos = 0;
+
+ primarySelection = true;
+
+ caretXPolicy = CARET_SLOP | CARET_EVEN;
+ caretXSlop = 50;
+
+ caretYPolicy = CARET_EVEN;
+ caretYSlop = 0;
+
+ searchAnchor = 0;
+
+ xOffset = 0;
+ xCaretMargin = 50;
+ horizontalScrollBarVisible = true;
+ scrollWidth = 2000;
+ trackLineWidth = false;
+ lineWidthMaxSeen = 0;
+ verticalScrollBarVisible = true;
+ endAtLastLine = true;
+ caretSticky = false;
+ multipleSelection = false;
+ additionalSelectionTyping = false;
+ multiPasteMode = SC_MULTIPASTE_ONCE;
+ additionalCaretsBlink = true;
+ additionalCaretsVisible = true;
+ virtualSpaceOptions = SCVS_NONE;
+
+ pixmapLine = Surface::Allocate();
+ pixmapSelMargin = Surface::Allocate();
+ pixmapSelPattern = Surface::Allocate();
+ pixmapIndentGuide = Surface::Allocate();
+ pixmapIndentGuideHighlight = Surface::Allocate();
+
+ targetStart = 0;
+ targetEnd = 0;
+ searchFlags = 0;
+
+ topLine = 0;
+ posTopLine = 0;
+
+ lengthForEncode = -1;
+
+ needUpdateUI = true;
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+ bracesMatchStyle = STYLE_BRACEBAD;
+ highlightGuideColumn = 0;
+
+ theEdge = 0;
+
+ paintState = notPainting;
+
+ modEventMask = SC_MODEVENTMASKALL;
+
+ pdoc = new Document();
+ pdoc->AddRef();
+ pdoc->AddWatcher(this, 0);
+
+ recordingMacro = false;
+ foldFlags = 0;
+
+ wrapState = eWrapNone;
+ wrapWidth = LineLayout::wrapWidthInfinite;
+ wrapStart = wrapLineLarge;
+ wrapEnd = wrapLineLarge;
+ wrapVisualFlags = 0;
+ wrapVisualFlagsLocation = 0;
+ wrapVisualStartIndent = 0;
+ wrapIndentMode = SC_WRAPINDENT_FIXED;
+ wrapAddIndent = 0;
+
+ convertPastes = true;
+
+ hsStart = -1;
+ hsEnd = -1;
+
+ llc.SetLevel(LineLayoutCache::llcCaret);
+ posCache.SetSize(0x400);
+}
+
+Editor::~Editor() {
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ pdoc = 0;
+ DropGraphics();
+ delete pixmapLine;
+ delete pixmapSelMargin;
+ delete pixmapSelPattern;
+ delete pixmapIndentGuide;
+ delete pixmapIndentGuideHighlight;
+}
+
+void Editor::Finalise() {
+ SetIdle(false);
+ CancelModes();
+}
+
+void Editor::DropGraphics() {
+ pixmapLine->Release();
+ pixmapSelMargin->Release();
+ pixmapSelPattern->Release();
+ pixmapIndentGuide->Release();
+ pixmapIndentGuideHighlight->Release();
+}
+
+void Editor::InvalidateStyleData() {
+ stylesValid = false;
+ DropGraphics();
+ palette.Release();
+ llc.Invalidate(LineLayout::llInvalid);
+ posCache.Clear();
+}
+
+void Editor::InvalidateStyleRedraw() {
+ NeedWrapping();
+ InvalidateStyleData();
+ Redraw();
+}
+
+void Editor::RefreshColourPalette(Palette &pal, bool want) {
+ vs.RefreshColourPalette(pal, want);
+}
+
+void Editor::RefreshStyleData() {
+ if (!stylesValid) {
+ stylesValid = true;
+ AutoSurface surface(this);
+ if (surface) {
+ vs.Refresh(*surface);
+ RefreshColourPalette(palette, true);
+ palette.Allocate(wMain);
+ RefreshColourPalette(palette, false);
+ }
+ if (wrapIndentMode == SC_WRAPINDENT_INDENT) {
+ wrapAddIndent = pdoc->IndentSize() * vs.spaceWidth;
+ } else if (wrapIndentMode == SC_WRAPINDENT_SAME) {
+ wrapAddIndent = 0;
+ } else { //SC_WRAPINDENT_FIXED
+ wrapAddIndent = wrapVisualStartIndent * vs.aveCharWidth;
+ if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (wrapAddIndent <= 0))
+ wrapAddIndent = vs.aveCharWidth; // must indent to show start visual
+ }
+ SetScrollBars();
+ SetRectangularRange();
+ }
+}
+
+PRectangle Editor::GetClientRectangle() {
+ return wMain.GetClientPosition();
+}
+
+PRectangle Editor::GetTextRectangle() {
+ PRectangle rc = GetClientRectangle();
+ rc.left += vs.fixedColumnWidth;
+ rc.right -= vs.rightMarginWidth;
+ return rc;
+}
+
+int Editor::LinesOnScreen() {
+ PRectangle rcClient = GetClientRectangle();
+ int htClient = rcClient.bottom - rcClient.top;
+ //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
+ return htClient / vs.lineHeight;
+}
+
+int Editor::LinesToScroll() {
+ int retVal = LinesOnScreen() - 1;
+ if (retVal < 1)
+ return 1;
+ else
+ return retVal;
+}
+
+int Editor::MaxScrollPos() {
+ //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
+ //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
+ int retVal = cs.LinesDisplayed();
+ if (endAtLastLine) {
+ retVal -= LinesOnScreen();
+ } else {
+ retVal--;
+ }
+ if (retVal < 0) {
+ return 0;
+ } else {
+ return retVal;
+ }
+}
+
+const char *ControlCharacterString(unsigned char ch) {
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ if (ch < (sizeof(reps) / sizeof(reps[0]))) {
+ return reps[ch];
+ } else {
+ return "BAD";
+ }
+}
+
+/**
+ * Convenience class to ensure LineLayout objects are always disposed.
+ */
+class AutoLineLayout {
+ LineLayoutCache &llc;
+ LineLayout *ll;
+ AutoLineLayout &operator=(const AutoLineLayout &);
+public:
+ AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
+ ~AutoLineLayout() {
+ llc.Dispose(ll);
+ ll = 0;
+ }
+ LineLayout *operator->() const {
+ return ll;
+ }
+ operator LineLayout *() const {
+ return ll;
+ }
+ void Set(LineLayout *ll_) {
+ llc.Dispose(ll);
+ ll = ll_;
+ }
+};
+
+SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
+ if (sp.Position() < 0) {
+ return SelectionPosition(0);
+ } else if (sp.Position() > pdoc->Length()) {
+ return SelectionPosition(pdoc->Length());
+ } else {
+ // If not at end of line then set offset to 0
+ if (!pdoc->IsLineEndPosition(sp.Position()))
+ sp.SetVirtualSpace(0);
+ return sp;
+ }
+}
+
+Point Editor::LocationFromPosition(SelectionPosition pos) {
+ Point pt;
+ RefreshStyleData();
+ if (pos.Position() == INVALID_POSITION)
+ return pt;
+ int line = pdoc->LineFromPosition(pos.Position());
+ int lineVisible = cs.DisplayFromDoc(line);
+ //Platform::DebugPrintf("line=%d\n", line);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ if (surface && ll) {
+ // -1 because of adding in for visible lines in following loop.
+ pt.y = (lineVisible - topLine - 1) * vs.lineHeight;
+ pt.x = 0;
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ int posInLine = pos.Position() - posLineStart;
+ // In case of very long line put x at arbitrary large position
+ if (posInLine > ll->maxLineLength) {
+ pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];
+ }
+
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)];
+ if (ll->wrapIndent != 0) {
+ int lineStart = ll->LineStart(subLine);
+ if (lineStart != 0) // Wrapped
+ pt.x += ll->wrapIndent;
+ }
+ }
+ if (posInLine >= ll->LineStart(subLine)) {
+ pt.y += vs.lineHeight;
+ }
+ }
+ pt.x += vs.fixedColumnWidth - xOffset;
+ }
+ pt.x += pos.VirtualSpace() * static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth);
+ return pt;
+}
+
+Point Editor::LocationFromPosition(int pos) {
+ return LocationFromPosition(SelectionPosition(pos));
+}
+
+int Editor::XFromPosition(int pos) {
+ Point pt = LocationFromPosition(pos);
+ return pt.x - vs.fixedColumnWidth + xOffset;
+}
+
+int Editor::XFromPosition(SelectionPosition sp) {
+ Point pt = LocationFromPosition(sp);
+ return pt.x - vs.fixedColumnWidth + xOffset;
+}
+
+int Editor::LineFromLocation(Point pt) {
+ return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+}
+
+void Editor::SetTopLine(int topLineNew) {
+ topLine = topLineNew;
+ posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
+}
+
+SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) {
+ RefreshStyleData();
+ if (canReturnInvalid) {
+ PRectangle rcClient = GetTextRectangle();
+ if (!rcClient.Contains(pt))
+ return SelectionPosition(INVALID_POSITION);
+ if (pt.x < vs.fixedColumnWidth)
+ return SelectionPosition(INVALID_POSITION);
+ if (pt.y < 0)
+ return SelectionPosition(INVALID_POSITION);
+ }
+ pt.x = pt.x - vs.fixedColumnWidth + xOffset;
+ int visibleLine = pt.y / vs.lineHeight + topLine;
+ if (pt.y < 0) { // Division rounds towards 0
+ visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine;
+ }
+ if (!canReturnInvalid && (visibleLine < 0))
+ visibleLine = 0;
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ if (canReturnInvalid && (lineDoc < 0))
+ return SelectionPosition(INVALID_POSITION);
+ if (lineDoc >= pdoc->LinesTotal())
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length());
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ SelectionPosition retVal(canReturnInvalid ? INVALID_POSITION : static_cast<int>(posLineStart));
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ int lineStartSet = cs.DisplayFromDoc(lineDoc);
+ int subLine = visibleLine - lineStartSet;
+ if (subLine < ll->lines) {
+ int lineStart = ll->LineStart(subLine);
+ int lineEnd = ll->LineLastVisible(subLine);
+ int subLineStart = ll->positions[lineStart];
+
+ if (ll->wrapIndent != 0) {
+ if (lineStart != 0) // Wrapped
+ pt.x -= ll->wrapIndent;
+ }
+ int i = ll->FindBefore(pt.x + subLineStart, lineStart, lineEnd);
+ while (i < lineEnd) {
+ if (charPosition) {
+ if ((pt.x + subLineStart) < (ll->positions[i + 1])) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
+ }
+ } else {
+ if ((pt.x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
+ }
+ }
+ i++;
+ }
+ if (virtualSpace) {
+ const int spaceWidth = static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth);
+ int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) /
+ spaceWidth;
+ return SelectionPosition(lineEnd + posLineStart, spaceOffset);
+ } else if (canReturnInvalid) {
+ if (pt.x < (ll->positions[lineEnd] - subLineStart)) {
+ return SelectionPosition(pdoc->MovePositionOutsideChar(lineEnd + posLineStart, 1));
+ }
+ } else {
+ return SelectionPosition(lineEnd + posLineStart);
+ }
+ }
+ if (!canReturnInvalid)
+ return SelectionPosition(ll->numCharsInLine + posLineStart);
+ }
+ return retVal;
+}
+
+int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) {
+ return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position();
+}
+
+/**
+ * Find the document position corresponding to an x coordinate on a particular document line.
+ * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
+ */
+int Editor::PositionFromLineX(int lineDoc, int x) {
+ RefreshStyleData();
+ if (lineDoc >= pdoc->LinesTotal())
+ return pdoc->Length();
+ //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ int retVal = 0;
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ retVal = ll->numCharsBeforeEOL + posLineStart;
+ int subLine = 0;
+ int lineStart = ll->LineStart(subLine);
+ int lineEnd = ll->LineLastVisible(subLine);
+ int subLineStart = ll->positions[lineStart];
+
+ if (ll->wrapIndent != 0) {
+ if (lineStart != 0) // Wrapped
+ x -= ll->wrapIndent;
+ }
+ int i = ll->FindBefore(x + subLineStart, lineStart, lineEnd);
+ while (i < lineEnd) {
+ if ((x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
+ retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1);
+ break;
+ }
+ i++;
+ }
+ }
+ return retVal;
+}
+
+/**
+ * Find the document position corresponding to an x coordinate on a particular document line.
+ * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
+ */
+SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) {
+ RefreshStyleData();
+ if (lineDoc >= pdoc->LinesTotal())
+ return SelectionPosition(pdoc->Length());
+ //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ int retVal = 0;
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ int subLine = 0;
+ int lineStart = ll->LineStart(subLine);
+ int lineEnd = ll->LineLastVisible(subLine);
+ int subLineStart = ll->positions[lineStart];
+
+ if (ll->wrapIndent != 0) {
+ if (lineStart != 0) // Wrapped
+ x -= ll->wrapIndent;
+ }
+ int i = ll->FindBefore(x + subLineStart, lineStart, lineEnd);
+ while (i < lineEnd) {
+ if ((x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
+ retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1);
+ return SelectionPosition(retVal);
+ }
+ i++;
+ }
+ const int spaceWidth = static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth);
+ int spaceOffset = (x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth;
+ return SelectionPosition(lineEnd + posLineStart, spaceOffset);
+ }
+ return SelectionPosition(retVal);
+}
+
+/**
+ * If painting then abandon the painting because a wider redraw is needed.
+ * @return true if calling code should stop drawing.
+ */
+bool Editor::AbandonPaint() {
+ if ((paintState == painting) && !paintingAllText) {
+ paintState = paintAbandoned;
+ }
+ return paintState == paintAbandoned;
+}
+
+void Editor::RedrawRect(PRectangle rc) {
+ //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);
+
+ // Clip the redraw rectangle into the client area
+ PRectangle rcClient = GetClientRectangle();
+ if (rc.top < rcClient.top)
+ rc.top = rcClient.top;
+ if (rc.bottom > rcClient.bottom)
+ rc.bottom = rcClient.bottom;
+ if (rc.left < rcClient.left)
+ rc.left = rcClient.left;
+ if (rc.right > rcClient.right)
+ rc.right = rcClient.right;
+
+ if ((rc.bottom > rc.top) && (rc.right > rc.left)) {
+ wMain.InvalidateRectangle(rc);
+ }
+}
+
+void Editor::Redraw() {
+ //Platform::DebugPrintf("Redraw all\n");
+ PRectangle rcClient = GetClientRectangle();
+ wMain.InvalidateRectangle(rcClient);
+ //wMain.InvalidateAll();
+}
+
+void Editor::RedrawSelMargin(int line, bool allAfter) {
+ 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;
+ if (!allAfter)
+ rcSelMargin.bottom = rcLine.bottom;
+ }
+ wMain.InvalidateRectangle(rcSelMargin);
+ }
+ }
+}
+
+PRectangle Editor::RectangleFromRange(int start, int end) {
+ int minPos = start;
+ if (minPos > end)
+ minPos = end;
+ int maxPos = start;
+ if (maxPos < end)
+ maxPos = end;
+ int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
+ int lineDocMax = pdoc->LineFromPosition(maxPos);
+ int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1;
+ PRectangle rcClient = GetTextRectangle();
+ PRectangle rc;
+ rc.left = vs.fixedColumnWidth;
+ rc.top = (minLine - topLine) * vs.lineHeight;
+ if (rc.top < 0)
+ rc.top = 0;
+ rc.right = rcClient.right;
+ rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
+ // Ensure PRectangle is within 16 bit space
+ rc.top = Platform::Clamp(rc.top, -32000, 32000);
+ rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
+
+ return rc;
+}
+
+void Editor::InvalidateRange(int start, int end) {
+ RedrawRect(RectangleFromRange(start, end));
+}
+
+int Editor::CurrentPosition() {
+ return sel.MainCaret();
+}
+
+bool Editor::SelectionEmpty() {
+ return sel.Empty();
+}
+
+SelectionPosition Editor::SelectionStart() {
+ return sel.RangeMain().Start();
+}
+
+SelectionPosition Editor::SelectionEnd() {
+ return sel.RangeMain().End();
+}
+
+void Editor::SetRectangularRange() {
+ if (sel.IsRectangular()) {
+ int xAnchor = XFromPosition(sel.Rectangular().anchor);
+ int xCaret = XFromPosition(sel.Rectangular().caret);
+ if (sel.selType == Selection::selThin) {
+ xCaret = xAnchor;
+ }
+ int lineAnchor = pdoc->LineFromPosition(sel.Rectangular().anchor.Position());
+ int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position());
+ int increment = (lineCaret > lineAnchor) ? 1 : -1;
+ for (int line=lineAnchor; line != lineCaret+increment; line += increment) {
+ SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor));
+ if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
+ range.ClearVirtualSpace();
+ if (line == lineAnchor)
+ sel.SetSelection(range);
+ else
+ sel.AddSelection(range);
+ }
+ }
+}
+
+void Editor::ThinRectangularRange() {
+ if (sel.IsRectangular()) {
+ sel.selType = Selection::selThin;
+ if (sel.Rectangular().caret < sel.Rectangular().anchor) {
+ sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor);
+ } else {
+ sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret);
+ }
+ SetRectangularRange();
+ }
+}
+
+void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) {
+ if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) {
+ invalidateWholeSelection = true;
+ }
+ int firstAffected = Platform::Minimum(sel.RangeMain().Start().Position(), newMain.Start().Position());
+ // +1 for lastAffected ensures caret repainted
+ int lastAffected = Platform::Maximum(newMain.caret.Position()+1, newMain.anchor.Position());
+ lastAffected = Platform::Maximum(lastAffected, sel.RangeMain().End().Position());
+ if (invalidateWholeSelection) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ firstAffected = Platform::Minimum(firstAffected, sel.Range(r).caret.Position());
+ firstAffected = Platform::Minimum(firstAffected, sel.Range(r).anchor.Position());
+ lastAffected = Platform::Maximum(lastAffected, sel.Range(r).caret.Position()+1);
+ lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position());
+ }
+ }
+ needUpdateUI = true;
+ InvalidateRange(firstAffected, lastAffected);
+}
+
+void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
+ SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_),
+ ClampPositionIntoDocument(anchor_));
+ if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
+ InvalidateSelection(rangeNew);
+ }
+ sel.RangeMain() = rangeNew;
+ SetRectangularRange();
+ ClaimSelection();
+}
+
+void Editor::SetSelection(int currentPos_, int anchor_) {
+ SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_));
+}
+
+// Just move the caret on the main selection
+void Editor::SetSelection(SelectionPosition currentPos_) {
+ currentPos_ = ClampPositionIntoDocument(currentPos_);
+ if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) {
+ InvalidateSelection(SelectionRange(currentPos_));
+ }
+ if (sel.IsRectangular()) {
+ sel.Rectangular() =
+ SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
+ SetRectangularRange();
+ } else {
+ sel.RangeMain() =
+ SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
+ }
+ ClaimSelection();
+}
+
+void Editor::SetSelection(int currentPos_) {
+ SetSelection(SelectionPosition(currentPos_));
+}
+
+void Editor::SetEmptySelection(SelectionPosition currentPos_) {
+ SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_));
+ if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
+ InvalidateSelection(rangeNew);
+ }
+ sel.Clear();
+ sel.RangeMain() = rangeNew;
+ SetRectangularRange();
+ ClaimSelection();
+
+}
+
+void Editor::SetEmptySelection(int currentPos_) {
+ SetEmptySelection(SelectionPosition(currentPos_));
+}
+
+bool Editor::RangeContainsProtected(int start, int end) const {
+ if (vs.ProtectionActive()) {
+ if (start > end) {
+ int t = start;
+ start = end;
+ end = t;
+ }
+ int mask = pdoc->stylingBitsMask;
+ for (int pos = start; pos < end; pos++) {
+ if (vs.styles[pdoc->StyleAt(pos) & mask].IsProtected())
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Editor::SelectionContainsProtected() {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Asks document to find a good position and then moves out of any invisible positions.
+ */
+int Editor::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const {
+ return MovePositionOutsideChar(SelectionPosition(pos), moveDir, checkLineEnd).Position();
+}
+
+SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd) const {
+ int posMoved = pdoc->MovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd);
+ if (posMoved != pos.Position())
+ pos.SetPosition(posMoved);
+ if (vs.ProtectionActive()) {
+ int mask = pdoc->stylingBitsMask;
+ if (moveDir > 0) {
+ if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()) {
+ while ((pos.Position() < pdoc->Length()) &&
+ (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()))
+ pos.Add(1);
+ }
+ } else if (moveDir < 0) {
+ if (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()) {
+ while ((pos.Position() > 0) &&
+ (vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()))
+ pos.Add(-1);
+ }
+ }
+ }
+ return pos;
+}
+
+int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) {
+ bool simpleCaret = (sel.Count() == 1) && sel.Empty();
+ SelectionPosition spCaret = sel.Last();
+
+ int delta = newPos.Position() - sel.MainCaret();
+ newPos = ClampPositionIntoDocument(newPos);
+ newPos = MovePositionOutsideChar(newPos, delta);
+ if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) {
+ // Can't turn into multiple selection so clear additional selections
+ InvalidateSelection(SelectionRange(newPos), true);
+ SelectionRange rangeMain = sel.RangeMain();
+ sel.SetSelection(rangeMain);
+ }
+ if (!sel.IsRectangular() && (selt == Selection::selRectangle)) {
+ // Switching to rectangular
+ SelectionRange rangeMain = sel.RangeMain();
+ sel.Clear();
+ sel.Rectangular() = rangeMain;
+ }
+ if (selt != Selection::noSel) {
+ sel.selType = selt;
+ }
+ if (selt != Selection::noSel || sel.MoveExtends()) {
+ SetSelection(newPos);
+ } else {
+ SetEmptySelection(newPos);
+ }
+ ShowCaretAtCurrentPosition();
+ if (ensureVisible) {
+ XYScrollPosition newXY = XYScrollToMakeVisible(true, true, true);
+ if (simpleCaret && (newXY.xOffset == xOffset)) {
+ // simple vertical scroll then invalidate
+ ScrollTo(newXY.topLine);
+ InvalidateSelection(SelectionRange(spCaret), true);
+ } else {
+ SetXYScroll(newXY);
+ }
+ }
+ return 0;
+}
+
+int Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) {
+ return MovePositionTo(SelectionPosition(newPos), selt, ensureVisible);
+}
+
+SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) {
+ pos = ClampPositionIntoDocument(pos);
+ pos = MovePositionOutsideChar(pos, moveDir);
+ int lineDoc = pdoc->LineFromPosition(pos.Position());
+ if (cs.GetVisible(lineDoc)) {
+ return pos;
+ } else {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (moveDir > 0) {
+ // lineDisplay is already line before fold as lines in fold use display line of line after fold
+ lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
+ return SelectionPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
+ } else {
+ lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed());
+ return SelectionPosition(pdoc->LineEnd(cs.DocFromDisplay(lineDisplay)));
+ }
+ }
+}
+
+SelectionPosition Editor::MovePositionSoVisible(int pos, int moveDir) {
+ return MovePositionSoVisible(SelectionPosition(pos), moveDir);
+}
+
+Point Editor::PointMainCaret() {
+ return LocationFromPosition(sel.Range(sel.Main()).caret);
+}
+
+/**
+ * Choose the x position that the caret will try to stick to
+ * as it moves up and down.
+ */
+void Editor::SetLastXChosen() {
+ Point pt = PointMainCaret();
+ lastXChosen = pt.x + xOffset;
+}
+
+void Editor::ScrollTo(int line, bool moveThumb) {
+ int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
+ if (topLineNew != topLine) {
+ // Try to optimise small scrolls
+ int linesToMove = topLine - topLineNew;
+ SetTopLine(topLineNew);
+ // Optimize by styling the view as this will invalidate any needed area
+ // which could abort the initial paint if discovered later.
+ StyleToPositionInView(PositionAfterArea(GetClientRectangle()));
+#ifndef UNDER_CE
+ // Perform redraw rather than scroll if many lines would be redrawn anyway.
+ if ((abs(linesToMove) <= 10) && (paintState == notPainting)) {
+ ScrollText(linesToMove);
+ } else {
+ Redraw();
+ }
+#else
+ Redraw();
+#endif
+ if (moveThumb) {
+ SetVerticalScrollPos();
+ }
+ }
+}
+
+void Editor::ScrollText(int /* linesToMove */) {
+ //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
+ Redraw();
+}
+
+void Editor::HorizontalScrollTo(int xPos) {
+ //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
+ if (xPos < 0)
+ xPos = 0;
+ if ((wrapState == eWrapNone) && (xOffset != xPos)) {
+ xOffset = xPos;
+ SetHorizontalScrollPos();
+ RedrawRect(GetClientRectangle());
+ }
+}
+
+void Editor::MoveCaretInsideView(bool ensureVisible) {
+ PRectangle rcClient = GetTextRectangle();
+ Point pt = PointMainCaret();
+ if (pt.y < rcClient.top) {
+ MovePositionTo(SPositionFromLocation(
+ Point(lastXChosen - xOffset, rcClient.top)),
+ Selection::noSel, ensureVisible);
+ } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
+ int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight;
+ MovePositionTo(SPositionFromLocation(
+ Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed)),
+ Selection::noSel, ensureVisible);
+ }
+}
+
+int Editor::DisplayFromPosition(int pos) {
+ int lineDoc = pdoc->LineFromPosition(pos);
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ unsigned int posLineStart = pdoc->LineStart(lineDoc);
+ int posInLine = pos - posLineStart;
+ lineDisplay--; // To make up for first increment ahead.
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if (posInLine >= ll->LineStart(subLine)) {
+ lineDisplay++;
+ }
+ }
+ }
+ return lineDisplay;
+}
+
+/**
+ * Ensure the caret is reasonably visible in context.
+ *
+Caret policy in SciTE
+
+If slop is set, we can define a slop value.
+This value defines an unwanted zone (UZ) where the caret is... unwanted.
+This zone is defined as a number of pixels near the vertical margins,
+and as a number of lines near the horizontal margins.
+By keeping the caret away from the edges, it is seen within its context,
+so it is likely that the identifier that the caret is on can be completely seen,
+and that the current line is seen with some of the lines following it which are
+often dependent on that line.
+
+If strict is set, the policy is enforced... strictly.
+The caret is centred on the display if slop is not set,
+and cannot go in the UZ if slop is set.
+
+If jumps is set, the display is moved more energetically
+so the caret can move in the same direction longer before the policy is applied again.
+'3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.
+
+If even is not set, instead of having symmetrical UZs,
+the left and bottom UZs are extended up to right and top UZs respectively.
+This way, we favour the displaying of useful information: the begining of lines,
+where most code reside, and the lines after the caret, eg. the body of a function.
+
+ | | | | |
+slop | strict | jumps | even | Caret can go to the margin | When reaching limit (caret going out of
+ | | | | | visibility or going into the UZ) display is...
+-----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
+ 0 | 0 | 0 | 0 | Yes | moved to put caret on top/on right
+ 0 | 0 | 0 | 1 | Yes | moved by one position
+ 0 | 0 | 1 | 0 | Yes | moved to put caret on top/on right
+ 0 | 0 | 1 | 1 | Yes | centred on the caret
+ 0 | 1 | - | 0 | Caret is always on top/on right of display | -
+ 0 | 1 | - | 1 | No, caret is always centred | -
+ 1 | 0 | 0 | 0 | Yes | moved to put caret out of the asymmetrical UZ
+ 1 | 0 | 0 | 1 | Yes | moved to put caret out of the UZ
+ 1 | 0 | 1 | 0 | Yes | moved to put caret at 3UZ of the top or right margin
+ 1 | 0 | 1 | 1 | Yes | moved to put caret at 3UZ of the margin
+ 1 | 1 | - | 0 | Caret is always at UZ of top/right margin | -
+ 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position
+ 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
+*/
+
+Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz) {
+ PRectangle rcClient = GetTextRectangle();
+ const SelectionPosition posCaret = posDrag.IsValid() ? posDrag : sel.RangeMain().caret;
+ const Point pt = LocationFromPosition(posCaret);
+ const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
+ const int lineCaret = DisplayFromPosition(posCaret.Position());
+
+ XYScrollPosition newXY(xOffset, topLine);
+
+ // Vertical positioning
+ if (vert && (pt.y < rcClient.top || ptBottomCaret.y > rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
+ const int linesOnScreen = LinesOnScreen();
+ const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
+ const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
+ const bool bStrict = (caretYPolicy & CARET_STRICT) != 0;
+ const bool bJump = (caretYPolicy & CARET_JUMPS) != 0;
+ const bool bEven = (caretYPolicy & CARET_EVEN) != 0;
+
+ // It should be possible to scroll the window to show the caret,
+ // but this fails to remove the caret on GTK+
+ if (bSlop) { // A margin is defined
+ int yMoveT, yMoveB;
+ if (bStrict) {
+ int yMarginT, yMarginB;
+ if (!useMargin) {
+ // In drag mode, avoid moves
+ // otherwise, a double click will select several lines.
+ yMarginT = yMarginB = 0;
+ } else {
+ // yMarginT must equal to caretYSlop, with a minimum of 1 and
+ // a maximum of slightly less than half the heigth of the text area.
+ yMarginT = Platform::Clamp(caretYSlop, 1, halfScreen);
+ if (bEven) {
+ yMarginB = yMarginT;
+ } else {
+ yMarginB = linesOnScreen - yMarginT - 1;
+ }
+ }
+ yMoveT = yMarginT;
+ if (bEven) {
+ if (bJump) {
+ yMoveT = Platform::Clamp(caretYSlop * 3, 1, halfScreen);
+ }
+ yMoveB = yMoveT;
+ } else {
+ yMoveB = linesOnScreen - yMoveT - 1;
+ }
+ if (lineCaret < topLine + yMarginT) {
+ // Caret goes too high
+ newXY.topLine = lineCaret - yMoveT;
+ } else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) {
+ // Caret goes too low
+ newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
+ }
+ } else { // Not strict
+ yMoveT = bJump ? caretYSlop * 3 : caretYSlop;
+ yMoveT = Platform::Clamp(yMoveT, 1, halfScreen);
+ if (bEven) {
+ yMoveB = yMoveT;
+ } else {
+ yMoveB = linesOnScreen - yMoveT - 1;
+ }
+ if (lineCaret < topLine) {
+ // Caret goes too high
+ newXY.topLine = lineCaret - yMoveT;
+ } else if (lineCaret > topLine + linesOnScreen - 1) {
+ // Caret goes too low
+ newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
+ }
+ }
+ } else { // No slop
+ if (!bStrict && !bJump) {
+ // Minimal move
+ if (lineCaret < topLine) {
+ // Caret goes too high
+ newXY.topLine = lineCaret;
+ } else if (lineCaret > topLine + linesOnScreen - 1) {
+ // Caret goes too low
+ if (bEven) {
+ newXY.topLine = lineCaret - linesOnScreen + 1;
+ } else {
+ newXY.topLine = lineCaret;
+ }
+ }
+ } else { // Strict or going out of display
+ if (bEven) {
+ // Always center caret
+ newXY.topLine = lineCaret - halfScreen;
+ } else {
+ // Always put caret on top of display
+ newXY.topLine = lineCaret;
+ }
+ }
+ }
+ newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
+ }
+
+ // Horizontal positioning
+ if (horiz && (wrapState == eWrapNone)) {
+ const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
+ const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
+ const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
+ const bool bJump = (caretXPolicy & CARET_JUMPS) != 0;
+ const bool bEven = (caretXPolicy & CARET_EVEN) != 0;
+
+ if (bSlop) { // A margin is defined
+ int xMoveL, xMoveR;
+ if (bStrict) {
+ int xMarginL, xMarginR;
+ if (!useMargin) {
+ // In drag mode, avoid moves unless very near of the margin
+ // otherwise, a simple click will select text.
+ xMarginL = xMarginR = 2;
+ } else {
+ // xMargin must equal to caretXSlop, with a minimum of 2 and
+ // a maximum of slightly less than half the width of the text area.
+ xMarginR = Platform::Clamp(caretXSlop, 2, halfScreen);
+ if (bEven) {
+ xMarginL = xMarginR;
+ } else {
+ xMarginL = rcClient.Width() - xMarginR - 4;
+ }
+ }
+ if (bJump && bEven) {
+ // Jump is used only in even mode
+ xMoveL = xMoveR = Platform::Clamp(caretXSlop * 3, 1, halfScreen);
+ } else {
+ xMoveL = xMoveR = 0; // Not used, avoid a warning
+ }
+ if (pt.x < rcClient.left + xMarginL) {
+ // Caret is on the left of the display
+ if (bJump && bEven) {
+ newXY.xOffset -= xMoveL;
+ } else {
+ // Move just enough to allow to display the caret
+ newXY.xOffset -= (rcClient.left + xMarginL) - pt.x;
+ }
+ } else if (pt.x >= rcClient.right - xMarginR) {
+ // Caret is on the right of the display
+ if (bJump && bEven) {
+ newXY.xOffset += xMoveR;
+ } else {
+ // Move just enough to allow to display the caret
+ newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1;
+ }
+ }
+ } else { // Not strict
+ xMoveR = bJump ? caretXSlop * 3 : caretXSlop;
+ xMoveR = Platform::Clamp(xMoveR, 1, halfScreen);
+ if (bEven) {
+ xMoveL = xMoveR;
+ } else {
+ xMoveL = rcClient.Width() - xMoveR - 4;
+ }
+ if (pt.x < rcClient.left) {
+ // Caret is on the left of the display
+ newXY.xOffset -= xMoveL;
+ } else if (pt.x >= rcClient.right) {
+ // Caret is on the right of the display
+ newXY.xOffset += xMoveR;
+ }
+ }
+ } else { // No slop
+ if (bStrict ||
+ (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) {
+ // Strict or going out of display
+ if (bEven) {
+ // Center caret
+ newXY.xOffset += pt.x - rcClient.left - halfScreen;
+ } else {
+ // Put caret on right
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ } else {
+ // Move just enough to allow to display the caret
+ if (pt.x < rcClient.left) {
+ // Caret is on the left of the display
+ if (bEven) {
+ newXY.xOffset -= rcClient.left - pt.x;
+ } else {
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ } else if (pt.x >= rcClient.right) {
+ // Caret is on the right of the display
+ newXY.xOffset += pt.x - rcClient.right + 1;
+ }
+ }
+ }
+ // In case of a jump (find result) largely out of display, adjust the offset to display the caret
+ if (pt.x + xOffset < rcClient.left + newXY.xOffset) {
+ newXY.xOffset = pt.x + xOffset - rcClient.left;
+ } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) {
+ newXY.xOffset = pt.x + xOffset - rcClient.right + 1;
+ if (vs.caretStyle == CARETSTYLE_BLOCK) {
+ // Ensure we can see a good portion of the block caret
+ newXY.xOffset += vs.aveCharWidth;
+ }
+ }
+ if (newXY.xOffset < 0) {
+ newXY.xOffset = 0;
+ }
+ }
+
+ return newXY;
+}
+
+void Editor::SetXYScroll(XYScrollPosition newXY) {
+ if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) {
+ if (newXY.topLine != topLine) {
+ SetTopLine(newXY.topLine);
+ SetVerticalScrollPos();
+ }
+ if (newXY.xOffset != xOffset) {
+ xOffset = newXY.xOffset;
+ if (newXY.xOffset > 0) {
+ PRectangle rcText = GetTextRectangle();
+ if (horizontalScrollBarVisible &&
+ rcText.Width() + xOffset > scrollWidth) {
+ scrollWidth = xOffset + rcText.Width();
+ SetScrollBars();
+ }
+ }
+ SetHorizontalScrollPos();
+ }
+ Redraw();
+ UpdateSystemCaret();
+ }
+}
+
+void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
+ SetXYScroll(XYScrollToMakeVisible(useMargin, vert, horiz));
+}
+
+void Editor::ShowCaretAtCurrentPosition() {
+ if (hasFocus) {
+ caret.active = true;
+ caret.on = true;
+ SetTicking(true);
+ } else {
+ caret.active = false;
+ caret.on = false;
+ }
+ InvalidateCaret();
+}
+
+void Editor::DropCaret() {
+ caret.active = false;
+ InvalidateCaret();
+}
+
+void Editor::InvalidateCaret() {
+ if (posDrag.IsValid()) {
+ InvalidateRange(posDrag.Position(), posDrag.Position() + 1);
+ } else {
+ for (size_t r=0; r<sel.Count(); r++) {
+ InvalidateRange(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1);
+ }
+ }
+ UpdateSystemCaret();
+}
+
+void Editor::UpdateSystemCaret() {
+}
+
+void Editor::NeedWrapping(int docLineStart, int docLineEnd) {
+ docLineStart = Platform::Clamp(docLineStart, 0, pdoc->LinesTotal());
+ if (wrapStart > docLineStart) {
+ wrapStart = docLineStart;
+ llc.Invalidate(LineLayout::llPositions);
+ }
+ if (wrapEnd < docLineEnd) {
+ wrapEnd = docLineEnd;
+ }
+ wrapEnd = Platform::Clamp(wrapEnd, 0, pdoc->LinesTotal());
+ // Wrap lines during idle.
+ if ((wrapState != eWrapNone) && (wrapEnd != wrapStart)) {
+ SetIdle(true);
+ }
+}
+
+bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
+ int linesWrapped = 1;
+ if (ll) {
+ LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
+ linesWrapped = ll->lines;
+ }
+ return cs.SetHeight(lineToWrap, linesWrapped +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
+}
+
+// Check if wrapping needed and perform any needed wrapping.
+// fullwrap: if true, all lines which need wrapping will be done,
+// in this single call.
+// priorityWrapLineStart: If greater than or equal to zero, all lines starting from
+// here to 1 page + 100 lines past will be wrapped (even if there are
+// more lines under wrapping process in idle).
+// If it is neither fullwrap, nor priorityWrap, then 1 page + 100 lines will be
+// wrapped, if there are any wrapping going on in idle. (Generally this
+// condition is called only from idler).
+// Return true if wrapping occurred.
+bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
+ // If there are any pending wraps, do them during idle if possible.
+ int linesInOneCall = LinesOnScreen() + 100;
+ if (wrapState != eWrapNone) {
+ if (wrapStart < wrapEnd) {
+ if (!SetIdle(true)) {
+ // Idle processing not supported so full wrap required.
+ fullWrap = true;
+ }
+ }
+ if (!fullWrap && priorityWrapLineStart >= 0 &&
+ // .. and if the paint window is outside pending wraps
+ (((priorityWrapLineStart + linesInOneCall) < wrapStart) ||
+ (priorityWrapLineStart > wrapEnd))) {
+ // No priority wrap pending
+ return false;
+ }
+ }
+ int goodTopLine = topLine;
+ bool wrapOccurred = false;
+ if (wrapStart <= pdoc->LinesTotal()) {
+ if (wrapState == eWrapNone) {
+ if (wrapWidth != LineLayout::wrapWidthInfinite) {
+ wrapWidth = LineLayout::wrapWidthInfinite;
+ for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
+ cs.SetHeight(lineDoc, 1 +
+ (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
+ }
+ wrapOccurred = true;
+ }
+ wrapStart = wrapLineLarge;
+ wrapEnd = wrapLineLarge;
+ } else {
+ if (wrapEnd >= pdoc->LinesTotal())
+ wrapEnd = pdoc->LinesTotal();
+ //ElapsedTime et;
+ int lineDocTop = cs.DocFromDisplay(topLine);
+ int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
+ PRectangle rcTextArea = GetClientRectangle();
+ rcTextArea.left = vs.fixedColumnWidth;
+ rcTextArea.right -= vs.rightMarginWidth;
+ wrapWidth = rcTextArea.Width();
+ // Ensure all of the document is styled.
+ pdoc->EnsureStyledTo(pdoc->Length());
+ RefreshStyleData();
+ AutoSurface surface(this);
+ if (surface) {
+ bool priorityWrap = false;
+ int lastLineToWrap = wrapEnd;
+ int lineToWrap = wrapStart;
+ if (!fullWrap) {
+ if (priorityWrapLineStart >= 0) {
+ // This is a priority wrap.
+ lineToWrap = priorityWrapLineStart;
+ lastLineToWrap = priorityWrapLineStart + linesInOneCall;
+ priorityWrap = true;
+ } else {
+ // This is idle wrap.
+ lastLineToWrap = wrapStart + linesInOneCall;
+ }
+ if (lastLineToWrap >= wrapEnd)
+ lastLineToWrap = wrapEnd;
+ } // else do a fullWrap.
+
+ // Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap);
+ // Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd);
+ while (lineToWrap < lastLineToWrap) {
+ if (WrapOneLine(surface, lineToWrap)) {
+ wrapOccurred = true;
+ }
+ lineToWrap++;
+ }
+ if (!priorityWrap)
+ wrapStart = lineToWrap;
+ // If wrapping is done, bring it to resting position
+ if (wrapStart >= wrapEnd) {
+ wrapStart = wrapLineLarge;
+ wrapEnd = wrapLineLarge;
+ }
+ }
+ goodTopLine = cs.DisplayFromDoc(lineDocTop);
+ if (subLineTop < cs.GetHeight(lineDocTop))
+ goodTopLine += subLineTop;
+ else
+ goodTopLine += cs.GetHeight(lineDocTop);
+ //double durWrap = et.Duration(true);
+ //Platform::DebugPrintf("Wrap:%9.6g \n", durWrap);
+ }
+ }
+ if (wrapOccurred) {
+ SetScrollBars();
+ SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ }
+ return wrapOccurred;
+}
+
+void Editor::LinesJoin() {
+ if (!RangeContainsProtected(targetStart, targetEnd)) {
+ UndoGroup ug(pdoc);
+ bool prevNonWS = true;
+ for (int pos = targetStart; pos < targetEnd; pos++) {
+ if (IsEOLChar(pdoc->CharAt(pos))) {
+ targetEnd -= pdoc->LenChar(pos);
+ pdoc->DelChar(pos);
+ if (prevNonWS) {
+ // Ensure at least one space separating previous lines
+ pdoc->InsertChar(pos, ' ');
+ targetEnd++;
+ }
+ } else {
+ prevNonWS = pdoc->CharAt(pos) != ' ';
+ }
+ }
+ }
+}
+
+const char *Editor::StringFromEOLMode(int eolMode) {
+ if (eolMode == SC_EOL_CRLF) {
+ return "\r\n";
+ } else if (eolMode == SC_EOL_CR) {
+ return "\r";
+ } else {
+ return "\n";
+ }
+}
+
+void Editor::LinesSplit(int pixelWidth) {
+ if (!RangeContainsProtected(targetStart, targetEnd)) {
+ if (pixelWidth == 0) {
+ PRectangle rcText = GetTextRectangle();
+ pixelWidth = rcText.Width();
+ }
+ int lineStart = pdoc->LineFromPosition(targetStart);
+ int lineEnd = pdoc->LineFromPosition(targetEnd);
+ const char *eol = StringFromEOLMode(pdoc->eolMode);
+ UndoGroup ug(pdoc);
+ for (int line = lineStart; line <= lineEnd; line++) {
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, pixelWidth);
+ for (int subLine = 1; subLine < ll->lines; subLine++) {
+ pdoc->InsertCString(posLineStart + (subLine - 1) * strlen(eol) +
+ ll->LineStart(subLine), eol);
+ targetEnd += static_cast<int>(strlen(eol));
+ }
+ }
+ lineEnd = pdoc->LineFromPosition(targetEnd);
+ }
+ }
+}
+
+int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) {
+ if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
+ return markerDefault;
+ return markerCheck;
+}
+
+// Avoid 64 bit compiler warnings.
+// Scintilla does not support text buffers larger than 2**31
+static int istrlen(const char *s) {
+ return static_cast<int>(strlen(s));
+}
+
+bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) {
+ if (st.multipleStyles) {
+ for (size_t iStyle=0; iStyle<st.length; iStyle++) {
+ if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
+ return false;
+ }
+ } else {
+ if (!vs.ValidStyle(styleOffset + st.style))
+ return false;
+ }
+ return true;
+}
+
+static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset,
+ const char *text, const unsigned char *styles, size_t len) {
+ int width = 0;
+ size_t start = 0;
+ while (start < len) {
+ size_t style = styles[start];
+ size_t endSegment = start;
+ while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style))
+ endSegment++;
+ width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, endSegment - start + 1);
+ start = endSegment + 1;
+ }
+ return width;
+}
+
+static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, const StyledText &st) {
+ int widthMax = 0;
+ size_t start = 0;
+ while (start < st.length) {
+ size_t lenLine = st.LineLength(start);
+ int widthSubLine;
+ if (st.multipleStyles) {
+ widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
+ } else {
+ widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, st.text + start, lenLine);
+ }
+ if (widthSubLine > widthMax)
+ widthMax = widthSubLine;
+ start += lenLine + 1;
+ }
+ return widthMax;
+}
+
+void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,
+ const StyledText &st, size_t start, size_t length) {
+
+ if (st.multipleStyles) {
+ int x = rcText.left;
+ size_t i = 0;
+ while (i < length) {
+ size_t end = i;
+ int style = st.styles[i + start];
+ while (end < length-1 && st.styles[start+end+1] == style)
+ end++;
+ style += styleOffset;
+ int width = surface->WidthText(vs.styles[style].font, st.text + start + i, end - i + 1);
+ PRectangle rcSegment = rcText;
+ rcSegment.left = x;
+ rcSegment.right = x + width + 1;
+ surface->DrawTextNoClip(rcSegment, vs.styles[style].font,
+ ascent, st.text + start + i, end - i + 1,
+ vs.styles[style].fore.allocated,
+ vs.styles[style].back.allocated);
+ x += width;
+ i = end + 1;
+ }
+ } else {
+ int style = st.style + styleOffset;
+ surface->DrawTextNoClip(rcText, vs.styles[style].font,
+ rcText.top + vs.maxAscent, st.text + start, length,
+ vs.styles[style].fore.allocated,
+ vs.styles[style].back.allocated);
+ }
+}
+
+void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
+ if (vs.fixedColumnWidth == 0)
+ return;
+
+ PRectangle rcMargin = GetClientRectangle();
+ rcMargin.right = vs.fixedColumnWidth;
+
+ if (!rc.Intersects(rcMargin))
+ return;
+
+ Surface *surface;
+ if (bufferedDraw) {
+ surface = pixmapSelMargin;
+ } else {
+ surface = surfWindow;
+ }
+
+ PRectangle rcSelMargin = rcMargin;
+ rcSelMargin.right = rcMargin.left;
+
+ for (int margin = 0; margin < vs.margins; margin++) {
+ if (vs.ms[margin].width > 0) {
+
+ rcSelMargin.left = rcSelMargin.right;
+ rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+ if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
+ /* alternate scheme:
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+ else
+ // Required because of special way brush is created for selection margin
+ surface->FillRectangle(rcSelMargin, pixmapSelPattern);
+ */
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+ // Required because of special way brush is created for selection margin
+ surface->FillRectangle(rcSelMargin, *pixmapSelPattern);
+ else {
+ ColourAllocated colour;
+ switch (vs.ms[margin].style) {
+ case SC_MARGIN_BACK:
+ colour = vs.styles[STYLE_DEFAULT].back.allocated;
+ break;
+ case SC_MARGIN_FORE:
+ colour = vs.styles[STYLE_DEFAULT].fore.allocated;
+ break;
+ default:
+ colour = vs.styles[STYLE_LINENUMBER].back.allocated;
+ break;
+ }
+ surface->FillRectangle(rcSelMargin, colour);
+ }
+ } else {
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated);
+ }
+
+ int visibleLine = topLine;
+ int yposScreen = 0;
+
+ // Work out whether the top line is whitespace located after a
+ // lessening of fold level which implies a 'fold tail' but which should not
+ // be displayed until the last of a sequence of whitespace.
+ bool needWhiteClosure = false;
+ int level = pdoc->GetLevel(cs.DocFromDisplay(topLine));
+ if (level & SC_FOLDLEVELWHITEFLAG) {
+ int lineBack = cs.DocFromDisplay(topLine);
+ int levelPrev = level;
+ while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
+ lineBack--;
+ levelPrev = pdoc->GetLevel(lineBack);
+ }
+ if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
+ if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
+ needWhiteClosure = true;
+ }
+ }
+
+ // Old code does not know about new markers needed to distinguish all cases
+ int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
+ SC_MARKNUM_FOLDEROPEN);
+ int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
+ SC_MARKNUM_FOLDER);
+
+ while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) {
+
+ PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
+
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ PLATFORM_ASSERT(cs.GetVisible(lineDoc));
+ bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc);
+
+ // Decide which fold indicator should be displayed
+ level = pdoc->GetLevel(lineDoc);
+ int levelNext = pdoc->GetLevel(lineDoc + 1);
+ int marks = pdoc->GetMark(lineDoc);
+ if (!firstSubLine)
+ marks = 0;
+ int levelNum = level & SC_FOLDLEVELNUMBERMASK;
+ int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (firstSubLine) {
+ if (cs.GetExpanded(lineDoc)) {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+ else
+ marks |= 1 << folderOpenMid;
+ } else {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDER;
+ else
+ marks |= 1 << folderEnd;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ needWhiteClosure = false;
+ } else if (level & SC_FOLDLEVELWHITEFLAG) {
+ if (needWhiteClosure) {
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ needWhiteClosure = false;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ needWhiteClosure = false;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ needWhiteClosure = false;
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ needWhiteClosure = true;
+ } else if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+
+ marks &= vs.ms[margin].mask;
+ PRectangle rcMarker = rcSelMargin;
+ rcMarker.top = yposScreen;
+ rcMarker.bottom = yposScreen + vs.lineHeight;
+ if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
+ char number[100];
+ number[0] = '\0';
+ if (firstSubLine)
+ sprintf(number, "%d", lineDoc + 1);
+ if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
+ int lev = pdoc->GetLevel(lineDoc);
+ sprintf(number, "%c%c %03X %03X",
+ (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
+ (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
+ lev & SC_FOLDLEVELNUMBERMASK,
+ lev >> 16
+ );
+ }
+ PRectangle rcNumber = rcMarker;
+ // Right justify
+ int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number));
+ int xpos = rcNumber.right - width - 3;
+ rcNumber.left = xpos;
+ surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font,
+ rcNumber.top + vs.maxAscent, number, istrlen(number),
+ vs.styles[STYLE_LINENUMBER].fore.allocated,
+ vs.styles[STYLE_LINENUMBER].back.allocated);
+ } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ if (firstSubLine) {
+ const StyledText stMargin = pdoc->MarginStyledText(lineDoc);
+ if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ surface->FillRectangle(rcMarker,
+ vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back.allocated);
+ if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
+ rcMarker.left = rcMarker.right - width - 3;
+ }
+ DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,
+ stMargin, 0, stMargin.length);
+ }
+ }
+ }
+
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font);
+ }
+ marks >>= 1;
+ }
+ }
+
+ visibleLine++;
+ yposScreen += vs.lineHeight;
+ }
+ }
+ }
+
+ PRectangle rcBlankMargin = rcMargin;
+ rcBlankMargin.left = rcSelMargin.right;
+ surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+
+ if (bufferedDraw) {
+ surfWindow->Copy(rcMargin, Point(), *pixmapSelMargin);
+ }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+ int ydiff = (rcTab.bottom - rcTab.top) / 2;
+ int xhead = rcTab.right - 1 - ydiff;
+ if (xhead <= rcTab.left) {
+ ydiff -= rcTab.left - xhead - 1;
+ xhead = rcTab.left - 1;
+ }
+ if ((rcTab.left + 2) < (rcTab.right - 1))
+ surface->MoveTo(rcTab.left + 2, ymid);
+ else
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(rcTab.right - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+}
+
+LineLayout *Editor::RetrieveLineLayout(int lineNumber) {
+ int posLineStart = pdoc->LineStart(lineNumber);
+ int posLineEnd = pdoc->LineStart(lineNumber + 1);
+ PLATFORM_ASSERT(posLineEnd >= posLineStart);
+ int lineCaret = pdoc->LineFromPosition(sel.MainCaret());
+ return llc.Retrieve(lineNumber, lineCaret,
+ posLineEnd - posLineStart, pdoc->GetStyleClock(),
+ LinesOnScreen() + 1, pdoc->LinesTotal());
+}
+
+static bool GoodTrailByte(int v) {
+ return (v >= 0x80) && (v < 0xc0);
+}
+
+bool BadUTF(const char *s, int len, int &trailBytes) {
+ // For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ if (trailBytes) {
+ trailBytes--;
+ return false;
+ }
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ if (*us < 0x80) {
+ // Single bytes easy
+ return false;
+ } else if (*us > 0xF4) {
+ // Characters longer than 4 bytes not possible in current UTF-8
+ return true;
+ } else if (*us >= 0xF0) {
+ // 4 bytes
+ if (len < 4)
+ return true;
+ if (GoodTrailByte(us[1]) && GoodTrailByte(us[2]) && GoodTrailByte(us[3])) {
+ if (*us == 0xf4) {
+ // Check if encoding a value beyond the last Unicode character 10FFFF
+ if (us[1] > 0x8f) {
+ return true;
+ } else if (us[1] == 0x8f) {
+ if (us[2] > 0xbf) {
+ return true;
+ } else if (us[2] == 0xbf) {
+ if (us[3] > 0xbf) {
+ return true;
+ }
+ }
+ }
+ } else if ((*us == 0xf0) && ((us[1] & 0xf0) == 0x80)) {
+ // Overlong
+ return true;
+ }
+ trailBytes = 3;
+ return false;
+ } else {
+ return true;
+ }
+ } else if (*us >= 0xE0) {
+ // 3 bytes
+ if (len < 3)
+ return true;
+ if (GoodTrailByte(us[1]) && GoodTrailByte(us[2])) {
+ if ((*us == 0xe0) && ((us[1] & 0xe0) == 0x80)) {
+ // Overlong
+ return true;
+ }
+ if ((*us == 0xed) && ((us[1] & 0xe0) == 0xa0)) {
+ // Surrogate
+ return true;
+ }
+ if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbe)) {
+ // U+FFFE
+ return true;
+ }
+ if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbf)) {
+ // U+FFFF
+ return true;
+ }
+ trailBytes = 2;
+ return false;
+ } else {
+ return true;
+ }
+ } else if (*us >= 0xC2) {
+ // 2 bytes
+ if (len < 2)
+ return true;
+ if (GoodTrailByte(us[1])) {
+ trailBytes = 1;
+ return false;
+ } else {
+ return true;
+ }
+ } else if (*us >= 0xC0) {
+ // Overlong encoding
+ return true;
+ } else {
+ // Trail byte
+ return true;
+ }
+}
+
+/**
+ * Fill in the LineLayout data for the given line.
+ * Copy the given @a line and its styles from the document into local arrays.
+ * Also determine the x position at which each character starts.
+ */
+void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) {
+ if (!ll)
+ return;
+
+ PLATFORM_ASSERT(line < pdoc->LinesTotal());
+ PLATFORM_ASSERT(ll->chars != NULL);
+ int posLineStart = pdoc->LineStart(line);
+ int posLineEnd = pdoc->LineStart(line + 1);
+ // If the line is very long, limit the treatment to a length that should fit in the viewport
+ if (posLineEnd > (posLineStart + ll->maxLineLength)) {
+ posLineEnd = posLineStart + ll->maxLineLength;
+ }
+ if (ll->validity == LineLayout::llCheckTextAndStyle) {
+ int lineLength = posLineEnd - posLineStart;
+ if (!vstyle.viewEOL) {
+ int cid = posLineEnd - 1;
+ while ((cid > posLineStart) && IsEOLChar(pdoc->CharAt(cid))) {
+ cid--;
+ lineLength--;
+ }
+ }
+ if (lineLength == ll->numCharsInLine) {
+ // See if chars, styles, indicators, are all the same
+ bool allSame = true;
+ const int styleMask = pdoc->stylingBitsMask;
+ // Check base line layout
+ char styleByte = 0;
+ int numCharsInLine = 0;
+ while (numCharsInLine < lineLength) {
+ int charInDoc = numCharsInLine + posLineStart;
+ char chDoc = pdoc->CharAt(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->chars[numCharsInLine] == chDoc);
+ else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
+ allSame = allSame &&
+ (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 {
+ ll->validity = LineLayout::llInvalid;
+ }
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ }
+ if (ll->validity == LineLayout::llInvalid) {
+ ll->widthLine = LineLayout::wrapWidthInfinite;
+ ll->lines = 1;
+ int numCharsInLine = 0;
+ int numCharsBeforeEOL = 0;
+ if (vstyle.edgeState == EDGE_BACKGROUND) {
+ ll->edgeColumn = pdoc->FindColumn(line, theEdge);
+ if (ll->edgeColumn >= posLineStart) {
+ ll->edgeColumn -= posLineStart;
+ }
+ } else {
+ ll->edgeColumn = -1;
+ }
+
+ 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);
+ ll->indicators[numCharsInLine] = static_cast<char>(styleByte & ~styleMask);
+ if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper)
+ ll->chars[numCharsInLine] = static_cast<char>(toupper(chDoc));
+ else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
+ ll->chars[numCharsInLine] = static_cast<char>(tolower(chDoc));
+ numCharsInLine++;
+ if (!IsEOLChar(chDoc))
+ numCharsBeforeEOL++;
+ }
+ }
+ ll->xHighlightGuide = 0;
+ // Extra element at the end of the line to hold end x position and act as
+ ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character
+ ll->styles[numCharsInLine] = styleByte; // For eolFilled
+ ll->indicators[numCharsInLine] = 0;
+
+ // Layout the line, determining the position of each character,
+ // with an extra element at the end for the end of the line.
+ int startseg = 0; // Start of the current segment, in char. number
+ int startsegx = 0; // Start of the current segment, in pixels
+ ll->positions[0] = 0;
+ unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
+ bool lastSegItalics = false;
+ Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
+
+ int ctrlCharWidth[32] = {0};
+ bool isControlNext = IsControlCharacter(ll->chars[0]);
+ int trailBytes = 0;
+ bool isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars, numCharsInLine, trailBytes);
+ for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
+ bool isControl = isControlNext;
+ isControlNext = IsControlCharacter(ll->chars[charInLine + 1]);
+ bool isBadUTF = isBadUTFNext;
+ isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
+ if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
+ isControl || isControlNext || isBadUTF || isBadUTFNext) {
+ ll->positions[startseg] = 0;
+ if (vstyle.styles[ll->styles[charInLine]].visible) {
+ if (isControl) {
+ if (ll->chars[charInLine] == '\t') {
+ ll->positions[charInLine + 1] = ((((startsegx + 2) /
+ tabWidth) + 1) * tabWidth) - startsegx;
+ } else if (controlCharSymbol < 32) {
+ 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,
+ ll->positions + startseg + 1);
+ }
+ lastSegItalics = false;
+ } else if (isBadUTF) {
+ char hexits[4];
+ sprintf(hexits, "x%2X", ll->chars[charInLine] & 0xff);
+ ll->positions[charInLine + 1] =
+ surface->WidthText(ctrlCharsFont, hexits, istrlen(hexits)) + 3;
+ } else { // Regular character
+ int lenSeg = charInLine - startseg + 1;
+ if ((lenSeg == 1) && (' ' == ll->chars[startseg])) {
+ lastSegItalics = false;
+ // Over half the segments are single characters and of these about half are space characters.
+ ll->positions[charInLine + 1] = vstyle.styles[ll->styles[charInLine]].spaceWidth;
+ } else {
+ lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic;
+ posCache.MeasureWidths(surface, vstyle, ll->styles[charInLine], ll->chars + startseg,
+ lenSeg, ll->positions + startseg + 1);
+ }
+ }
+ } else { // invisible
+ for (int posToZero = startseg; posToZero <= (charInLine + 1); posToZero++) {
+ ll->positions[posToZero] = 0;
+ }
+ }
+ for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) {
+ ll->positions[posToIncrease] += startsegx;
+ }
+ startsegx = ll->positions[charInLine + 1];
+ startseg = charInLine + 1;
+ }
+ }
+ // Small hack to make lines that end with italics not cut off the edge of the last character
+ if ((startseg > 0) && lastSegItalics) {
+ ll->positions[startseg] += 2;
+ }
+ ll->numCharsInLine = numCharsInLine;
+ ll->numCharsBeforeEOL = numCharsBeforeEOL;
+ ll->validity = LineLayout::llPositions;
+ }
+ // Hard to cope when too narrow, so just assume there is space
+ if (width < 20) {
+ width = 20;
+ }
+ if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
+ ll->widthLine = width;
+ if (width == LineLayout::wrapWidthInfinite) {
+ ll->lines = 1;
+ } else if (width > ll->positions[ll->numCharsInLine]) {
+ // Simple common case where line does not need wrapping.
+ ll->lines = 1;
+ } else {
+ if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ width -= vstyle.aveCharWidth; // take into account the space for end wrap mark
+ }
+ ll->wrapIndent = wrapAddIndent;
+ if (wrapIndentMode != SC_WRAPINDENT_FIXED)
+ for (int i = 0; i < ll->numCharsInLine; i++) {
+ if (!IsSpaceOrTab(ll->chars[i])) {
+ ll->wrapIndent += ll->positions[i]; // Add line indent
+ break;
+ }
+ }
+ // Check for text width minimum
+ if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
+ ll->wrapIndent = wrapAddIndent;
+ // Check for wrapIndent minimum
+ if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < static_cast<int>(vstyle.aveCharWidth)))
+ ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
+ ll->lines = 0;
+ // Calculate line start positions based upon width.
+ int lastGoodBreak = 0;
+ int lastLineStart = 0;
+ int startOffset = 0;
+ int p = 0;
+ while (p < ll->numCharsInLine) {
+ if ((ll->positions[p + 1] - startOffset) >= width) {
+ if (lastGoodBreak == lastLineStart) {
+ // Try moving to start of last character
+ if (p > 0) {
+ lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ }
+ if (lastGoodBreak == lastLineStart) {
+ // Ensure at least one character on line.
+ lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
+ - posLineStart;
+ }
+ }
+ lastLineStart = lastGoodBreak;
+ ll->lines++;
+ ll->SetLineStart(ll->lines, lastGoodBreak);
+ startOffset = ll->positions[lastGoodBreak];
+ // take into account the space for start wrap mark and indent
+ startOffset -= ll->wrapIndent;
+ p = lastGoodBreak + 1;
+ continue;
+ }
+ if (p > 0) {
+ 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;
+ }
+ }
+ p++;
+ }
+ ll->lines++;
+ }
+ ll->validity = LineLayout::llLines;
+ }
+}
+
+ColourAllocated Editor::SelectionBackground(ViewStyle &vsDraw, bool main) {
+ return main ?
+ (primarySelection ? vsDraw.selbackground.allocated : vsDraw.selbackground2.allocated) :
+ vsDraw.selAdditionalBackground.allocated;
+}
+
+ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground,
+ ColourAllocated background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) {
+ if (inSelection == 1) {
+ if (vsDraw.selbackset && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, true);
+ }
+ } else if (inSelection == 2) {
+ if (vsDraw.selbackset && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, false);
+ }
+ } else {
+ if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
+ (i >= ll->edgeColumn) &&
+ !IsEOLChar(ll->chars[i]))
+ return vsDraw.edgecolour.allocated;
+ if (inHotspot && vsDraw.hotspotBackgroundSet)
+ return vsDraw.hotspotBackground.allocated;
+ if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD))
+ return background;
+ }
+ return vsDraw.styles[styleMain].back.allocated;
+}
+
+void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
+ Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
+ PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom);
+ surface->Copy(rcCopyArea, from,
+ highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
+}
+
+void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace,
+ bool isEndMarker, ColourAllocated wrapColour) {
+ surface->PenColour(wrapColour);
+
+ enum { xa = 1 }; // gap before start
+ int w = rcPlace.right - rcPlace.left - xa - 1;
+
+ bool xStraight = isEndMarker; // x-mirrored symbol for start marker
+ bool yStraight = true;
+ //bool yStraight= isEndMarker; // comment in for start marker y-mirrowed
+
+ int x0 = xStraight ? rcPlace.left : rcPlace.right - 1;
+ int y0 = yStraight ? rcPlace.top : rcPlace.bottom - 1;
+
+ int dy = (rcPlace.bottom - rcPlace.top) / 5;
+ int y = (rcPlace.bottom - rcPlace.top) / 2 + dy;
+
+ struct Relative {
+ Surface *surface;
+ int xBase;
+ int xDir;
+ int yBase;
+ int yDir;
+ void MoveTo(int xRelative, int yRelative) {
+ surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ void LineTo(int xRelative, int yRelative) {
+ surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ };
+ Relative rel = {surface, x0, xStraight ? 1 : -1, y0, yStraight ? 1 : -1};
+
+ // arrow head
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2*w / 3, y - dy);
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2*w / 3, y + dy);
+
+ // arrow body
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + w, y);
+ rel.LineTo(xa + w, y - 2 * dy);
+ rel.LineTo(xa - 1, // on windows lineto is exclusive endpoint, perhaps GTK not...
+ y - 2 * dy);
+}
+
+static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourAllocated fill, int alpha) {
+ if (alpha != SC_ALPHA_NOALPHA) {
+ surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
+ }
+}
+
+void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
+ const char *s, ColourAllocated textBack, ColourAllocated textFore, bool twoPhaseDraw) {
+ if (!twoPhaseDraw) {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+ int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+ surface->InternalLeading(ctrlCharsFont);
+ PRectangle rcCChar = rcSegment;
+ rcCChar.left = rcCChar.left + 1;
+ rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+ rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+ PRectangle rcCentral = rcCChar;
+ rcCentral.top++;
+ rcCentral.bottom--;
+ surface->FillRectangle(rcCentral, textFore);
+ PRectangle rcChar = rcCChar;
+ rcChar.left++;
+ rcChar.right--;
+ surface->DrawTextClipped(rcChar, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
+ textBack, textFore);
+}
+
+void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
+ int line, int lineEnd, int xStart, int subLine, int subLineStart,
+ bool overrideBackground, ColourAllocated background,
+ bool drawWrapMarkEnd, ColourAllocated wrapColour) {
+
+ const int posLineStart = pdoc->LineStart(line);
+ const int styleMask = pdoc->stylingBitsMask;
+ PRectangle rcSegment = rcLine;
+
+ const bool lastSubLine = subLine == (ll->lines - 1);
+ int virtualSpace = 0;
+ if (lastSubLine) {
+ const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth);
+ virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth;
+ }
+
+ // Fill in a PRectangle representing the end of line characters
+
+ int xEol = ll->positions[lineEnd] - subLineStart;
+
+ // Fill the virtual space and show selections within it
+ if (virtualSpace) {
+ rcSegment.left = xEol + xStart;
+ rcSegment.right = xEol + xStart + virtualSpace;
+ surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated);
+ if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
+ SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line))));
+ for (size_t r=0; r<sel.Count(); r++) {
+ int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha == SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth);
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
+ rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left);
+ rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right);
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == sel.Main()));
+ }
+ }
+ }
+ }
+ }
+
+ int posAfterLineEnd = pdoc->LineStart(line + 1);
+ int eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ int alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+
+ // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
+ int blobsWidth = 0;
+ if (lastSubLine) {
+ for (int eolPos=ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
+ rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
+ rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
+ blobsWidth += rcSegment.Width();
+ const char *ctrlChar = ControlCharacterString(ll->chars[eolPos]);
+ int inSelection = 0;
+ bool inHotspot = false;
+ int styleMain = ll->styles[eolPos];
+ ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, eolPos, ll);
+ ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated;
+ if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) {
+ if (alpha == SC_ALPHA_NOALPHA) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
+ }
+ }
+
+ // Draw the eol-is-selected rectangle
+ rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
+ rcSegment.right = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth;
+
+ if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ if (overrideBackground) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (line < pdoc->LinesTotal() - 1) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);
+ }
+ if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ }
+
+ // Fill the remainder of the line
+ rcSegment.left = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth;
+ rcSegment.right = rcLine.right;
+
+ if (!hideSelection && vsDraw.selEOLFilled && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
+ } else {
+ if (overrideBackground) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);
+ }
+ if (!hideSelection && vsDraw.selEOLFilled && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
+ }
+ }
+
+ if (drawWrapMarkEnd) {
+ PRectangle rcPlace = rcSegment;
+
+ if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
+ rcPlace.left = xEol + xStart + virtualSpace;
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+ } else {
+ // draw left of the right text margin, to avoid clipping by the current clip rect
+ rcPlace.right = rcLine.right - vs.rightMarginWidth;
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ }
+ DrawWrapMarker(surface, rcPlace, true, wrapColour);
+ }
+}
+
+void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
+ // Draw decorators
+ const int posLineStart = pdoc->LineStart(line);
+ const int lineStart = ll->LineStart(subLine);
+ const int subLineStart = ll->positions[lineStart];
+ const int posLineEnd = posLineStart + lineEnd;
+
+ if (!under) {
+ // Draw indicators
+ // 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(
+ ll->positions[startPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll->positions[indicPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine);
+ // RESET control var
+ startPos = -1;
+ }
+ }
+ }
+ mask <<= 1;
+ }
+ }
+
+ for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) {
+ if (under == vsDraw.indicators[deco->indicator].under) {
+ int startPos = posLineStart + lineStart;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
+ int endPos = deco->rs.EndRun(startPos);
+ if (endPos > posLineEnd)
+ endPos = posLineEnd;
+ PRectangle rcIndic(
+ ll->positions[startPos - posLineStart] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll->positions[endPos - posLineStart] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[deco->indicator].Draw(surface, rcIndic, rcLine);
+ startPos = deco->rs.EndRun(endPos);
+ }
+ }
+ }
+}
+
+void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+ int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth;
+ PRectangle rcSegment = rcLine;
+ int annotationLine = subLine - ll->lines;
+ const StyledText stAnnotation = pdoc->AnnotationStyledText(line);
+ if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[0].back.allocated);
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ // Only care about calculating width if need to draw box
+ int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
+ widthAnnotation += vsDraw.spaceWidth * 2; // Margins
+ rcSegment.left = xStart + indent;
+ rcSegment.right = rcSegment.left + widthAnnotation;
+ surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated);
+ } else {
+ rcSegment.left = xStart;
+ }
+ const int annotationLines = pdoc->AnnotationLines(line);
+ size_t start = 0;
+ size_t lengthAnnotation = stAnnotation.LineLength(start);
+ int lineInAnnotation = 0;
+ while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
+ start += lengthAnnotation + 1;
+ lengthAnnotation = stAnnotation.LineLength(start);
+ lineInAnnotation++;
+ }
+ PRectangle rcText = rcSegment;
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ surface->FillRectangle(rcText,
+ vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back.allocated);
+ rcText.left += vsDraw.spaceWidth;
+ }
+ DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,
+ stAnnotation, start, lengthAnnotation);
+ if (vs.annotationVisible == ANNOTATION_BOXED) {
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.left, rcSegment.bottom);
+ surface->MoveTo(rcSegment.right, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.bottom);
+ if (subLine == ll->lines) {
+ surface->MoveTo(rcSegment.left, rcSegment.top);
+ surface->LineTo(rcSegment.right, rcSegment.top);
+ }
+ if (subLine == ll->lines+annotationLines-1) {
+ surface->MoveTo(rcSegment.left, rcSegment.bottom - 1);
+ surface->LineTo(rcSegment.right, rcSegment.bottom - 1);
+ }
+ }
+ }
+}
+
+void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+
+ PRectangle rcSegment = rcLine;
+
+ // Using one font for all control characters so it can be controlled independently to ensure
+ // the box goes around the characters tightly. Seems to be no way to work out what height
+ // is taken by an individual character - internal leading gives varying results.
+ Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+ // See if something overrides the line background color: Either if caret is on the line
+ // and background color is set for that, or if a marker is defined that forces its background
+ // color onto the line, or if a marker is defined but has no selection margin in which to
+ // display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order
+ // with the earlier taking precedence. When multiple markers cause background override,
+ // the color for the highest numbered one is used.
+ bool overrideBackground = false;
+ ColourAllocated background;
+ if (caret.active && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
+ overrideBackground = true;
+ background = vsDraw.caretLineBackground.allocated;
+ }
+ if (!overrideBackground) {
+ int marks = pdoc->GetMark(line);
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ background = vsDraw.markers[markBit].back.allocated;
+ overrideBackground = true;
+ }
+ marks >>= 1;
+ }
+ }
+ if (!overrideBackground) {
+ if (vsDraw.maskInLine) {
+ int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marksMasked) {
+ for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
+ if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ overrideBackground = true;
+ background = vsDraw.markers[markBit].back.allocated;
+ }
+ marksMasked >>= 1;
+ }
+ }
+ }
+ }
+
+ bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
+ (!overrideBackground) && (vsDraw.whitespaceBackgroundSet);
+
+ bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ int indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;
+
+ int posLineStart = pdoc->LineStart(line);
+
+ int startseg = ll->LineStart(subLine);
+ int subLineStart = ll->positions[startseg];
+ if (subLine >= ll->lines) {
+ DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine);
+ return; // No further drawing
+ }
+ int lineStart = 0;
+ int lineEnd = 0;
+ if (subLine < ll->lines) {
+ lineStart = ll->LineStart(subLine);
+ lineEnd = ll->LineStart(subLine + 1);
+ if (subLine == ll->lines - 1) {
+ lineEnd = ll->numCharsBeforeEOL;
+ }
+ }
+
+ ColourAllocated wrapColour = vsDraw.styles[STYLE_DEFAULT].fore.allocated;
+ if (vsDraw.whitespaceForegroundSet)
+ wrapColour = vsDraw.whitespaceForeground.allocated;
+
+ bool drawWrapMarkEnd = false;
+
+ if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ if (subLine + 1 < ll->lines) {
+ drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
+ }
+ }
+
+ if (ll->wrapIndent != 0) {
+
+ bool continuedWrapLine = false;
+ if (subLine < ll->lines) {
+ continuedWrapLine = ll->LineStart(subLine) != 0;
+ }
+
+ if (continuedWrapLine) {
+ // draw continuation rect
+ PRectangle rcPlace = rcSegment;
+
+ rcPlace.left = ll->positions[startseg] + xStart - subLineStart;
+ rcPlace.right = rcPlace.left + ll->wrapIndent;
+
+ // default bgnd here..
+ surface->FillRectangle(rcSegment, overrideBackground ? background :
+ vsDraw.styles[STYLE_DEFAULT].back.allocated);
+
+ // main line style would be below but this would be inconsistent with end markers
+ // also would possibly not be the style at wrap point
+ //int styleMain = ll->styles[lineStart];
+ //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back.allocated);
+
+ if (wrapVisualFlags & SC_WRAPVISUALFLAG_START) {
+
+ if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT)
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ else
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+
+ DrawWrapMarker(surface, rcPlace, false, wrapColour);
+ }
+
+ xStart += ll->wrapIndent;
+ }
+ }
+
+ bool selBackDrawn = vsDraw.selbackset &&
+ ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA));
+
+ // Does not take margin into account but not significant
+ int xStartVisible = subLineStart - xStart;
+
+ ll->psel = &sel;
+
+ BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible, selBackDrawn);
+ int next = bfBack.First();
+
+ // Background drawing loop
+ while (twoPhaseDraw && (next < lineEnd)) {
+
+ startseg = next;
+ next = bfBack.Next();
+ int i = next - 1;
+ int iDoc = i + posLineStart;
+
+ rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
+ rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
+ // Clip to line rectangle, since may have a huge position which will not work with some platforms
+ rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left);
+ rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right);
+
+ int styleMain = ll->styles[i];
+ const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
+ bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
+ ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceBackground.allocated;
+ surface->FillRectangle(rcSegment, textBack);
+ } else if (IsControlCharacter(ll->chars[i])) {
+ // Control character display
+ inIndentation = false;
+ surface->FillRectangle(rcSegment, textBack);
+ } else {
+ // Normal text display
+ surface->FillRectangle(rcSegment, textBack);
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
+ for (int cpos = 0; cpos <= i - startseg; cpos++) {
+ if (ll->chars[cpos + startseg] == ' ') {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
+ rcSegment.top,
+ ll->positions[cpos + startseg + 1] + xStart - subLineStart,
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated);
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+
+ if (twoPhaseDraw) {
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
+ xStart, subLine, subLineStart, overrideBackground, background,
+ drawWrapMarkEnd, wrapColour);
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true);
+
+ if (vsDraw.edgeState == EDGE_LINE) {
+ int edgeX = theEdge * vsDraw.spaceWidth;
+ rcSegment.left = edgeX + xStart;
+ rcSegment.right = rcSegment.left + 1;
+ surface->FillRectangle(rcSegment, vsDraw.edgecolour.allocated);
+ }
+
+ // Draw underline mark as part of background if not transparent
+ int marks = pdoc->GetMark(line);
+ int markBit;
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ PRectangle rcUnderline = rcLine;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back.allocated);
+ }
+ marks >>= 1;
+ }
+
+ inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ // Foreground drawing loop
+ BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible,
+ ((!twoPhaseDraw && selBackDrawn) || vsDraw.selforeset));
+ next = bfFore.First();
+
+ while (next < lineEnd) {
+
+ startseg = next;
+ next = bfFore.Next();
+ int i = next - 1;
+
+ int iDoc = i + posLineStart;
+
+ rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
+ rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
+ int styleMain = ll->styles[i];
+ ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated;
+ Font &textFont = vsDraw.styles[styleMain].font;
+ //hotspot foreground
+ if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
+ if (vsDraw.hotspotForegroundSet)
+ textFore = vsDraw.hotspotForeground.allocated;
+ }
+ const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
+ if (inSelection && (vsDraw.selforeset)) {
+ textFore = (inSelection == 1) ? vsDraw.selforeground.allocated : vsDraw.selAdditionalForeground.allocated;
+ }
+ bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
+ ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (!twoPhaseDraw) {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceBackground.allocated;
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ if ((vsDraw.viewWhitespace != wsInvisible) ||
+ (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
+ if (vsDraw.whitespaceForegroundSet)
+ textFore = vsDraw.whitespaceForeground.allocated;
+ surface->PenColour(textFore);
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {
+ if (xIG >= ll->positions[i] && xIG > 0) {
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment,
+ (ll->xHighlightGuide == xIG));
+ }
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+ rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+ DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
+ }
+ }
+ } else if (IsControlCharacter(ll->chars[i])) {
+ // Control character display
+ inIndentation = false;
+ if (controlCharSymbol < 32) {
+ // Draw the character
+ const char *ctrlChar = ControlCharacterString(ll->chars[i]);
+ DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
+ } else {
+ char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
+ surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent,
+ cc, 1, textBack, textFore);
+ }
+ } else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) {
+ // A single byte >= 0x80 in UTF-8 is a bad byte and is displayed as its hex value
+ char hexits[4];
+ sprintf(hexits, "x%2X", ll->chars[i] & 0xff);
+ DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw);
+ } else {
+ // Normal text display
+ if (vsDraw.styles[styleMain].visible) {
+ if (twoPhaseDraw) {
+ surface->DrawTextTransparent(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+ i - startseg + 1, textFore);
+ } else {
+ surface->DrawTextNoClip(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+ i - startseg + 1, textFore, textBack);
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
+ for (int cpos = 0; cpos <= i - startseg; cpos++) {
+ if (ll->chars[cpos + startseg] == ' ') {
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (vsDraw.whitespaceForegroundSet)
+ textFore = vsDraw.whitespaceForeground.allocated;
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
+ if (!twoPhaseDraw && drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ textBack = vsDraw.whitespaceBackground.allocated;
+ PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
+ rcSegment.top,
+ ll->positions[cpos + startseg + 1] + xStart - subLineStart,
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, textBack);
+ }
+ PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+ rcDot.right = rcDot.left + vs.whitespaceSize;
+ rcDot.bottom = rcDot.top + vs.whitespaceSize;
+ surface->FillRectangle(rcDot, textFore);
+ }
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ int startSpace = ll->positions[cpos + startseg];
+ if (startSpace > 0 && (startSpace % indentWidth == 0)) {
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment,
+ (ll->xHighlightGuide == ll->positions[cpos + startseg]));
+ }
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ if (vsDraw.hotspotForegroundSet)
+ surface->FillRectangle(rcUL, vsDraw.hotspotForeground.allocated);
+ else
+ surface->FillRectangle(rcUL, textFore);
+ } else if (vsDraw.styles[styleMain].underline) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ surface->FillRectangle(rcUL, textFore);
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+ if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
+ && (subLine == 0)) {
+ int indentSpace = pdoc->GetLineIndentation(line);
+ int xStartText = ll->positions[pdoc->GetLineIndentPosition(line) - posLineStart];
+
+ // Find the most recent line with some text
+
+ int lineLastWithText = line;
+ while (lineLastWithText > Platform::Maximum(line-20, 0) && pdoc->IsWhiteLine(lineLastWithText)) {
+ lineLastWithText--;
+ }
+ if (lineLastWithText < line) {
+ xStartText = 100000; // Don't limit to visible indentation on empty line
+ // This line is empty, so use indentation of last line with text
+ int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
+ int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
+ if (isFoldHeader) {
+ // Level is one more level than parent
+ indentLastWithText += pdoc->IndentSize();
+ }
+ if (vsDraw.viewIndentationGuides == ivLookForward) {
+ // In viLookForward mode, previous line only used if it is a fold header
+ if (isFoldHeader) {
+ indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+ }
+ } else { // viLookBoth
+ indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+ }
+ }
+
+ int lineNextWithText = line;
+ while (lineNextWithText < Platform::Minimum(line+20, pdoc->LinesTotal()) && pdoc->IsWhiteLine(lineNextWithText)) {
+ lineNextWithText++;
+ }
+ if (lineNextWithText > line) {
+ // This line is empty, so use indentation of last line with text
+ indentSpace = Platform::Maximum(indentSpace,
+ pdoc->GetLineIndentation(lineNextWithText));
+ }
+
+ for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
+ int xIndent = indentPos * vsDraw.spaceWidth;
+ if (xIndent < xStartText) {
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
+
+ // End of the drawing of the current line
+ if (!twoPhaseDraw) {
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
+ xStart, subLine, subLineStart, overrideBackground, background,
+ drawWrapMarkEnd, wrapColour);
+ }
+ if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) {
+ // For each selection draw
+ int virtualSpaces = 0;
+ if (subLine == (ll->lines - 1)) {
+ virtualSpaces = sel.VirtualSpaceFor(pdoc->LineEnd(line));
+ }
+ SelectionPosition posStart(posLineStart);
+ SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces);
+ SelectionSegment virtualSpaceRange(posStart, posEnd);
+ for (size_t r=0; r<sel.Count(); r++) {
+ int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha != SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth);
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
+ rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left);
+ rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right);
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha);
+ }
+ }
+ }
+ }
+
+ // Draw any translucent whole line states
+ rcSegment.left = xStart;
+ rcSegment.right = rcLine.right - 1;
+ if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha);
+ }
+ marks = pdoc->GetMark(line);
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha);
+ } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
+ PRectangle rcUnderline = rcSegment;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha);
+ }
+ marks >>= 1;
+ }
+ if (vsDraw.maskInLine) {
+ int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marksMasked) {
+ for (markBit = 0; (markBit < 32) && marksMasked; markBit++) {
+ if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) {
+ SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha);
+ }
+ marksMasked >>= 1;
+ }
+ }
+ }
+}
+
+void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
+ int xStart, int offset, int posCaret, PRectangle rcCaret, ColourAllocated caretColour) {
+
+ int lineStart = ll->LineStart(subLine);
+ int posBefore = posCaret;
+ int posAfter = MovePositionOutsideChar(posCaret + 1, 1);
+ int numCharsToDraw = posAfter - posCaret;
+
+ // Work out where the starting and ending offsets are. We need to
+ // see if the previous character shares horizontal space, such as a
+ // glyph / combining character. If so we'll need to draw that too.
+ int offsetFirstChar = offset;
+ int offsetLastChar = offset + (posAfter - posCaret);
+ while ((offsetLastChar - numCharsToDraw) >= lineStart) {
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ // Update posBefore to point to the prev char
+ posBefore = MovePositionOutsideChar(posBefore - 1, -1);
+ numCharsToDraw = posAfter - posBefore;
+ offsetFirstChar = offset - (posCaret - posBefore);
+ }
+
+ // See if the next character shares horizontal space, if so we'll
+ // need to draw that too.
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
+ // Update posAfter to point to the 2nd next char, this is where
+ // the next character ends, and 2nd next begins. We'll need
+ // to compare these two
+ posBefore = posAfter;
+ posAfter = MovePositionOutsideChar(posAfter + 1, 1);
+ offsetLastChar = offset + (posAfter - posCaret);
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ }
+
+ // We now know what to draw, update the caret drawing rectangle
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
+ rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[lineStart] + xStart;
+
+ // Adjust caret position to take into account any word wrapping symbols.
+ if ((ll->wrapIndent != 0) && (lineStart != 0)) {
+ int wordWrapCharWidth = ll->wrapIndent;
+ rcCaret.left += wordWrapCharWidth;
+ rcCaret.right += wordWrapCharWidth;
+ }
+
+ // This character is where the caret block is, we override the colours
+ // (inversed) for drawing the caret here.
+ int styleMain = ll->styles[offsetFirstChar];
+ surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font,
+ rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
+ numCharsToDraw, vsDraw.styles[styleMain].back.allocated,
+ caretColour);
+}
+
+void Editor::RefreshPixMaps(Surface *surfaceWindow) {
+ if (!pixmapSelPattern->Initialised()) {
+ const int patternSize = 8;
+ pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
+ // This complex procedure is to reproduce the checkerboard dithered pattern used by windows
+ // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+ // way between the chrome colour and the chrome highlight colour making a nice transition
+ // between the window chrome and the content area. And it works in low colour depths.
+ PRectangle rcPattern(0, 0, patternSize, patternSize);
+
+ // Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
+ ColourAllocated colourFMFill = vs.selbar.allocated;
+ ColourAllocated colourFMStripes = vs.selbarlight.allocated;
+
+ if (!(vs.selbarlight.desired == ColourDesired(0xff, 0xff, 0xff))) {
+ // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+ // (Typically, the highlight colour is white.)
+ colourFMFill = vs.selbarlight.allocated;
+ }
+
+ if (vs.foldmarginColourSet) {
+ // override default fold margin colour
+ colourFMFill = vs.foldmarginColour.allocated;
+ }
+ if (vs.foldmarginHighlightColourSet) {
+ // override default fold margin highlight colour
+ colourFMStripes = vs.foldmarginHighlightColour.allocated;
+ }
+
+ pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
+ pixmapSelPattern->PenColour(colourFMStripes);
+ for (int stripe = 0; stripe < patternSize; stripe++) {
+ // Alternating 1 pixel stripes is same as checkerboard.
+ pixmapSelPattern->MoveTo(0, stripe * 2);
+ pixmapSelPattern->LineTo(patternSize, stripe * 2 - patternSize);
+ }
+ }
+
+ if (!pixmapIndentGuide->Initialised()) {
+ // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
+ pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
+ pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
+ PRectangle rcIG(0, 0, 1, vs.lineHeight);
+ pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated);
+ pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated);
+ pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated);
+ pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated);
+ for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) {
+ pixmapIndentGuide->MoveTo(0, stripe);
+ pixmapIndentGuide->LineTo(2, stripe);
+ pixmapIndentGuideHighlight->MoveTo(0, stripe);
+ pixmapIndentGuideHighlight->LineTo(2, stripe);
+ }
+ }
+
+ if (bufferedDraw) {
+ if (!pixmapLine->Initialised()) {
+ PRectangle rcClient = GetClientRectangle();
+ pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
+ surfaceWindow, wMain.GetID());
+ pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
+ rcClient.Height(), surfaceWindow, wMain.GetID());
+ }
+ }
+}
+
+void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine) {
+ // When drag is active it is the only caret drawn
+ bool drawDrag = posDrag.IsValid();
+ if (hideSelection && !drawDrag)
+ return;
+ const int posLineStart = pdoc->LineStart(lineDoc);
+ // For each selection draw
+ for (size_t r=0; (r<sel.Count()) || drawDrag; r++) {
+ const bool mainCaret = r == sel.Main();
+ const SelectionPosition posCaret = (drawDrag ? posDrag : sel.Range(r).caret);
+ const int offset = posCaret.Position() - posLineStart;
+ const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth);
+ const int virtualOffset = posCaret.VirtualSpace() * spaceWidth;
+ if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
+ int xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
+ if (ll->wrapIndent != 0) {
+ int lineStart = ll->LineStart(subLine);
+ if (lineStart != 0) // Wrapped
+ xposCaret += ll->wrapIndent;
+ }
+ bool caretBlinkState = (caret.active && caret.on) || (!additionalCaretsBlink && !mainCaret);
+ bool caretVisibleState = additionalCaretsVisible || mainCaret;
+ if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
+ ((posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
+ bool caretAtEOF = false;
+ bool caretAtEOL = false;
+ bool drawBlockCaret = false;
+ int widthOverstrikeCaret;
+ int caretWidthOffset = 0;
+ PRectangle rcCaret = rcLine;
+
+ if (posCaret.Position() == pdoc->Length()) { // At end of document
+ caretAtEOF = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line
+ caretAtEOL = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else {
+ widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset];
+ }
+ if (widthOverstrikeCaret < 3) // Make sure its visible
+ widthOverstrikeCaret = 3;
+
+ if (xposCaret > 0)
+ caretWidthOffset = 1; // Move back so overlaps both character cells.
+ xposCaret += xStart;
+ if (posDrag.IsValid()) {
+ /* Dragging text, use a line caret */
+ rcCaret.left = xposCaret - caretWidthOffset;
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ } else if (inOverstrike) {
+ /* Overstrike (insert mode), use a modified bar caret */
+ rcCaret.top = rcCaret.bottom - 2;
+ rcCaret.left = xposCaret + 1;
+ rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+ } else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) {
+ /* Block caret */
+ rcCaret.left = xposCaret;
+ if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) {
+ drawBlockCaret = true;
+ rcCaret.right = xposCaret + widthOverstrikeCaret;
+ } else {
+ rcCaret.right = xposCaret + vsDraw.aveCharWidth;
+ }
+ } else {
+ /* Line caret */
+ rcCaret.left = xposCaret - caretWidthOffset;
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ }
+ ColourAllocated caretColour = mainCaret ? vsDraw.caretcolour.allocated : vsDraw.additionalCaretColour.allocated;
+ if (drawBlockCaret) {
+ DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour);
+ } else {
+ surface->FillRectangle(rcCaret, caretColour);
+ }
+ }
+ }
+ if (drawDrag)
+ break;
+ }
+}
+
+void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+ //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
+ // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+
+ StyleToPositionInView(PositionAfterArea(rcArea));
+
+ pixmapLine->Release();
+ RefreshStyleData();
+ RefreshPixMaps(surfaceWindow);
+
+ PRectangle rcClient = GetClientRectangle();
+ //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
+ // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+ surfaceWindow->SetPalette(&palette, true);
+ pixmapLine->SetPalette(&palette, !hasFocus);
+
+ int screenLinePaintFirst = rcArea.top / vs.lineHeight;
+
+ int xStart = vs.fixedColumnWidth - xOffset;
+ int ypos = 0;
+ if (!bufferedDraw)
+ ypos += screenLinePaintFirst * vs.lineHeight;
+ int yposScreen = screenLinePaintFirst * vs.lineHeight;
+
+ bool paintAbandonedByStyling = paintState == paintAbandoned;
+ if (needUpdateUI) {
+ // Deselect palette by selecting a temporary palette
+ Palette palTemp;
+ surfaceWindow->SetPalette(&palTemp, true);
+
+ NotifyUpdateUI();
+ needUpdateUI = false;
+
+ RefreshStyleData();
+ RefreshPixMaps(surfaceWindow);
+ surfaceWindow->SetPalette(&palette, true);
+ pixmapLine->SetPalette(&palette, !hasFocus);
+ }
+
+ // Call priority lines wrap on a window of lines which are likely
+ // to rendered with the following paint (that is wrap the visible
+ // lines first).
+ int startLineToWrap = cs.DocFromDisplay(topLine) - 5;
+ if (startLineToWrap < 0)
+ startLineToWrap = 0;
+ if (WrapLines(false, startLineToWrap)) {
+ // The wrapping process has changed the height of some lines so
+ // abandon this paint for a complete repaint.
+ if (AbandonPaint()) {
+ return;
+ }
+ RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change
+ }
+ PLATFORM_ASSERT(pixmapSelPattern->Initialised());
+
+ if (paintState != paintAbandoned) {
+ PaintSelMargin(surfaceWindow, rcArea);
+
+ PRectangle rcRightMargin = rcClient;
+ rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+ if (rcArea.Intersects(rcRightMargin)) {
+ surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back.allocated);
+ }
+ }
+
+ if (paintState == paintAbandoned) {
+ // Either styling or NotifyUpdateUI noticed that painting is needed
+ // outside the current painting rectangle
+ //Platform::DebugPrintf("Abandoning paint\n");
+ if (wrapState != eWrapNone) {
+ if (paintAbandonedByStyling) {
+ // Styling has spilled over a line end, such as occurs by starting a multiline
+ // comment. The width of subsequent text may have changed, so rewrap.
+ NeedWrapping(cs.DocFromDisplay(topLine));
+ }
+ }
+ return;
+ }
+ //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+ // Do the painting
+ if (rcArea.right > vs.fixedColumnWidth) {
+
+ Surface *surface = surfaceWindow;
+ if (bufferedDraw) {
+ surface = pixmapLine;
+ PLATFORM_ASSERT(pixmapLine->Initialised());
+ }
+ surface->SetUnicodeMode(IsUnicodeMode());
+ surface->SetDBCSMode(CodePage());
+
+ int visibleLine = topLine + screenLinePaintFirst;
+
+ SelectionPosition posCaret = sel.RangeMain().caret;
+ if (posDrag.IsValid())
+ posCaret = posDrag;
+ int lineCaret = pdoc->LineFromPosition(posCaret.Position());
+
+ // Remove selection margin from drawing area so text will not be drawn
+ // on it in unbuffered mode.
+ PRectangle rcTextArea = rcClient;
+ rcTextArea.left = vs.fixedColumnWidth;
+ rcTextArea.right -= vs.rightMarginWidth;
+ surfaceWindow->SetClip(rcTextArea);
+
+ // Loop on visible lines
+ //double durLayout = 0.0;
+ //double durPaint = 0.0;
+ //double durCopy = 0.0;
+ //ElapsedTime etWhole;
+ int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times
+ AutoLineLayout ll(llc, 0);
+ while (visibleLine < cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+
+ int lineDoc = cs.DocFromDisplay(visibleLine);
+ // Only visible lines should be handled by the code within the loop
+ PLATFORM_ASSERT(cs.GetVisible(lineDoc));
+ int lineStartSet = cs.DisplayFromDoc(lineDoc);
+ int subLine = visibleLine - lineStartSet;
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ //ElapsedTime et;
+ if (lineDoc != lineDocPrevious) {
+ ll.Set(0);
+ ll.Set(RetrieveLineLayout(lineDoc));
+ LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
+ lineDocPrevious = lineDoc;
+ }
+ //durLayout += et.Duration(true);
+
+ if (ll) {
+ ll->containsCaret = lineDoc == lineCaret;
+ if (hideSelection) {
+ ll->containsCaret = false;
+ }
+
+ GetHotSpotRange(ll->hsStart, ll->hsEnd);
+
+ PRectangle rcLine = rcClient;
+ rcLine.top = ypos;
+ rcLine.bottom = ypos + vs.lineHeight;
+
+ Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1));
+ // Highlight the current braces if any
+ ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle),
+ highlightGuideColumn * vs.spaceWidth);
+
+ // Draw the line
+ DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine);
+ //durPaint += et.Duration(true);
+
+ // Restore the previous styles for the brace highlights in case layout is in cache.
+ ll->RestoreBracesHighlight(rangeLine, braces);
+
+ bool expanded = cs.GetExpanded(lineDoc);
+ // Paint the line above the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
+ if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.bottom = rcFoldLine.top + 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+ // Paint the line below the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
+ if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.top = rcFoldLine.bottom - 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+
+ DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);
+
+ if (bufferedDraw) {
+ Point from(vs.fixedColumnWidth, 0);
+ PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen,
+ rcClient.right, yposScreen + vs.lineHeight);
+ surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
+ }
+
+ lineWidthMaxSeen = Platform::Maximum(
+ lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
+ //durCopy += et.Duration(true);
+ }
+
+ if (!bufferedDraw) {
+ ypos += vs.lineHeight;
+ }
+
+ yposScreen += vs.lineHeight;
+ visibleLine++;
+
+ //gdk_flush();
+ }
+ ll.Set(0);
+ //if (durPaint < 0.00000001)
+ // durPaint = 0.00000001;
+
+ // Right column limit indicator
+ PRectangle rcBeyondEOF = rcClient;
+ rcBeyondEOF.left = vs.fixedColumnWidth;
+ rcBeyondEOF.right = rcBeyondEOF.right;
+ rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
+ if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back.allocated);
+ if (vs.edgeState == EDGE_LINE) {
+ int edgeX = theEdge * vs.spaceWidth;
+ rcBeyondEOF.left = edgeX + xStart;
+ rcBeyondEOF.right = rcBeyondEOF.left + 1;
+ surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated);
+ }
+ }
+ //Platform::DebugPrintf(
+ //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n",
+ //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration());
+ NotifyPainted();
+ }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace " "
+
+ColourDesired InvertedLight(ColourDesired orig) {
+ unsigned int r = orig.GetRed();
+ unsigned int g = orig.GetGreen();
+ unsigned int b = orig.GetBlue();
+ unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye
+ unsigned int il = 0xff - l;
+ if (l == 0)
+ return ColourDesired(0xff, 0xff, 0xff);
+ r = r * il / l;
+ g = g * il / l;
+ b = b * il / l;
+ return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff));
+}
+
+// This is mostly copied from the Paint method but with some things omitted
+// such as the margin markers, line numbers, selection and caret
+// Should be merged back into a combined Draw method.
+long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
+ if (!pfr)
+ return 0;
+
+ AutoSurface surface(pfr->hdc, this);
+ if (!surface)
+ return 0;
+ AutoSurface surfaceMeasure(pfr->hdcTarget, this);
+ if (!surfaceMeasure) {
+ return 0;
+ }
+
+ // Can't use measurements cached for screen
+ posCache.Clear();
+
+ ViewStyle vsPrint(vs);
+
+ // Modify the view style for printing as do not normally want any of the transient features to be printed
+ // Printing supports only the line number margin.
+ int lineNumberIndex = -1;
+ for (int margin = 0; margin < ViewStyle::margins; margin++) {
+ if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
+ lineNumberIndex = margin;
+ } else {
+ vsPrint.ms[margin].width = 0;
+ }
+ }
+ vsPrint.showMarkedLines = false;
+ vsPrint.fixedColumnWidth = 0;
+ vsPrint.zoomLevel = printMagnification;
+ vsPrint.viewIndentationGuides = ivNone;
+ // Don't show the selection when printing
+ vsPrint.selbackset = false;
+ vsPrint.selforeset = false;
+ vsPrint.selAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.whitespaceBackgroundSet = false;
+ vsPrint.whitespaceForegroundSet = false;
+ vsPrint.showCaretLineBackground = false;
+
+ // Set colours for printing according to users settings
+ for (size_t sty = 0; sty < vsPrint.stylesSize; sty++) {
+ if (printColourMode == SC_PRINT_INVERTLIGHT) {
+ vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired);
+ vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired);
+ } else if (printColourMode == SC_PRINT_BLACKONWHITE) {
+ vsPrint.styles[sty].fore.desired = ColourDesired(0, 0, 0);
+ vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printColourMode == SC_PRINT_COLOURONWHITE) {
+ vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printColourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) {
+ if (sty <= STYLE_DEFAULT) {
+ vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff);
+ }
+ }
+ }
+ // White background for the line numbers
+ vsPrint.styles[STYLE_LINENUMBER].back.desired = ColourDesired(0xff, 0xff, 0xff);
+
+ vsPrint.Refresh(*surfaceMeasure);
+ // Determining width must hapen after fonts have been realised in Refresh
+ int lineNumberWidth = 0;
+ if (lineNumberIndex >= 0) {
+ lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
+ "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
+ vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+ vsPrint.Refresh(*surfaceMeasure); // Recalculate fixedColumnWidth
+ }
+ // Ensure colours are set up
+ vsPrint.RefreshColourPalette(palette, true);
+ vsPrint.RefreshColourPalette(palette, false);
+
+ int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
+ int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+ if (linePrintLast < linePrintStart)
+ linePrintLast = linePrintStart;
+ int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax);
+ if (linePrintLast > linePrintMax)
+ linePrintLast = linePrintMax;
+ //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+ // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+ // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+ int endPosPrint = pdoc->Length();
+ if (linePrintLast < pdoc->LinesTotal())
+ endPosPrint = pdoc->LineStart(linePrintLast + 1);
+
+ // Ensure we are styled to where we are formatting.
+ pdoc->EnsureStyledTo(endPosPrint);
+
+ int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
+ int ypos = pfr->rc.top;
+
+ int lineDoc = linePrintStart;
+
+ int nPrintPos = pfr->chrg.cpMin;
+ int visibleLine = 0;
+ int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
+ if (printWrapState == eWrapNone)
+ widthPrint = LineLayout::wrapWidthInfinite;
+
+ while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {
+
+ // When printing, the hdc and hdcTarget may be the same, so
+ // changing the state of surfaceMeasure may change the underlying
+ // state of surface. Therefore, any cached state is discarded before
+ // using each surface.
+ surfaceMeasure->FlushCachedState();
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ LineLayout ll(8000);
+ LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);
+
+ ll.containsCaret = false;
+
+ PRectangle rcLine;
+ rcLine.left = pfr->rc.left;
+ rcLine.top = ypos;
+ rcLine.right = pfr->rc.right - 1;
+ rcLine.bottom = ypos + vsPrint.lineHeight;
+
+ // When document line is wrapped over multiple display lines, find where
+ // to start printing from to ensure a particular position is on the first
+ // line of the page.
+ if (visibleLine == 0) {
+ int startWithinLine = nPrintPos - pdoc->LineStart(lineDoc);
+ for (int iwl = 0; iwl < ll.lines - 1; iwl++) {
+ if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) {
+ visibleLine = -iwl;
+ }
+ }
+
+ if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) {
+ visibleLine = -(ll.lines - 1);
+ }
+ }
+
+ if (draw && lineNumberWidth &&
+ (ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
+ (visibleLine >= 0)) {
+ char number[100];
+ sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1);
+ PRectangle rcNumber = rcLine;
+ rcNumber.right = rcNumber.left + lineNumberWidth;
+ // Right justify
+ rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
+ vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number));
+ surface->FlushCachedState();
+ surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+ ypos + vsPrint.maxAscent, number, istrlen(number),
+ vsPrint.styles[STYLE_LINENUMBER].fore.allocated,
+ vsPrint.styles[STYLE_LINENUMBER].back.allocated);
+ }
+
+ // Draw the line
+ surface->FlushCachedState();
+
+ for (int iwl = 0; iwl < ll.lines; iwl++) {
+ if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
+ if (visibleLine >= 0) {
+ if (draw) {
+ rcLine.top = ypos;
+ rcLine.bottom = ypos + vsPrint.lineHeight;
+ DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl);
+ }
+ ypos += vsPrint.lineHeight;
+ }
+ visibleLine++;
+ if (iwl == ll.lines - 1)
+ nPrintPos = pdoc->LineStart(lineDoc + 1);
+ else
+ nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl);
+ }
+ }
+
+ ++lineDoc;
+ }
+
+ // Clear cache so measurements are not used for screen
+ posCache.Clear();
+
+ return nPrintPos;
+}
+
+int Editor::TextWidth(int style, const char *text) {
+ RefreshStyleData();
+ AutoSurface surface(this);
+ if (surface) {
+ return surface->WidthText(vs.styles[style].font, text, istrlen(text));
+ } else {
+ return 1;
+ }
+}
+
+// Empty method is overridden on GTK+ to show / hide scrollbars
+void Editor::ReconfigureScrollBars() {}
+
+void Editor::SetScrollBars() {
+ RefreshStyleData();
+
+ 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
+ if (topLine > MaxScrollPos()) {
+ SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ if (modified) {
+ if (!AbandonPaint())
+ Redraw();
+ }
+ //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
+}
+
+void Editor::ChangeSize() {
+ DropGraphics();
+ SetScrollBars();
+ if (wrapState != eWrapNone) {
+ PRectangle rcTextArea = GetClientRectangle();
+ rcTextArea.left = vs.fixedColumnWidth;
+ rcTextArea.right -= vs.rightMarginWidth;
+ if (wrapWidth != rcTextArea.Width()) {
+ NeedWrapping();
+ Redraw();
+ }
+ }
+}
+
+int Editor::InsertSpace(int position, unsigned int spaces) {
+ if (spaces > 0) {
+ std::string spaceText(spaces, ' ');
+ pdoc->InsertString(position, spaceText.c_str(), spaces);
+ position += spaces;
+ }
+ return position;
+}
+
+void Editor::AddChar(char ch) {
+ char s[2];
+ s[0] = ch;
+ s[1] = '\0';
+ AddCharUTF(s, 1);
+}
+
+void Editor::FilterSelections() {
+ if (!additionalSelectionTyping && (sel.Count() > 1)) {
+ SelectionRange rangeOnly = sel.RangeMain();
+ InvalidateSelection(rangeOnly, true);
+ sel.SetSelection(rangeOnly);
+ }
+}
+
+// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
+void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
+ FilterSelections();
+ {
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ int positionInsert = sel.Range(r).Start().Position();
+ if (!sel.Range(r).Empty()) {
+ if (sel.Range(r).Length()) {
+ pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
+ sel.Range(r).ClearVirtualSpace();
+ } else {
+ // Range is all virtual so collapse to start of virtual space
+ sel.Range(r).MinimizeVirtualSpace();
+ }
+ } else if (inOverstrike) {
+ if (positionInsert < pdoc->Length()) {
+ if (!IsEOLChar(pdoc->CharAt(positionInsert))) {
+ pdoc->DelChar(positionInsert);
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ }
+ positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
+ if (pdoc->InsertString(positionInsert, s, len)) {
+ sel.Range(r).caret.SetPosition(positionInsert + len);
+ sel.Range(r).anchor.SetPosition(positionInsert + len);
+ }
+ sel.Range(r).ClearVirtualSpace();
+ // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+ if (wrapState != eWrapNone) {
+ AutoSurface surface(this);
+ if (surface) {
+ if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) {
+ SetScrollBars();
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ }
+ }
+ }
+ }
+ }
+ if (wrapState != eWrapNone) {
+ SetScrollBars();
+ }
+ ThinRectangularRange();
+ // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+ EnsureCaretVisible();
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+
+ if (treatAsDBCS) {
+ NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
+ static_cast<unsigned char>(s[1]));
+ } else {
+ int byte = static_cast<unsigned char>(s[0]);
+ if ((byte < 0xC0) || (1 == len)) {
+ // Handles UTF-8 characters between 0x01 and 0x7F and single byte
+ // characters when not in UTF-8 mode.
+ // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
+ // characters representing themselves.
+ } else {
+ // Unroll 1 to 3 byte UTF-8 sequences. See reference data at:
+ // http://www.cl.cam.ac.uk/~mgk25/unicode.html
+ // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+ if (byte < 0xE0) {
+ int byte2 = static_cast<unsigned char>(s[1]);
+ if ((byte2 & 0xC0) == 0x80) {
+ // Two-byte-character lead-byte followed by a trail-byte.
+ byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F));
+ }
+ // A two-byte-character lead-byte not followed by trail-byte
+ // represents itself.
+ } else if (byte < 0xF0) {
+ int byte2 = static_cast<unsigned char>(s[1]);
+ int byte3 = static_cast<unsigned char>(s[2]);
+ if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) {
+ // Three-byte-character lead byte followed by two trail bytes.
+ byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
+ (byte3 & 0x3F));
+ }
+ // A three-byte-character lead-byte not followed by two trail-bytes
+ // represents itself.
+ }
+ }
+ NotifyChar(byte);
+ }
+
+ if (recordingMacro) {
+ NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(s));
+ }
+}
+
+void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) {
+ if (multiPasteMode == SC_MULTIPASTE_ONCE) {
+ selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace()));
+ if (pdoc->InsertString(selStart.Position(), text, len)) {
+ SetEmptySelection(selStart.Position() + len);
+ }
+ } else {
+ // SC_MULTIPASTE_EACH
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ int positionInsert = sel.Range(r).Start().Position();
+ if (!sel.Range(r).Empty()) {
+ if (sel.Range(r).Length()) {
+ pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
+ sel.Range(r).ClearVirtualSpace();
+ } else {
+ // Range is all virtual so collapse to start of virtual space
+ sel.Range(r).MinimizeVirtualSpace();
+ }
+ }
+ positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
+ if (pdoc->InsertString(positionInsert, text, len)) {
+ sel.Range(r).caret.SetPosition(positionInsert + len);
+ sel.Range(r).anchor.SetPosition(positionInsert + len);
+ }
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ }
+}
+
+void Editor::ClearSelection() {
+ if (!sel.IsRectangular())
+ FilterSelections();
+ UndoGroup ug(pdoc);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!sel.Range(r).Empty()) {
+ if (!RangeContainsProtected(sel.Range(r).Start().Position(),
+ sel.Range(r).End().Position())) {
+ pdoc->DeleteChars(sel.Range(r).Start().Position(),
+ sel.Range(r).Length());
+ sel.Range(r) = sel.Range(r).Start();
+ }
+ }
+ }
+ ThinRectangularRange();
+ sel.RemoveDuplicates();
+ ClaimSelection();
+}
+
+void Editor::ClearAll() {
+ {
+ UndoGroup ug(pdoc);
+ if (0 != pdoc->Length()) {
+ pdoc->DeleteChars(0, pdoc->Length());
+ }
+ if (!pdoc->IsReadOnly()) {
+ cs.Clear();
+ pdoc->AnnotationClearAll();
+ pdoc->MarginClearAll();
+ }
+ }
+ sel.Clear();
+ SetTopLine(0);
+ SetVerticalScrollPos();
+ InvalidateStyleRedraw();
+}
+
+void Editor::ClearDocumentStyle() {
+ Decoration *deco = pdoc->decorations.root;
+ while (deco) {
+ // Save next in case deco deleted
+ Decoration *decoNext = deco->next;
+ if (deco->indicator < INDIC_CONTAINER) {
+ pdoc->decorations.SetCurrentIndicator(deco->indicator);
+ pdoc->DecorationFillRange(0, 0, pdoc->Length());
+ }
+ deco = decoNext;
+ }
+ pdoc->StartStyling(0, '\377');
+ pdoc->SetStyleFor(pdoc->Length(), 0);
+ cs.ShowAll();
+ pdoc->ClearLevels();
+}
+
+void Editor::CopyAllowLine() {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText, true);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::Cut() {
+ pdoc->CheckReadOnly();
+ if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
+ Copy();
+ ClearSelection();
+ }
+}
+
+void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
+ if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
+ return;
+ }
+ sel.Clear();
+ sel.RangeMain() = SelectionRange(pos);
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ int xInsert = XFromPosition(sel.RangeMain().caret);
+ bool prevCr = false;
+ while ((len > 0) && IsEOLChar(ptr[len-1]))
+ len--;
+ for (int i = 0; i < len; i++) {
+ if (IsEOLChar(ptr[i])) {
+ if ((ptr[i] == '\r') || (!prevCr))
+ line++;
+ if (line >= pdoc->LinesTotal()) {
+ if (pdoc->eolMode != SC_EOL_LF)
+ pdoc->InsertChar(pdoc->Length(), '\r');
+ if (pdoc->eolMode != SC_EOL_CR)
+ pdoc->InsertChar(pdoc->Length(), '\n');
+ }
+ // Pad the end of lines with spaces if required
+ sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert));
+ if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) {
+ while (XFromPosition(sel.MainCaret()) < xInsert) {
+ pdoc->InsertChar(sel.MainCaret(), ' ');
+ sel.RangeMain().caret.Add(1);
+ }
+ }
+ prevCr = ptr[i] == '\r';
+ } else {
+ pdoc->InsertString(sel.MainCaret(), ptr + i, 1);
+ sel.RangeMain().caret.Add(1);
+ prevCr = false;
+ }
+ }
+ SetEmptySelection(pos);
+}
+
+bool Editor::CanPaste() {
+ return !pdoc->IsReadOnly() && !SelectionContainsProtected();
+}
+
+void Editor::Clear() {
+ // If multiple selections, don't delete EOLS
+ if (sel.Empty()) {
+ UndoGroup ug(pdoc, sel.Count() > 1);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
+ if (sel.Range(r).Start().VirtualSpace()) {
+ if (sel.Range(r).anchor < sel.Range(r).caret)
+ sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).anchor.Position(), sel.Range(r).anchor.VirtualSpace()));
+ else
+ sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
+ }
+ if ((sel.Count() == 1) || !IsEOLChar(pdoc->CharAt(sel.Range(r).caret.Position()))) {
+ pdoc->DelChar(sel.Range(r).caret.Position());
+ sel.Range(r).ClearVirtualSpace();
+ } // else multiple selection so don't eat line ends
+ } else {
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ } else {
+ ClearSelection();
+ }
+ sel.RemoveDuplicates();
+}
+
+void Editor::SelectAll() {
+ sel.Clear();
+ SetSelection(0, pdoc->Length());
+ Redraw();
+}
+
+void Editor::Undo() {
+ if (pdoc->CanUndo()) {
+ InvalidateCaret();
+ int newPos = pdoc->Undo();
+ if (newPos >= 0)
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::Redo() {
+ if (pdoc->CanRedo()) {
+ int newPos = pdoc->Redo();
+ if (newPos >= 0)
+ SetEmptySelection(newPos);
+ EnsureCaretVisible();
+ }
+}
+
+void Editor::DelChar() {
+ if (!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1)) {
+ pdoc->DelChar(sel.MainCaret());
+ }
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::DelCharBack(bool allowLineStartDeletion) {
+ if (!sel.IsRectangular())
+ FilterSelections();
+ if (sel.IsRectangular())
+ allowLineStartDeletion = false;
+ UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
+ if (sel.Empty()) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
+ if (sel.Range(r).caret.VirtualSpace()) {
+ sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1);
+ sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace());
+ } else {
+ int lineCurrentPos = pdoc->LineFromPosition(sel.Range(r).caret.Position());
+ if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
+ if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
+ pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
+ UndoGroup ugInner(pdoc, !ug.Needed());
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ if (indentation % indentationStep == 0) {
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
+ } else {
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep));
+ }
+ // SetEmptySelection
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos),
+ pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ pdoc->DelCharBack(sel.Range(r).caret.Position());
+ }
+ }
+ }
+ } else {
+ sel.Range(r).ClearVirtualSpace();
+ }
+ }
+ } else {
+ ClearSelection();
+ }
+ sel.RemoveDuplicates();
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::NotifyFocus(bool) {}
+
+void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_STYLENEEDED;
+ scn.position = endStyleNeeded;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) {
+ NotifyStyleToNeeded(endStyleNeeded);
+}
+
+void Editor::NotifyChar(int ch) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_CHARADDED;
+ scn.ch = ch;
+ NotifyParent(scn);
+}
+
+void Editor::NotifySavePoint(bool isSavePoint) {
+ SCNotification scn = {0};
+ if (isSavePoint) {
+ scn.nmhdr.code = SCN_SAVEPOINTREACHED;
+ } else {
+ scn.nmhdr.code = SCN_SAVEPOINTLEFT;
+ }
+ NotifyParent(scn);
+}
+
+void Editor::NotifyModifyAttempt() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_DOUBLECLICK;
+ scn.line = LineFromLocation(pt);
+ scn.position = PositionFromLocation(pt, true);
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
+ scn.position = position;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_HOTSPOTCLICK;
+ scn.position = position;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ NotifyParent(scn);
+}
+
+void Editor::NotifyUpdateUI() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_UPDATEUI;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyPainted() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_PAINTED;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt) {
+ int mask = pdoc->decorations.AllOnFor(position);
+ if ((click && mask) || pdoc->decorations.clickNotified) {
+ SCNotification scn = {0};
+ pdoc->decorations.clickNotified = click;
+ scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0);
+ scn.position = position;
+ NotifyParent(scn);
+ }
+}
+
+bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
+ int marginClicked = -1;
+ int x = 0;
+ for (int margin = 0; margin < ViewStyle::margins; margin++) {
+ if ((pt.x > x) && (pt.x < x + vs.ms[margin].width))
+ marginClicked = margin;
+ x += vs.ms[margin].width;
+ }
+ if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MARGINCLICK;
+ scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ scn.position = pdoc->LineStart(LineFromLocation(pt));
+ scn.margin = marginClicked;
+ NotifyParent(scn);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Editor::NotifyNeedShown(int pos, int len) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_NEEDSHOWN;
+ scn.position = pos;
+ scn.length = len;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyDwelling(Point pt, bool state) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
+ scn.position = PositionFromLocation(pt, true);
+ scn.x = pt.x;
+ scn.y = pt.y;
+ NotifyParent(scn);
+}
+
+void Editor::NotifyZoom() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_ZOOM;
+ NotifyParent(scn);
+}
+
+// Notifications from document
+void Editor::NotifyModifyAttempt(Document *, void *) {
+ //Platform::DebugPrintf("** Modify Attempt\n");
+ NotifyModifyAttempt();
+}
+
+void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) {
+ //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
+ NotifySavePoint(atSavePoint);
+}
+
+void Editor::CheckModificationForWrap(DocModification mh) {
+ if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
+ llc.Invalidate(LineLayout::llCheckTextAndStyle);
+ if (wrapState != eWrapNone) {
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ int lines = Platform::Maximum(0, mh.linesAdded);
+ NeedWrapping(lineDoc, lineDoc + lines + 1);
+ }
+ // Fix up annotation heights
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ int lines = Platform::Maximum(0, mh.linesAdded);
+ SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
+ }
+}
+
+// Move a position so it is still after the same character as before the insertion.
+static inline int MovePositionForInsertion(int position, int startInsertion, int length) {
+ if (position > startInsertion) {
+ return position + length;
+ }
+ return position;
+}
+
+// Move a position so it is still after the same character as before the deletion if that
+// character is still present else after the previous surviving character.
+static inline int MovePositionForDeletion(int position, int startDeletion, int length) {
+ if (position > startDeletion) {
+ int endDeletion = startDeletion + length;
+ if (position > endDeletion) {
+ return position - length;
+ } else {
+ return startDeletion;
+ }
+ } else {
+ return position;
+ }
+}
+
+void Editor::NotifyModified(Document *, DocModification mh, void *) {
+ needUpdateUI = true;
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
+ }
+ if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
+ if (paintState == painting) {
+ CheckForChangeOutsidePaint(
+ Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
+ } else {
+ // Could check that change is before last visible line.
+ Redraw();
+ }
+ }
+ if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
+ if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+ pdoc->IncrementStyleClock();
+ }
+ if (paintState == notPainting) {
+ if (mh.position < pdoc->LineStart(topLine)) {
+ // Styling performed before this view
+ Redraw();
+ } else {
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ }
+ if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+ llc.Invalidate(LineLayout::llCheckTextAndStyle);
+ }
+ } else {
+ // Move selection and brace highlights
+ if (mh.modificationType & SC_MOD_INSERTTEXT) {
+ sel.MovePositions(true, mh.position, mh.length);
+ braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
+ braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
+ } else if (mh.modificationType & SC_MOD_DELETETEXT) {
+ sel.MovePositions(false, mh.position, mh.length);
+ braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
+ braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
+ }
+ if (cs.LinesDisplayed() < cs.LinesInDoc()) {
+ // 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, 0);
+ } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
+ NotifyNeedShown(mh.position, mh.length);
+ }
+ }
+ if (mh.linesAdded != 0) {
+ // Update contraction state for inserted and removed lines
+ // lineOfPos should be calculated in context of state before modification, shouldn't it
+ int lineOfPos = pdoc->LineFromPosition(mh.position);
+ if (mh.linesAdded > 0) {
+ cs.InsertLines(lineOfPos, mh.linesAdded);
+ } else {
+ cs.DeleteLines(lineOfPos, -mh.linesAdded);
+ }
+ }
+ if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
+ int lineDoc = pdoc->LineFromPosition(mh.position);
+ if (vs.annotationVisible) {
+ cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded);
+ }
+ }
+ CheckModificationForWrap(mh);
+ if (mh.linesAdded != 0) {
+ // Avoid scrolling of display if change before current display
+ if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
+ int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
+ if (newTop != topLine) {
+ SetTopLine(newTop);
+ SetVerticalScrollPos();
+ }
+ }
+
+ //Platform::DebugPrintf("** %x Doc Changed\n", this);
+ // TODO: could invalidate from mh.startModification to end of screen
+ //InvalidateRange(mh.position, mh.position + mh.length);
+ if (paintState == notPainting && !CanDeferToLastStep(mh)) {
+ QueueStyling(pdoc->Length());
+ Redraw();
+ }
+ } else {
+ //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
+ // mh.position, mh.position + mh.length);
+ if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
+ QueueStyling(mh.position + mh.length);
+ InvalidateRange(mh.position, mh.position + mh.length);
+ }
+ }
+ }
+
+ if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
+ SetScrollBars();
+ }
+
+ if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
+ if ((paintState == notPainting) || !PaintContainsMargin()) {
+ if (mh.modificationType & SC_MOD_CHANGEFOLD) {
+ // Fold changes can affect the drawing of following lines so redraw whole margin
+ RedrawSelMargin(mh.line-1, true);
+ } 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 | SC_MOD_CHANGEINDICATOR)) == 0) {
+ // Real modification made to text of document.
+ NotifyChange(); // Send EN_CHANGE
+ }
+
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MODIFIED;
+ scn.position = mh.position;
+ scn.modificationType = mh.modificationType;
+ scn.text = mh.text;
+ scn.length = mh.length;
+ scn.linesAdded = mh.linesAdded;
+ scn.line = mh.line;
+ scn.foldLevelNow = mh.foldLevelNow;
+ scn.foldLevelPrev = mh.foldLevelPrev;
+ scn.token = mh.token;
+ scn.annotationLinesAdded = mh.annotationLinesAdded;
+ NotifyParent(scn);
+ }
+}
+
+void Editor::NotifyDeleted(Document *, void *) {
+ /* Do nothing */
+}
+
+void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+
+ // Enumerates all macroable messages
+ switch (iMessage) {
+ case SCI_CUT:
+ case SCI_COPY:
+ case SCI_PASTE:
+ case SCI_CLEAR:
+ case SCI_REPLACESEL:
+ case SCI_ADDTEXT:
+ case SCI_INSERTTEXT:
+ case SCI_APPENDTEXT:
+ case SCI_CLEARALL:
+ case SCI_SELECTALL:
+ case SCI_GOTOLINE:
+ case SCI_GOTOPOS:
+ case SCI_SEARCHANCHOR:
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_PARADOWN:
+ case SCI_PARADOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_PARAUP:
+ case SCI_PARAUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_WORDPARTLEFT:
+ case SCI_WORDPARTLEFTEXTEND:
+ case SCI_WORDPARTRIGHT:
+ case SCI_WORDPARTRIGHTEXTEND:
+ case SCI_WORDLEFTEND:
+ case SCI_WORDLEFTENDEXTEND:
+ case SCI_WORDRIGHTEND:
+ case SCI_WORDRIGHTENDEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_HOMEWRAP:
+ case SCI_HOMEWRAPEXTEND:
+ case SCI_LINEENDWRAP:
+ case SCI_LINEENDWRAPEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+ case SCI_STUTTEREDPAGEUP:
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ case SCI_STUTTEREDPAGEDOWN:
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_VCHOMEWRAP:
+ case SCI_VCHOMEWRAPEXTEND:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ case SCI_DELWORDRIGHTEND:
+ case SCI_DELLINELEFT:
+ case SCI_DELLINERIGHT:
+ case SCI_LINECOPY:
+ case SCI_LINECUT:
+ case SCI_LINEDELETE:
+ case SCI_LINETRANSPOSE:
+ case SCI_LINEDUPLICATE:
+ case SCI_LOWERCASE:
+ case SCI_UPPERCASE:
+ case SCI_LINESCROLLDOWN:
+ case SCI_LINESCROLLUP:
+ case SCI_DELETEBACKNOTLINE:
+ case SCI_HOMEDISPLAY:
+ case SCI_HOMEDISPLAYEXTEND:
+ case SCI_LINEENDDISPLAY:
+ case SCI_LINEENDDISPLAYEXTEND:
+ case SCI_SETSELECTIONMODE:
+ case SCI_LINEDOWNRECTEXTEND:
+ case SCI_LINEUPRECTEXTEND:
+ case SCI_CHARLEFTRECTEXTEND:
+ case SCI_CHARRIGHTRECTEXTEND:
+ case SCI_HOMERECTEXTEND:
+ case SCI_VCHOMERECTEXTEND:
+ case SCI_LINEENDRECTEXTEND:
+ case SCI_PAGEUPRECTEXTEND:
+ case SCI_PAGEDOWNRECTEXTEND:
+ case SCI_SELECTIONDUPLICATE:
+ case SCI_COPYALLOWLINE:
+ break;
+
+ // Filter out all others like display changes. Also, newlines are redundant
+ // with char insert messages.
+ case SCI_NEWLINE:
+ default:
+ // printf("Filtered out %ld of macro recording\n", iMessage);
+ return ;
+ }
+
+ // Send notification
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_MACRORECORD;
+ scn.message = iMessage;
+ scn.wParam = wParam;
+ scn.lParam = lParam;
+ NotifyParent(scn);
+}
+
+/**
+ * Force scroll and keep position relative to top of window.
+ *
+ * If stuttered = true and not already at first/last row, move to first/last row of window.
+ * If stuttered = true and already at first/last row, scroll as normal.
+ */
+void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
+ int topLineNew, newPos;
+
+ // I consider only the caretYSlop, and ignore the caretYPolicy-- is that a problem?
+ int currentLine = pdoc->LineFromPosition(sel.MainCaret());
+ int topStutterLine = topLine + caretYSlop;
+ int bottomStutterLine =
+ pdoc->LineFromPosition(PositionFromLocation(
+ Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll())))
+ - caretYSlop - 1;
+
+ if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
+ topLineNew = topLine;
+ newPos = PositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop));
+
+ } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
+ topLineNew = topLine;
+ newPos = PositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)));
+
+ } else {
+ Point pt = LocationFromPosition(sel.MainCaret());
+
+ topLineNew = Platform::Clamp(
+ topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+ newPos = PositionFromLocation(
+ Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())));
+ }
+
+ if (topLineNew != topLine) {
+ SetTopLine(topLineNew);
+ MovePositionTo(SelectionPosition(newPos), selt);
+ Redraw();
+ SetVerticalScrollPos();
+ } else {
+ MovePositionTo(SelectionPosition(newPos), selt);
+ }
+}
+
+void Editor::ChangeCaseOfSelection(int caseMapping) {
+ UndoGroup ug(pdoc);
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionRange current = sel.Range(r);
+ SelectionRange currentNoVS = current;
+ currentNoVS.ClearVirtualSpace();
+ char *text = CopyRange(currentNoVS.Start().Position(), currentNoVS.End().Position());
+ size_t rangeBytes = currentNoVS.Length();
+ if (rangeBytes > 0) {
+ std::string sText(text, rangeBytes);
+
+ std::string sMapped = CaseMapString(sText, caseMapping);
+
+ if (sMapped != sText) {
+ size_t firstDifference = 0;
+ while (sMapped[firstDifference] == sText[firstDifference])
+ firstDifference++;
+ size_t lastDifference = sMapped.size() - 1;
+ while (sMapped[lastDifference] == sText[lastDifference])
+ lastDifference--;
+ size_t endSame = sMapped.size() - 1 - lastDifference;
+ pdoc->DeleteChars(currentNoVS.Start().Position() + firstDifference,
+ rangeBytes - firstDifference - endSame);
+ pdoc->InsertString(currentNoVS.Start().Position() + firstDifference,
+ sMapped.c_str() + firstDifference, lastDifference - firstDifference + 1);
+ // Automatic movement changes selection so reset to exactly the same as it was.
+ sel.Range(r) = current;
+ }
+ }
+ delete []text;
+ }
+}
+
+void Editor::LineTranspose() {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ if (line > 0) {
+ UndoGroup ug(pdoc);
+ int startPrev = pdoc->LineStart(line - 1);
+ int endPrev = pdoc->LineEnd(line - 1);
+ int start = pdoc->LineStart(line);
+ int end = pdoc->LineEnd(line);
+ char *line1 = CopyRange(startPrev, endPrev);
+ int len1 = endPrev - startPrev;
+ char *line2 = CopyRange(start, end);
+ int len2 = end - start;
+ pdoc->DeleteChars(start, len2);
+ pdoc->DeleteChars(startPrev, len1);
+ pdoc->InsertString(startPrev, line2, len2);
+ pdoc->InsertString(start - len1 + len2, line1, len1);
+ MovePositionTo(SelectionPosition(start - len1 + len2));
+ delete []line1;
+ delete []line2;
+ }
+}
+
+void Editor::Duplicate(bool forLine) {
+ if (sel.Empty()) {
+ forLine = true;
+ }
+ UndoGroup ug(pdoc, sel.Count() > 1);
+ SelectionPosition last;
+ const char *eol = "";
+ int eolLen = 0;
+ if (forLine) {
+ eol = StringFromEOLMode(pdoc->eolMode);
+ eolLen = istrlen(eol);
+ }
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionPosition start = sel.Range(r).Start();
+ SelectionPosition end = sel.Range(r).End();
+ if (forLine) {
+ int line = pdoc->LineFromPosition(sel.Range(r).caret.Position());
+ start = SelectionPosition(pdoc->LineStart(line));
+ end = SelectionPosition(pdoc->LineEnd(line));
+ }
+ char *text = CopyRange(start.Position(), end.Position());
+ if (forLine)
+ pdoc->InsertString(end.Position(), eol, eolLen);
+ pdoc->InsertString(end.Position() + eolLen, text, SelectionRange(end, start).Length());
+ delete []text;
+ }
+ if (sel.Count() && sel.IsRectangular()) {
+ SelectionPosition last = sel.Last();
+ if (forLine) {
+ int line = pdoc->LineFromPosition(last.Position());
+ last = SelectionPosition(last.Position() + pdoc->LineStart(line+1) - pdoc->LineStart(line));
+ }
+ if (sel.Rectangular().anchor > sel.Rectangular().caret)
+ sel.Rectangular().anchor = last;
+ else
+ sel.Rectangular().caret = last;
+ SetRectangularRange();
+ }
+}
+
+void Editor::CancelModes() {
+ sel.SetMoveExtends(false);
+}
+
+void Editor::NewLine() {
+ ClearSelection();
+ const char *eol = "\n";
+ if (pdoc->eolMode == SC_EOL_CRLF) {
+ eol = "\r\n";
+ } else if (pdoc->eolMode == SC_EOL_CR) {
+ eol = "\r";
+ } // else SC_EOL_LF -> "\n" already set
+ if (pdoc->InsertCString(sel.MainCaret(), eol)) {
+ SetEmptySelection(sel.MainCaret() + istrlen(eol));
+ while (*eol) {
+ NotifyChar(*eol);
+ if (recordingMacro) {
+ char txt[2];
+ txt[0] = *eol;
+ txt[1] = '\0';
+ NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(txt));
+ }
+ eol++;
+ }
+ }
+ SetLastXChosen();
+ SetScrollBars();
+ EnsureCaretVisible();
+ // Avoid blinking during rapid typing:
+ ShowCaretAtCurrentPosition();
+}
+
+void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
+ SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
+ if (sel.IsRectangular()) {
+ if (selt == Selection::noSel) {
+ caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start;
+ } else {
+ caretToUse = sel.Rectangular().caret;
+ }
+ }
+ Point pt = LocationFromPosition(caretToUse);
+ int lineDoc = pdoc->LineFromPosition(caretToUse.Position());
+ Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
+ int subLine = (pt.y - ptStartLine.y) / vs.lineHeight;
+ int commentLines = vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0;
+ SelectionPosition posNew = SPositionFromLocation(
+ Point(lastXChosen - xOffset, pt.y + direction * vs.lineHeight), false, false, UserVirtualSpace());
+ if ((direction > 0) && (subLine >= (cs.GetHeight(lineDoc) - 1 - commentLines))) {
+ posNew = SPositionFromLocation(
+ Point(lastXChosen - xOffset, pt.y + (commentLines + 1) * vs.lineHeight), false, false, UserVirtualSpace());
+ }
+ if (direction < 0) {
+ // Line wrapping may lead to a location on the same line, so
+ // seek back if that is the case.
+ // There is an equivalent case when moving down which skips
+ // over a line but as that does not trap the user it is fine.
+ Point ptNew = LocationFromPosition(posNew.Position());
+ while ((posNew.Position() > 0) && (pt.y == ptNew.y)) {
+ posNew.Add(- 1);
+ posNew.SetVirtualSpace(0);
+ ptNew = LocationFromPosition(posNew.Position());
+ }
+ }
+ MovePositionTo(posNew, selt);
+}
+
+void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) {
+ int lineDoc, savedPos = sel.MainCaret();
+ do {
+ MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt);
+ lineDoc = pdoc->LineFromPosition(sel.MainCaret());
+ if (direction > 0) {
+ if (sel.MainCaret() >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
+ if (selt == Selection::noSel) {
+ MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos)));
+ }
+ break;
+ }
+ }
+ } while (!cs.GetVisible(lineDoc));
+}
+
+int Editor::StartEndDisplayLine(int pos, bool start) {
+ RefreshStyleData();
+ int line = pdoc->LineFromPosition(pos);
+ AutoSurface surface(this);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line));
+ int posRet = INVALID_POSITION;
+ if (surface && ll) {
+ unsigned int posLineStart = pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, wrapWidth);
+ int posInLine = pos - posLineStart;
+ if (posInLine <= ll->maxLineLength) {
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ if (start) {
+ posRet = ll->LineStart(subLine) + posLineStart;
+ } else {
+ if (subLine == ll->lines - 1)
+ posRet = ll->LineStart(subLine + 1) + posLineStart;
+ else
+ posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
+ }
+ }
+ }
+ }
+ }
+ if (posRet == INVALID_POSITION) {
+ return pos;
+ } else {
+ return posRet;
+ }
+}
+
+int Editor::KeyCommand(unsigned int iMessage) {
+ switch (iMessage) {
+ case SCI_LINEDOWN:
+ CursorUpOrDown(1);
+ break;
+ case SCI_LINEDOWNEXTEND:
+ CursorUpOrDown(1, Selection::selStream);
+ break;
+ case SCI_LINEDOWNRECTEXTEND:
+ CursorUpOrDown(1, Selection::selRectangle);
+ break;
+ case SCI_PARADOWN:
+ ParaUpOrDown(1);
+ break;
+ case SCI_PARADOWNEXTEND:
+ ParaUpOrDown(1, Selection::selStream);
+ break;
+ case SCI_LINESCROLLDOWN:
+ ScrollTo(topLine + 1);
+ MoveCaretInsideView(false);
+ break;
+ case SCI_LINEUP:
+ CursorUpOrDown(-1);
+ break;
+ case SCI_LINEUPEXTEND:
+ CursorUpOrDown(-1, Selection::selStream);
+ break;
+ case SCI_LINEUPRECTEXTEND:
+ CursorUpOrDown(-1, Selection::selRectangle);
+ break;
+ case SCI_PARAUP:
+ ParaUpOrDown(-1);
+ break;
+ case SCI_PARAUPEXTEND:
+ ParaUpOrDown(-1, Selection::selStream);
+ break;
+ case SCI_LINESCROLLUP:
+ ScrollTo(topLine - 1);
+ MoveCaretInsideView(false);
+ break;
+ case SCI_CHARLEFT:
+ if (SelectionEmpty() || sel.MoveExtends()) {
+ if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret);
+ } else {
+ MovePositionTo(MovePositionSoVisible(
+ SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1));
+ }
+ } else {
+ MovePositionTo(sel.LimitsForRectangularElseMain().start);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARLEFTEXTEND:
+ if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret, Selection::selStream);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARLEFTRECTEXTEND:
+ if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ MovePositionTo(spCaret, Selection::selRectangle);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHT:
+ if (SelectionEmpty() || sel.MoveExtends()) {
+ if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret);
+ } else {
+ MovePositionTo(MovePositionSoVisible(
+ SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1));
+ }
+ } else {
+ MovePositionTo(sel.LimitsForRectangularElseMain().end);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHTEXTEND:
+ if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret, Selection::selStream);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_CHARRIGHTRECTEXTEND:
+ if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ SelectionPosition spCaret = sel.RangeMain().caret;
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ MovePositionTo(spCaret, Selection::selRectangle);
+ } else {
+ MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle);
+ }
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHT:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+
+ case SCI_WORDLEFTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDLEFTENDEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDRIGHTENDEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+
+ case SCI_HOME:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ SetLastXChosen();
+ break;
+ case SCI_HOMEEXTEND:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_HOMERECTEXTEND:
+ MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_LINEEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()));
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDEXTEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDRECTEXTEND:
+ MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_HOMEWRAP: {
+ SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (sel.RangeMain().caret <= homePos)
+ homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ MovePositionTo(homePos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_HOMEWRAPEXTEND: {
+ SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if (sel.RangeMain().caret <= homePos)
+ homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
+ MovePositionTo(homePos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEENDWRAP: {
+ SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
+ SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
+ if (endPos > realEndPos // if moved past visible EOLs
+ || sel.RangeMain().caret >= endPos) // if at end of display line already
+ endPos = realEndPos;
+ MovePositionTo(endPos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEENDWRAPEXTEND: {
+ SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
+ SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
+ if (endPos > realEndPos // if moved past visible EOLs
+ || sel.RangeMain().caret >= endPos) // if at end of display line already
+ endPos = realEndPos;
+ MovePositionTo(endPos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DOCUMENTSTART:
+ MovePositionTo(0);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTSTARTEXTEND:
+ MovePositionTo(0, Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTEND:
+ MovePositionTo(pdoc->Length());
+ SetLastXChosen();
+ break;
+ case SCI_DOCUMENTENDEXTEND:
+ MovePositionTo(pdoc->Length(), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_STUTTEREDPAGEUP:
+ PageMove(-1, Selection::noSel, true);
+ break;
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ PageMove(-1, Selection::selStream, true);
+ break;
+ case SCI_STUTTEREDPAGEDOWN:
+ PageMove(1, Selection::noSel, true);
+ break;
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+ PageMove(1, Selection::selStream, true);
+ break;
+ case SCI_PAGEUP:
+ PageMove(-1);
+ break;
+ case SCI_PAGEUPEXTEND:
+ PageMove(-1, Selection::selStream);
+ break;
+ case SCI_PAGEUPRECTEXTEND:
+ PageMove(-1, Selection::selRectangle);
+ break;
+ case SCI_PAGEDOWN:
+ PageMove(1);
+ break;
+ case SCI_PAGEDOWNEXTEND:
+ PageMove(1, Selection::selStream);
+ break;
+ case SCI_PAGEDOWNRECTEXTEND:
+ PageMove(1, Selection::selRectangle);
+ break;
+ case SCI_EDITTOGGLEOVERTYPE:
+ inOverstrike = !inOverstrike;
+ DropCaret();
+ ShowCaretAtCurrentPosition();
+ NotifyUpdateUI();
+ break;
+ case SCI_CANCEL: // Cancel any modes - handled in subclass
+ // Also unselect text
+ CancelModes();
+ break;
+ case SCI_DELETEBACK:
+ DelCharBack(true);
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+ case SCI_DELETEBACKNOTLINE:
+ DelCharBack(false);
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+ case SCI_TAB:
+ Indent(true);
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ ShowCaretAtCurrentPosition(); // Avoid blinking
+ break;
+ case SCI_BACKTAB:
+ Indent(false);
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ ShowCaretAtCurrentPosition(); // Avoid blinking
+ break;
+ case SCI_NEWLINE:
+ NewLine();
+ break;
+ case SCI_FORMFEED:
+ AddChar('\f');
+ break;
+ case SCI_VCHOME:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()));
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEEXTEND:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMERECTEXTEND:
+ MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle);
+ SetLastXChosen();
+ break;
+ case SCI_VCHOMEWRAP: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_VCHOMEWRAPEXTEND: {
+ SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
+ SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
+ if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
+ homePos = viewLineStart;
+
+ MovePositionTo(homePos, Selection::selStream);
+ SetLastXChosen();
+ }
+ break;
+ case SCI_ZOOMIN:
+ if (vs.zoomLevel < 20) {
+ vs.zoomLevel++;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ }
+ break;
+ case SCI_ZOOMOUT:
+ if (vs.zoomLevel > -10) {
+ vs.zoomLevel--;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ }
+ break;
+ case SCI_DELWORDLEFT: {
+ int startWord = pdoc->NextWordStart(sel.MainCaret(), -1);
+ pdoc->DeleteChars(startWord, sel.MainCaret() - startWord);
+ sel.RangeMain().ClearVirtualSpace();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DELWORDRIGHT: {
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ int endWord = pdoc->NextWordStart(sel.MainCaret(), 1);
+ pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
+ }
+ break;
+ case SCI_DELWORDRIGHTEND: {
+ UndoGroup ug(pdoc);
+ sel.RangeMain().caret = SelectionPosition(
+ InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
+ int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1);
+ pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
+ }
+ break;
+ case SCI_DELLINELEFT: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(line);
+ pdoc->DeleteChars(start, sel.MainCaret() - start);
+ sel.RangeMain().ClearVirtualSpace();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_DELLINERIGHT: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int end = pdoc->LineEnd(line);
+ pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret());
+ }
+ break;
+ case SCI_LINECOPY: {
+ int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
+ CopyRangeToClipboard(pdoc->LineStart(lineStart),
+ pdoc->LineStart(lineEnd + 1));
+ }
+ break;
+ case SCI_LINECUT: {
+ int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
+ int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
+ int start = pdoc->LineStart(lineStart);
+ int end = pdoc->LineStart(lineEnd + 1);
+ SetSelection(start, end);
+ Cut();
+ SetLastXChosen();
+ }
+ break;
+ case SCI_LINEDELETE: {
+ int line = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(line);
+ int end = pdoc->LineStart(line + 1);
+ pdoc->DeleteChars(start, end - start);
+ }
+ break;
+ case SCI_LINETRANSPOSE:
+ LineTranspose();
+ break;
+ case SCI_LINEDUPLICATE:
+ Duplicate(true);
+ break;
+ case SCI_SELECTIONDUPLICATE:
+ Duplicate(false);
+ break;
+ case SCI_LOWERCASE:
+ ChangeCaseOfSelection(cmLower);
+ break;
+ case SCI_UPPERCASE:
+ ChangeCaseOfSelection(cmUpper);
+ break;
+ case SCI_WORDPARTLEFT:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTLEFTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTRIGHT:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1));
+ SetLastXChosen();
+ break;
+ case SCI_WORDPARTRIGHTEXTEND:
+ MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_HOMEDISPLAY:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), true), -1));
+ SetLastXChosen();
+ break;
+ case SCI_HOMEDISPLAYEXTEND:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDDISPLAY:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), false), 1));
+ SetLastXChosen();
+ break;
+ case SCI_LINEENDDISPLAYEXTEND:
+ MovePositionTo(MovePositionSoVisible(
+ StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream);
+ SetLastXChosen();
+ break;
+ }
+ return 0;
+}
+
+int Editor::KeyDefault(int, int) {
+ return 0;
+}
+
+int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) {
+ DwellEnd(false);
+ int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+ (alt ? SCI_ALT : 0);
+ int msg = kmap.Find(key, modifiers);
+ if (msg) {
+ if (consumed)
+ *consumed = true;
+ return WndProc(msg, 0, 0);
+ } else {
+ if (consumed)
+ *consumed = false;
+ return KeyDefault(key, modifiers);
+ }
+}
+
+void Editor::SetWhitespaceVisible(int view) {
+ vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(view);
+}
+
+int Editor::GetWhitespaceVisible() {
+ return vs.viewWhitespace;
+}
+
+void Editor::Indent(bool forwards) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ int lineOfAnchor = pdoc->LineFromPosition(sel.Range(r).anchor.Position());
+ int caretPosition = sel.Range(r).caret.Position();
+ int lineCurrentPos = pdoc->LineFromPosition(caretPosition);
+ if (lineOfAnchor == lineCurrentPos) {
+ if (forwards) {
+ UndoGroup ug(pdoc);
+ pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
+ caretPosition = sel.Range(r).caret.Position();
+ if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
+ pdoc->tabIndents) {
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ if (pdoc->useTabs) {
+ pdoc->InsertChar(caretPosition, '\t');
+ sel.Range(r) = SelectionRange(caretPosition+1);
+ } else {
+ int numSpaces = (pdoc->tabInChars) -
+ (pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
+ if (numSpaces < 1)
+ numSpaces = pdoc->tabInChars;
+ for (int i = 0; i < numSpaces; i++) {
+ pdoc->InsertChar(caretPosition + i, ' ');
+ }
+ sel.Range(r) = SelectionRange(caretPosition+numSpaces);
+ }
+ }
+ } else {
+ if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
+ pdoc->tabIndents) {
+ UndoGroup ug(pdoc);
+ int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ int indentationStep = pdoc->IndentSize();
+ pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
+ sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
+ } else {
+ int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
+ pdoc->tabInChars;
+ if (newColumn < 0)
+ newColumn = 0;
+ int newPos = caretPosition;
+ while (pdoc->GetColumn(newPos) > newColumn)
+ newPos--;
+ sel.Range(r) = SelectionRange(newPos);
+ }
+ }
+ } else { // Multiline
+ int anchorPosOnLine = sel.Range(r).anchor.Position() - pdoc->LineStart(lineOfAnchor);
+ int currentPosPosOnLine = caretPosition - pdoc->LineStart(lineCurrentPos);
+ // Multiple lines selected so indent / dedent
+ int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
+ int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
+ if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
+ lineBottomSel--; // If not selecting any characters on a line, do not indent
+ {
+ UndoGroup ug(pdoc);
+ pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+ }
+ if (lineOfAnchor < lineCurrentPos) {
+ if (currentPosPosOnLine == 0)
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
+ } else {
+ if (anchorPosOnLine == 0)
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+ else
+ sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
+ }
+ }
+ }
+}
+
+class CaseFolderASCII : public CaseFolderTable {
+public:
+ CaseFolderASCII() {
+ StandardASCII();
+ }
+ ~CaseFolderASCII() {
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if (lenMixed > sizeFolded) {
+ return 0;
+ } else {
+ for (size_t i=0; i<lenMixed; i++) {
+ folded[i] = mapping[static_cast<unsigned char>(mixed[i])];
+ }
+ return lenMixed;
+ }
+ }
+};
+
+
+CaseFolder *Editor::CaseFolderForEncoding() {
+ // Simple default that only maps ASCII upper case to lower case.
+ return new CaseFolderASCII();
+}
+
+/**
+ * Search of a text in the document, in the given range.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::FindText(
+ uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
+ ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+ sptr_t lParam) { ///< @c TextToFind structure: The text to search for in the given range.
+
+ Sci_TextToFind *ft = reinterpret_cast<Sci_TextToFind *>(lParam);
+ int lengthFound = istrlen(ft->lpstrText);
+ std::auto_ptr<CaseFolder> pcf(CaseFolderForEncoding());
+ int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound,
+ pcf.get());
+ if (pos != -1) {
+ ft->chrgText.cpMin = pos;
+ ft->chrgText.cpMax = pos + lengthFound;
+ }
+ return pos;
+}
+
+/**
+ * Relocatable search support : Searches relative to current selection
+ * point and sets the selection to the found text range with
+ * each search.
+ */
+/**
+ * Anchor following searches at current selection start: This allows
+ * multiple incremental interactive searches to be macro recorded
+ * while still setting the selection to found text so the find/select
+ * operation is self-contained.
+ */
+void Editor::SearchAnchor() {
+ searchAnchor = SelectionStart().Position();
+}
+
+/**
+ * Find text from current search anchor: Must call @c SearchAnchor first.
+ * Used for next text and previous text requests.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::SearchText(
+ unsigned int iMessage, ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
+ uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
+ ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+ sptr_t lParam) { ///< The text to search for.
+
+ const char *txt = reinterpret_cast<char *>(lParam);
+ int pos;
+ int lengthFound = istrlen(txt);
+ std::auto_ptr<CaseFolder> pcf(CaseFolderForEncoding());
+ if (iMessage == SCI_SEARCHNEXT) {
+ pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound,
+ pcf.get());
+ } else {
+ pos = pdoc->FindText(searchAnchor, 0, txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ wParam,
+ &lengthFound,
+ pcf.get());
+ }
+ if (pos != -1) {
+ SetSelection(pos, pos + lengthFound);
+ }
+
+ return pos;
+}
+
+std::string Editor::CaseMapString(const std::string &s, int caseMapping) {
+ std::string ret(s);
+ for (size_t i=0; i<ret.size(); i++) {
+ switch (caseMapping) {
+ case cmUpper:
+ if (ret[i] >= 'a' && ret[i] <= 'z')
+ ret[i] = static_cast<char>(ret[i] - 'a' + 'A');
+ break;
+ case cmLower:
+ if (ret[i] >= 'A' && ret[i] <= 'Z')
+ ret[i] = static_cast<char>(ret[i] - 'A' + 'a');
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Search for text in the target range of the document.
+ * @return The position of the found text, -1 if not found.
+ */
+long Editor::SearchInTarget(const char *text, int length) {
+ int lengthFound = length;
+
+ std::auto_ptr<CaseFolder> pcf(CaseFolderForEncoding());
+ int pos = pdoc->FindText(targetStart, targetEnd, text,
+ (searchFlags & SCFIND_MATCHCASE) != 0,
+ (searchFlags & SCFIND_WHOLEWORD) != 0,
+ (searchFlags & SCFIND_WORDSTART) != 0,
+ (searchFlags & SCFIND_REGEXP) != 0,
+ searchFlags,
+ &lengthFound,
+ pcf.get());
+ if (pos != -1) {
+ targetStart = pos;
+ targetEnd = pos + lengthFound;
+ }
+ return pos;
+}
+
+void Editor::GoToLine(int lineNo) {
+ if (lineNo > pdoc->LinesTotal())
+ lineNo = pdoc->LinesTotal();
+ if (lineNo < 0)
+ lineNo = 0;
+ SetEmptySelection(pdoc->LineStart(lineNo));
+ ShowCaretAtCurrentPosition();
+ EnsureCaretVisible();
+}
+
+static bool Close(Point pt1, Point pt2) {
+ if (abs(pt1.x - pt2.x) > 3)
+ return false;
+ if (abs(pt1.y - pt2.y) > 3)
+ return false;
+ return true;
+}
+
+char *Editor::CopyRange(int start, int end) {
+ char *text = 0;
+ if (start < end) {
+ int len = end - start;
+ text = new char[len + 1];
+ for (int i = 0; i < len; i++) {
+ text[i] = pdoc->CharAt(start + i);
+ }
+ text[len] = '\0';
+ }
+ return text;
+}
+
+void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
+ if (sel.Empty()) {
+ if (allowLineCopy) {
+ int currentLine = pdoc->LineFromPosition(sel.MainCaret());
+ int start = pdoc->LineStart(currentLine);
+ int end = pdoc->LineEnd(currentLine);
+
+ char *text = CopyRange(start, end);
+ int textLen = text ? strlen(text) : 0;
+ // include room for \r\n\0
+ textLen += 3;
+ char *textWithEndl = new char[textLen];
+ textWithEndl[0] = '\0';
+ if (text)
+ strncat(textWithEndl, text, textLen);
+ if (pdoc->eolMode != SC_EOL_LF)
+ strncat(textWithEndl, "\r", textLen);
+ if (pdoc->eolMode != SC_EOL_CR)
+ strncat(textWithEndl, "\n", textLen);
+ ss->Set(textWithEndl, strlen(textWithEndl) + 1,
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true);
+ delete []text;
+ }
+ } else {
+ int delimiterLength = 0;
+ if (sel.selType == Selection::selRectangle) {
+ if (pdoc->eolMode == SC_EOL_CRLF) {
+ delimiterLength = 2;
+ } else {
+ delimiterLength = 1;
+ }
+ }
+ int size = sel.Length() + delimiterLength * sel.Count();
+ char *text = new char[size + 1];
+ int j = 0;
+ std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
+ if (sel.selType == Selection::selRectangle)
+ std::sort(rangesInOrder.begin(), rangesInOrder.end());
+ for (size_t r=0; r<rangesInOrder.size(); r++) {
+ SelectionRange current = rangesInOrder[r];
+ for (int i = current.Start().Position();
+ i < current.End().Position();
+ i++) {
+ text[j++] = pdoc->CharAt(i);
+ }
+ if (sel.selType == Selection::selRectangle) {
+ if (pdoc->eolMode != SC_EOL_LF) {
+ text[j++] = '\r';
+ }
+ if (pdoc->eolMode != SC_EOL_CR) {
+ text[j++] = '\n';
+ }
+ }
+ }
+ text[size] = '\0';
+ ss->Set(text, size + 1, pdoc->dbcsCodePage,
+ vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
+ }
+}
+
+void Editor::CopyRangeToClipboard(int start, int end) {
+ start = pdoc->ClampPositionIntoDocument(start);
+ end = pdoc->ClampPositionIntoDocument(end);
+ SelectionText selectedText;
+ selectedText.Set(CopyRange(start, end), end - start + 1,
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::CopyText(int length, const char *text) {
+ SelectionText selectedText;
+ selectedText.Copy(text, length + 1,
+ pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
+ CopyToClipboard(selectedText);
+}
+
+void Editor::SetDragPosition(SelectionPosition newPos) {
+ if (newPos.Position() >= 0) {
+ newPos = MovePositionOutsideChar(newPos, 1);
+ posDrop = newPos;
+ }
+ if (!(posDrag == newPos)) {
+ caret.on = true;
+ SetTicking(true);
+ InvalidateCaret();
+ posDrag = newPos;
+ InvalidateCaret();
+ }
+}
+
+void Editor::DisplayCursor(Window::Cursor c) {
+ if (cursorMode == SC_CURSORNORMAL)
+ wMain.SetCursor(c);
+ else
+ wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));
+}
+
+bool Editor::DragThreshold(Point ptStart, Point ptNow) {
+ int xMove = ptStart.x - ptNow.x;
+ int yMove = ptStart.y - ptNow.y;
+ int distanceSquared = xMove * xMove + yMove * yMove;
+ return distanceSquared > 16;
+}
+
+void Editor::StartDrag() {
+ // Always handled by subclasses
+ //SetMouseCapture(true);
+ //DisplayCursor(Window::cursorArrow);
+}
+
+void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) {
+ //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
+ if (inDragDrop == ddDragging)
+ dropWentOutside = false;
+
+ bool positionWasInSelection = PositionInSelection(position.Position());
+
+ bool positionOnEdgeOfSelection =
+ (position == SelectionStart()) || (position == SelectionEnd());
+
+ if ((inDragDrop != ddDragging) || !(positionWasInSelection) ||
+ (positionOnEdgeOfSelection && !moving)) {
+
+ SelectionPosition selStart = SelectionStart();
+ SelectionPosition selEnd = SelectionEnd();
+
+ UndoGroup ug(pdoc);
+
+ SelectionPosition positionAfterDeletion = position;
+ if ((inDragDrop == ddDragging) && moving) {
+ // Remove dragged out text
+ if (rectangular || sel.selType == Selection::selLines) {
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (position >= sel.Range(r).Start()) {
+ if (position > sel.Range(r).End()) {
+ positionAfterDeletion.Add(-sel.Range(r).Length());
+ } else {
+ positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length());
+ }
+ }
+ }
+ } else {
+ if (position > selStart) {
+ positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length());
+ }
+ }
+ ClearSelection();
+ }
+ position = positionAfterDeletion;
+
+ if (rectangular) {
+ PasteRectangular(position, value, istrlen(value));
+ // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
+ SetEmptySelection(position);
+ } else {
+ position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position());
+ position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace()));
+ if (pdoc->InsertCString(position.Position(), value)) {
+ SelectionPosition posAfterInsertion = position;
+ posAfterInsertion.Add(istrlen(value));
+ SetSelection(posAfterInsertion, position);
+ }
+ }
+ } else if (inDragDrop == ddDragging) {
+ SetEmptySelection(position);
+ }
+}
+
+/**
+ * @return true if given position is inside the selection,
+ */
+bool Editor::PositionInSelection(int pos) {
+ pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos);
+ for (size_t r=0; r<sel.Count(); r++) {
+ if (sel.Range(r).Contains(pos))
+ return true;
+ }
+ return false;
+}
+
+bool Editor::PointInSelection(Point pt) {
+ SelectionPosition pos = SPositionFromLocation(pt);
+ int xPos = XFromPosition(pos);
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionRange range = sel.Range(r);
+ if (range.Contains(pos)) {
+ bool hit = true;
+ if (pos == range.Start()) {
+ // see if just before selection
+ if (pt.x < xPos) {
+ hit = false;
+ }
+ }
+ if (pos == range.End()) {
+ // see if just after selection
+ if (pt.x > xPos) {
+ hit = false;
+ }
+ }
+ if (hit)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Editor::PointInSelMargin(Point pt) {
+ // Really means: "Point in a margin"
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
+ return rcSelMargin.Contains(pt);
+ } else {
+ return false;
+ }
+}
+
+void Editor::LineSelection(int lineCurrent_, int lineAnchor_) {
+ if (lineAnchor_ < lineCurrent_) {
+ SetSelection(pdoc->LineStart(lineCurrent_ + 1),
+ pdoc->LineStart(lineAnchor_));
+ } else if (lineAnchor_ > lineCurrent_) {
+ SetSelection(pdoc->LineStart(lineCurrent_),
+ pdoc->LineStart(lineAnchor_ + 1));
+ } else { // Same line, select it
+ SetSelection(pdoc->LineStart(lineAnchor_ + 1),
+ pdoc->LineStart(lineAnchor_));
+ }
+}
+
+void Editor::DwellEnd(bool mouseMoved) {
+ if (mouseMoved)
+ ticksToDwell = dwellDelay;
+ else
+ ticksToDwell = SC_TIME_FOREVER;
+ if (dwelling && (dwellDelay < SC_TIME_FOREVER)) {
+ dwelling = false;
+ NotifyDwelling(ptMouseLast, dwelling);
+ }
+}
+
+void Editor::MouseLeave() {
+ SetHotSpotRange(NULL);
+}
+
+static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) {
+ return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0)
+ || (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0));
+}
+
+void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+ //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
+ ptMouseLast = pt;
+ SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt));
+ newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
+ inDragDrop = ddNone;
+ sel.SetMoveExtends(false);
+
+ bool processed = NotifyMarginClick(pt, shift, ctrl, alt);
+ if (processed)
+ return;
+
+ NotifyIndicatorClick(true, newPos.Position(), shift, ctrl, alt);
+
+ bool inSelMargin = PointInSelMargin(pt);
+ if (shift & !inSelMargin) {
+ SetSelection(newPos.Position());
+ }
+ if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+ //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
+ SetMouseCapture(true);
+ SetEmptySelection(newPos.Position());
+ bool doubleClick = false;
+ // Stop mouse button bounce changing selection type
+ if (!Platform::MouseButtonBounce() || curTime != lastClickTime) {
+ if (selectionType == selChar) {
+ selectionType = selWord;
+ doubleClick = true;
+ } else if (selectionType == selWord) {
+ selectionType = selLine;
+ } else {
+ selectionType = selChar;
+ originalAnchorPos = sel.MainCaret();
+ }
+ }
+
+ if (selectionType == selWord) {
+ if (sel.MainCaret() >= originalAnchorPos) { // Moved forward
+ SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), 1),
+ pdoc->ExtendWordSelect(originalAnchorPos, -1));
+ } else { // Moved backward
+ SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), -1),
+ pdoc->ExtendWordSelect(originalAnchorPos, 1));
+ }
+ } else if (selectionType == selLine) {
+ lineAnchor = LineFromLocation(pt);
+ SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+ //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
+ } else {
+ SetEmptySelection(sel.MainCaret());
+ }
+ //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
+ if (doubleClick) {
+ NotifyDoubleClick(pt, shift, ctrl, alt);
+ if (PositionIsHotspot(newPos.Position()))
+ NotifyHotSpotDoubleClicked(newPos.Position(), shift, ctrl, alt);
+ }
+ } else { // Single click
+ if (inSelMargin) {
+ sel.selType = Selection::selStream;
+ if (ctrl) {
+ SelectAll();
+ lastClickTime = curTime;
+ return;
+ }
+ if (!shift) {
+ lineAnchor = LineFromLocation(pt);
+ // Single click in margin: select whole line
+ LineSelection(lineAnchor, lineAnchor);
+ SetSelection(pdoc->LineStart(lineAnchor + 1),
+ pdoc->LineStart(lineAnchor));
+ } else {
+ // Single shift+click in margin: select from line anchor to clicked line
+ if (sel.MainAnchor() > sel.MainCaret())
+ lineAnchor = pdoc->LineFromPosition(sel.MainAnchor() - 1);
+ else
+ lineAnchor = pdoc->LineFromPosition(sel.MainAnchor());
+ int lineStart = LineFromLocation(pt);
+ LineSelection(lineStart, lineAnchor);
+ //lineAnchor = lineStart; // Keep the same anchor for ButtonMove
+ }
+
+ SetDragPosition(SelectionPosition(invalidPosition));
+ SetMouseCapture(true);
+ selectionType = selLine;
+ } else {
+ if (PointIsHotspot(pt)) {
+ NotifyHotSpotClicked(newPos.Position(), shift, ctrl, alt);
+ }
+ if (!shift) {
+ if (PointInSelection(pt) && !SelectionEmpty())
+ inDragDrop = ddInitial;
+ else
+ inDragDrop = ddNone;
+ }
+ SetMouseCapture(true);
+ if (inDragDrop != ddInitial) {
+ SetDragPosition(SelectionPosition(invalidPosition));
+ if (!shift) {
+ if (ctrl && multipleSelection) {
+ SelectionRange range(newPos);
+ sel.TentativeSelection(range);
+ InvalidateSelection(range, true);
+ } else {
+ InvalidateSelection(SelectionRange(newPos), true);
+ if (sel.Count() > 1)
+ Redraw();
+ sel.Clear();
+ sel.selType = alt ? Selection::selRectangle : Selection::selStream;
+ SetSelection(newPos, newPos);
+ }
+ }
+ SelectionPosition anchorCurrent = newPos;
+ if (shift)
+ anchorCurrent = sel.IsRectangular() ?
+ sel.Rectangular().anchor : sel.RangeMain().anchor;
+ sel.selType = alt ? Selection::selRectangle : Selection::selStream;
+ selectionType = selChar;
+ originalAnchorPos = sel.MainCaret();
+ sel.Rectangular() = SelectionRange(newPos, anchorCurrent);
+ SetRectangularRange();
+ }
+ }
+ }
+ lastClickTime = curTime;
+ lastXChosen = pt.x + xOffset;
+ ShowCaretAtCurrentPosition();
+}
+
+bool Editor::PositionIsHotspot(int position) {
+ return vs.styles[pdoc->StyleAt(position) & pdoc->stylingBitsMask].hotspot;
+}
+
+bool Editor::PointIsHotspot(Point pt) {
+ int pos = PositionFromLocation(pt, true);
+ if (pos == INVALID_POSITION)
+ return false;
+ return PositionIsHotspot(pos);
+}
+
+void Editor::SetHotSpotRange(Point *pt) {
+ if (pt) {
+ int pos = PositionFromLocation(*pt);
+
+ // If we don't limit this to word characters then the
+ // range can encompass more than the run range and then
+ // the underline will not be drawn properly.
+ int hsStart_ = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine);
+ int hsEnd_ = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine);
+
+ // Only invalidate the range if the hotspot range has changed...
+ if (hsStart_ != hsStart || hsEnd_ != hsEnd) {
+ if (hsStart != -1) {
+ InvalidateRange(hsStart, hsEnd);
+ }
+ hsStart = hsStart_;
+ hsEnd = hsEnd_;
+ InvalidateRange(hsStart, hsEnd);
+ }
+ } else {
+ if (hsStart != -1) {
+ int hsStart_ = hsStart;
+ int hsEnd_ = hsEnd;
+ hsStart = -1;
+ hsEnd = -1;
+ InvalidateRange(hsStart_, hsEnd_);
+ } else {
+ hsStart = -1;
+ hsEnd = -1;
+ }
+ }
+}
+
+void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) {
+ hsStart_ = hsStart;
+ hsEnd_ = hsEnd;
+}
+
+void Editor::ButtonMove(Point pt) {
+ if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) {
+ DwellEnd(true);
+ }
+
+ SelectionPosition movePos = SPositionFromLocation(pt, false, false,
+ AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
+ movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());
+
+ if (inDragDrop == ddInitial) {
+ if (DragThreshold(ptMouseLast, pt)) {
+ SetMouseCapture(false);
+ SetDragPosition(movePos);
+ CopySelectionRange(&drag);
+ StartDrag();
+ }
+ return;
+ }
+
+ ptMouseLast = pt;
+ //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+ if (HaveMouseCapture()) {
+
+ // Slow down autoscrolling/selection
+ autoScrollTimer.ticksToWait -= timer.tickSize;
+ if (autoScrollTimer.ticksToWait > 0)
+ return;
+ autoScrollTimer.ticksToWait = autoScrollDelay;
+
+ // Adjust selection
+ if (posDrag.IsValid()) {
+ SetDragPosition(movePos);
+ } else {
+ if (selectionType == selChar) {
+ if (sel.IsRectangular()) {
+ sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor);
+ SetSelection(movePos, sel.RangeMain().anchor);
+ } else if (sel.Count() > 1) {
+ SelectionRange range(movePos, sel.RangeMain().anchor);
+ sel.TentativeSelection(range);
+ InvalidateSelection(range, true);
+ } else {
+ SetSelection(movePos, sel.RangeMain().anchor);
+ }
+ } else if (selectionType == selWord) {
+ // Continue selecting by word
+ if (movePos.Position() == originalAnchorPos) { // Didn't move
+ // No need to do anything. Previously this case was lumped
+ // in with "Moved forward", but that can be harmful in this
+ // case: a handler for the NotifyDoubleClick re-adjusts
+ // the selection for a fancier definition of "word" (for
+ // example, in Perl it is useful to include the leading
+ // '$', '%' or '@' on variables for word selection). In this
+ // the ButtonMove() called via Tick() for auto-scrolling
+ // could result in the fancier word selection adjustment
+ // being unmade.
+ } else if (movePos.Position() > originalAnchorPos) { // Moved forward
+ SetSelection(pdoc->ExtendWordSelect(movePos.Position(), 1),
+ pdoc->ExtendWordSelect(originalAnchorPos, -1));
+ } else { // Moved backward
+ SetSelection(pdoc->ExtendWordSelect(movePos.Position(), -1),
+ pdoc->ExtendWordSelect(originalAnchorPos, 1));
+ }
+ } else {
+ // Continue selecting by line
+ int lineMove = LineFromLocation(pt);
+ LineSelection(lineMove, lineAnchor);
+ }
+ }
+
+ // Autoscroll
+ PRectangle rcClient = GetClientRectangle();
+ if (pt.y > rcClient.bottom) {
+ int lineMove = cs.DisplayFromDoc(LineFromLocation(pt));
+ if (lineMove < 0) {
+ lineMove = cs.DisplayFromDoc(pdoc->LinesTotal() - 1);
+ }
+ ScrollTo(lineMove - LinesOnScreen() + 1);
+ Redraw();
+ } else if (pt.y < rcClient.top) {
+ int lineMove = cs.DisplayFromDoc(LineFromLocation(pt));
+ ScrollTo(lineMove - 1);
+ Redraw();
+ }
+ EnsureCaretVisible(false, false, true);
+
+ if (hsStart != -1 && !PositionIsHotspot(movePos.Position()))
+ SetHotSpotRange(NULL);
+
+ } else {
+ if (vs.fixedColumnWidth > 0) { // There is a margin
+ if (PointInSelMargin(pt)) {
+ DisplayCursor(Window::cursorReverseArrow);
+ SetHotSpotRange(NULL);
+ return; // No need to test for selection
+ }
+ }
+ // Display regular (drag) cursor over selection
+ if (PointInSelection(pt) && !SelectionEmpty()) {
+ DisplayCursor(Window::cursorArrow);
+ } else if (PointIsHotspot(pt)) {
+ DisplayCursor(Window::cursorHand);
+ SetHotSpotRange(&pt);
+ } else {
+ DisplayCursor(Window::cursorText);
+ SetHotSpotRange(NULL);
+ }
+ }
+}
+
+void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+ //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
+ SelectionPosition newPos = SPositionFromLocation(pt, false, false,
+ AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
+ newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
+ if (inDragDrop == ddInitial) {
+ inDragDrop = ddNone;
+ SetEmptySelection(newPos.Position());
+ }
+ if (HaveMouseCapture()) {
+ if (PointInSelMargin(pt)) {
+ DisplayCursor(Window::cursorReverseArrow);
+ } else {
+ DisplayCursor(Window::cursorText);
+ SetHotSpotRange(NULL);
+ }
+ ptMouseLast = pt;
+ SetMouseCapture(false);
+ NotifyIndicatorClick(false, newPos.Position(), false, false, false);
+ if (inDragDrop == ddDragging) {
+ SelectionPosition selStart = SelectionStart();
+ SelectionPosition selEnd = SelectionEnd();
+ if (selStart < selEnd) {
+ if (drag.len) {
+ if (ctrl) {
+ if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
+ SetSelection(newPos.Position(), newPos.Position() + drag.len);
+ }
+ } else if (newPos < selStart) {
+ pdoc->DeleteChars(selStart.Position(), drag.len);
+ if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
+ SetSelection(newPos.Position(), newPos.Position() + drag.len);
+ }
+ } else if (newPos > selEnd) {
+ pdoc->DeleteChars(selStart.Position(), drag.len);
+ newPos.Add(-drag.len);
+ if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
+ SetSelection(newPos.Position(), newPos.Position() + drag.len);
+ }
+ } else {
+ SetEmptySelection(newPos.Position());
+ }
+ drag.Free();
+ }
+ selectionType = selChar;
+ }
+ } else {
+ if (selectionType == selChar) {
+ if (sel.Count() > 1) {
+ sel.RangeMain() =
+ SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor);
+ InvalidateSelection(sel.RangeMain(), true);
+ } else {
+ SetSelection(newPos, sel.RangeMain().anchor);
+ }
+ }
+ sel.CommitTentative();
+ }
+ SetRectangularRange();
+ lastClickTime = curTime;
+ lastClick = pt;
+ lastXChosen = pt.x + xOffset;
+ if (sel.selType == Selection::selStream) {
+ SetLastXChosen();
+ }
+ inDragDrop = ddNone;
+ EnsureCaretVisible(false);
+ }
+}
+
+// Called frequently to perform background UI including
+// caret blinking and automatic scrolling.
+void Editor::Tick() {
+ if (HaveMouseCapture()) {
+ // Auto scroll
+ ButtonMove(ptMouseLast);
+ }
+ if (caret.period > 0) {
+ timer.ticksToWait -= timer.tickSize;
+ if (timer.ticksToWait <= 0) {
+ caret.on = !caret.on;
+ timer.ticksToWait = caret.period;
+ if (caret.active) {
+ InvalidateCaret();
+ }
+ }
+ }
+ if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
+ scrollWidth = lineWidthMaxSeen;
+ SetScrollBars();
+ }
+ if ((dwellDelay < SC_TIME_FOREVER) &&
+ (ticksToDwell > 0) &&
+ (!HaveMouseCapture())) {
+ ticksToDwell -= timer.tickSize;
+ if (ticksToDwell <= 0) {
+ dwelling = true;
+ NotifyDwelling(ptMouseLast, dwelling);
+ }
+ }
+}
+
+bool Editor::Idle() {
+
+ bool idleDone;
+
+ bool wrappingDone = wrapState == eWrapNone;
+
+ if (!wrappingDone) {
+ // Wrap lines during idle.
+ WrapLines(false, -1);
+ // No more wrapping
+ if (wrapStart == wrapEnd)
+ wrappingDone = true;
+ }
+
+ // Add more idle things to do here, but make sure idleDone is
+ // set correctly before the function returns. returning
+ // false will stop calling this idle funtion until SetIdle() is
+ // called again.
+
+ idleDone = wrappingDone; // && thatDone && theOtherThingDone...
+
+ return !idleDone;
+}
+
+void Editor::SetFocusState(bool focusState) {
+ hasFocus = focusState;
+ NotifyFocus(hasFocus);
+ if (hasFocus) {
+ ShowCaretAtCurrentPosition();
+ } else {
+ CancelModes();
+ DropCaret();
+ }
+}
+
+int Editor::PositionAfterArea(PRectangle rcArea) {
+ // The start of the document line after the display line after the area
+ // This often means that the line after a modification is restyled which helps
+ // detect multiline comment additions and heals single line comments
+ int lineAfter = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1;
+ if (lineAfter < cs.LinesDisplayed())
+ return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1);
+ else
+ return pdoc->Length();
+}
+
+// Style to a position within the view. If this causes a change at end of last line then
+// affects later lines so style all the viewed text.
+void Editor::StyleToPositionInView(Position pos) {
+ int endWindow = PositionAfterArea(GetClientRectangle());
+ if (pos > endWindow)
+ pos = endWindow;
+ int styleAtEnd = pdoc->StyleAt(pos-1);
+ pdoc->EnsureStyledTo(pos);
+ if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) {
+ // Style at end of line changed so is multi-line change like starting a comment
+ // so require rest of window to be styled.
+ pdoc->EnsureStyledTo(endWindow);
+ }
+}
+
+void Editor::IdleStyling() {
+ // Style the line after the modification as this allows modifications that change just the
+ // line of the modification to heal instead of propagating to the rest of the window.
+ StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(styleNeeded.upTo) + 2));
+
+ if (needUpdateUI) {
+ NotifyUpdateUI();
+ needUpdateUI = false;
+ }
+ styleNeeded.Reset();
+}
+
+void Editor::QueueStyling(int upTo) {
+ styleNeeded.NeedUpTo(upTo);
+}
+
+bool Editor::PaintContains(PRectangle rc) {
+ if (rc.Empty()) {
+ return true;
+ } else {
+ return rcPaint.Contains(rc);
+ }
+}
+
+bool Editor::PaintContainsMargin() {
+ PRectangle rcSelMargin = GetClientRectangle();
+ rcSelMargin.right = vs.fixedColumnWidth;
+ return PaintContains(rcSelMargin);
+}
+
+void Editor::CheckForChangeOutsidePaint(Range r) {
+ if (paintState == painting && !paintingAllText) {
+ //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
+ if (!r.Valid())
+ return;
+
+ PRectangle rcRange = RectangleFromRange(r.start, r.end);
+ PRectangle rcText = GetTextRectangle();
+ if (rcRange.top < rcText.top) {
+ rcRange.top = rcText.top;
+ }
+ if (rcRange.bottom > rcText.bottom) {
+ rcRange.bottom = rcText.bottom;
+ }
+
+ if (!PaintContains(rcRange)) {
+ AbandonPaint();
+ }
+ }
+}
+
+void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
+ if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
+ if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[0]));
+ CheckForChangeOutsidePaint(Range(pos0));
+ braces[0] = pos0;
+ }
+ if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
+ CheckForChangeOutsidePaint(Range(braces[1]));
+ CheckForChangeOutsidePaint(Range(pos1));
+ braces[1] = pos1;
+ }
+ bracesMatchStyle = matchStyle;
+ if (paintState == notPainting) {
+ Redraw();
+ }
+ }
+}
+
+void Editor::SetAnnotationHeights(int start, int end) {
+ if (vs.annotationVisible) {
+ for (int line=start; line<end; line++) {
+ cs.SetHeight(line, pdoc->AnnotationLines(line) + 1);
+ }
+ }
+}
+
+void Editor::SetDocPointer(Document *document) {
+ //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
+ pdoc->RemoveWatcher(this, 0);
+ pdoc->Release();
+ if (document == NULL) {
+ pdoc = new Document();
+ } else {
+ pdoc = document;
+ }
+ pdoc->AddRef();
+
+ // Ensure all positions within document
+ sel.Clear();
+ targetStart = 0;
+ targetEnd = 0;
+
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+
+ // Reset the contraction state to fully shown.
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
+ llc.Deallocate();
+ NeedWrapping();
+
+ pdoc->AddWatcher(this, 0);
+ SetScrollBars();
+ Redraw();
+}
+
+void Editor::SetAnnotationVisible(int visible) {
+ if (vs.annotationVisible != visible) {
+ bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
+ vs.annotationVisible = visible;
+ if (changedFromOrToHidden) {
+ int dir = vs.annotationVisible ? 1 : -1;
+ for (int line=0; line<pdoc->LinesTotal(); line++) {
+ int annotationLines = pdoc->AnnotationLines(line);
+ if (annotationLines > 0) {
+ cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
+ */
+void Editor::Expand(int &line, bool doExpand) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ line++;
+ while (line <= lineMaxSubord) {
+ if (doExpand)
+ cs.SetVisible(line, line, true);
+ int level = pdoc->GetLevel(line);
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (doExpand && cs.GetExpanded(line)) {
+ Expand(line, true);
+ } else {
+ Expand(line, false);
+ }
+ } else {
+ line++;
+ }
+ }
+}
+
+void Editor::ToggleContraction(int line) {
+ if (line >= 0) {
+ if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
+ line = pdoc->GetFoldParent(line);
+ if (line < 0)
+ return;
+ }
+
+ if (cs.GetExpanded(line)) {
+ int lineMaxSubord = pdoc->GetLastChild(line);
+ cs.SetExpanded(line, 0);
+ if (lineMaxSubord > line) {
+ cs.SetVisible(line + 1, lineMaxSubord, false);
+
+ int lineCurrent = pdoc->LineFromPosition(sel.MainCaret());
+ if (lineCurrent > line && lineCurrent <= lineMaxSubord) {
+ // This does not re-expand the fold
+ EnsureCaretVisible();
+ }
+
+ SetScrollBars();
+ Redraw();
+ }
+
+ } else {
+ if (!(cs.GetVisible(line))) {
+ EnsureLineVisible(line, false);
+ GoToLine(line);
+ }
+ cs.SetExpanded(line, 1);
+ Expand(line, true);
+ SetScrollBars();
+ Redraw();
+ }
+ }
+}
+
+/**
+ * Recurse up from this line to find any folds that prevent this line from being visible
+ * and unfold them all.
+ */
+void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
+
+ // In case in need of wrapping to ensure DisplayFromDoc works.
+ WrapLines(true, -1);
+
+ if (!cs.GetVisible(lineDoc)) {
+ int lineParent = pdoc->GetFoldParent(lineDoc);
+ if (lineParent >= 0) {
+ if (lineDoc != lineParent)
+ EnsureLineVisible(lineParent, enforcePolicy);
+ if (!cs.GetExpanded(lineParent)) {
+ cs.SetExpanded(lineParent, 1);
+ Expand(lineParent, true);
+ }
+ }
+ SetScrollBars();
+ Redraw();
+ }
+ if (enforcePolicy) {
+ int lineDisplay = cs.DisplayFromDoc(lineDoc);
+ if (visiblePolicy & VISIBLE_SLOP) {
+ if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) {
+ SetTopLine(Platform::Clamp(lineDisplay - visibleSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ } else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
+ ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
+ SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ } else {
+ if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) {
+ SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
+ SetVerticalScrollPos();
+ Redraw();
+ }
+ }
+ }
+}
+
+int Editor::GetTag(char *tagValue, int tagNumber) {
+ char name[3] = "\\?";
+ const char *text = 0;
+ int length = 0;
+ if ((tagNumber >= 1) && (tagNumber <= 9)) {
+ name[1] = static_cast<char>(tagNumber + '0');
+ length = 2;
+ text = pdoc->SubstituteByPosition(name, &length);
+ }
+ if (tagValue) {
+ if (text)
+ memcpy(tagValue, text, length + 1);
+ else
+ *tagValue = '\0';
+ }
+ return length;
+}
+
+int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
+ UndoGroup ug(pdoc);
+ if (length == -1)
+ length = istrlen(text);
+ if (replacePatterns) {
+ text = pdoc->SubstituteByPosition(text, &length);
+ if (!text) {
+ return 0;
+ }
+ }
+ if (targetStart != targetEnd)
+ pdoc->DeleteChars(targetStart, targetEnd - targetStart);
+ targetEnd = targetStart;
+ pdoc->InsertString(targetStart, text, length);
+ targetEnd = targetStart + length;
+ return length;
+}
+
+bool Editor::IsUnicodeMode() const {
+ return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage);
+}
+
+int Editor::CodePage() const {
+ if (pdoc)
+ return pdoc->dbcsCodePage;
+ else
+ 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;
+ }
+}
+
+void Editor::AddStyledText(char *buffer, int appendLength) {
+ // The buffer consists of alternating character bytes and style bytes
+ size_t textLength = appendLength / 2;
+ char *text = new char[textLength];
+ size_t i;
+ for (i = 0; i < textLength; i++) {
+ text[i] = buffer[i*2];
+ }
+ pdoc->InsertString(CurrentPosition(), text, textLength);
+ for (i = 0; i < textLength; i++) {
+ text[i] = buffer[i*2+1];
+ }
+ pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
+ pdoc->SetStyles(textLength, text);
+ delete []text;
+ SetEmptySelection(sel.MainCaret() + textLength);
+}
+
+static bool ValidMargin(unsigned long wParam) {
+ return wParam < ViewStyle::margins;
+}
+
+static char *CharPtrFromSPtr(sptr_t lParam) {
+ return reinterpret_cast<char *>(lParam);
+}
+
+void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ vs.EnsureStyle(wParam);
+ switch (iMessage) {
+ case SCI_STYLESETFORE:
+ vs.styles[wParam].fore.desired = ColourDesired(lParam);
+ break;
+ case SCI_STYLESETBACK:
+ vs.styles[wParam].back.desired = ColourDesired(lParam);
+ break;
+ case SCI_STYLESETBOLD:
+ vs.styles[wParam].bold = lParam != 0;
+ break;
+ case SCI_STYLESETITALIC:
+ vs.styles[wParam].italic = lParam != 0;
+ break;
+ case SCI_STYLESETEOLFILLED:
+ vs.styles[wParam].eolFilled = lParam != 0;
+ break;
+ case SCI_STYLESETSIZE:
+ vs.styles[wParam].size = lParam;
+ break;
+ case SCI_STYLESETFONT:
+ if (lParam != 0) {
+ vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
+ }
+ break;
+ case SCI_STYLESETUNDERLINE:
+ vs.styles[wParam].underline = lParam != 0;
+ break;
+ case SCI_STYLESETCASE:
+ vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
+ break;
+ case SCI_STYLESETCHARACTERSET:
+ vs.styles[wParam].characterSet = lParam;
+ break;
+ case SCI_STYLESETVISIBLE:
+ vs.styles[wParam].visible = lParam != 0;
+ break;
+ case SCI_STYLESETCHANGEABLE:
+ vs.styles[wParam].changeable = lParam != 0;
+ break;
+ case SCI_STYLESETHOTSPOT:
+ vs.styles[wParam].hotspot = lParam != 0;
+ break;
+ }
+ InvalidateStyleRedraw();
+}
+
+sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ vs.EnsureStyle(wParam);
+ switch (iMessage) {
+ case SCI_STYLEGETFORE:
+ return vs.styles[wParam].fore.desired.AsLong();
+ case SCI_STYLEGETBACK:
+ return vs.styles[wParam].back.desired.AsLong();
+ case SCI_STYLEGETBOLD:
+ return vs.styles[wParam].bold ? 1 : 0;
+ case SCI_STYLEGETITALIC:
+ return vs.styles[wParam].italic ? 1 : 0;
+ case SCI_STYLEGETEOLFILLED:
+ return vs.styles[wParam].eolFilled ? 1 : 0;
+ case SCI_STYLEGETSIZE:
+ return vs.styles[wParam].size;
+ case SCI_STYLEGETFONT:
+ if (!vs.styles[wParam].fontName)
+ return 0;
+ if (lParam != 0)
+ strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
+ return strlen(vs.styles[wParam].fontName);
+ case SCI_STYLEGETUNDERLINE:
+ return vs.styles[wParam].underline ? 1 : 0;
+ case SCI_STYLEGETCASE:
+ return static_cast<int>(vs.styles[wParam].caseForce);
+ case SCI_STYLEGETCHARACTERSET:
+ return vs.styles[wParam].characterSet;
+ case SCI_STYLEGETVISIBLE:
+ return vs.styles[wParam].visible ? 1 : 0;
+ case SCI_STYLEGETCHANGEABLE:
+ return vs.styles[wParam].changeable ? 1 : 0;
+ case SCI_STYLEGETHOTSPOT:
+ return vs.styles[wParam].hotspot ? 1 : 0;
+ }
+ return 0;
+}
+
+sptr_t Editor::StringResult(sptr_t lParam, const char *val) {
+ const int n = strlen(val);
+ if (lParam != 0) {
+ char *ptr = reinterpret_cast<char *>(lParam);
+ strcpy(ptr, val);
+ }
+ return n; // Not including NUL
+}
+
+sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+
+ // Optional macro recording hook
+ if (recordingMacro)
+ NotifyMacroRecord(iMessage, wParam, lParam);
+
+ switch (iMessage) {
+
+ case SCI_GETTEXT: {
+ if (lParam == 0)
+ return pdoc->Length() + 1;
+ if (wParam == 0)
+ return 0;
+ char *ptr = CharPtrFromSPtr(lParam);
+ unsigned int iChar = 0;
+ for (; iChar < wParam - 1; iChar++)
+ ptr[iChar] = pdoc->CharAt(iChar);
+ ptr[iChar] = '\0';
+ return iChar;
+ }
+
+ case SCI_SETTEXT: {
+ if (lParam == 0)
+ return 0;
+ UndoGroup ug(pdoc);
+ pdoc->DeleteChars(0, pdoc->Length());
+ SetEmptySelection(0);
+ pdoc->InsertCString(0, CharPtrFromSPtr(lParam));
+ return 1;
+ }
+
+ case SCI_GETTEXTLENGTH:
+ return pdoc->Length();
+
+ case SCI_CUT:
+ Cut();
+ SetLastXChosen();
+ break;
+
+ case SCI_COPY:
+ Copy();
+ break;
+
+ case SCI_COPYALLOWLINE:
+ CopyAllowLine();
+ break;
+
+ case SCI_COPYRANGE:
+ CopyRangeToClipboard(wParam, lParam);
+ break;
+
+ case SCI_COPYTEXT:
+ CopyText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_PASTE:
+ Paste();
+ if (!caretSticky) {
+ SetLastXChosen();
+ }
+ EnsureCaretVisible();
+ break;
+
+ case SCI_CLEAR:
+ Clear();
+ SetLastXChosen();
+ EnsureCaretVisible();
+ break;
+
+ case SCI_UNDO:
+ Undo();
+ SetLastXChosen();
+ break;
+
+ case SCI_CANUNDO:
+ return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
+
+ case SCI_EMPTYUNDOBUFFER:
+ pdoc->DeleteUndoHistory();
+ return 0;
+
+ case SCI_GETFIRSTVISIBLELINE:
+ return topLine;
+
+ case SCI_SETFIRSTVISIBLELINE:
+ ScrollTo(wParam);
+ break;
+
+ case SCI_GETLINE: { // Risk of overwriting the end of the buffer
+ int lineStart = pdoc->LineStart(wParam);
+ int lineEnd = pdoc->LineStart(wParam + 1);
+ if (lParam == 0) {
+ return lineEnd - lineStart;
+ }
+ char *ptr = CharPtrFromSPtr(lParam);
+ int iPlace = 0;
+ for (int iChar = lineStart; iChar < lineEnd; iChar++) {
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ }
+ return iPlace;
+ }
+
+ case SCI_GETLINECOUNT:
+ if (pdoc->LinesTotal() == 0)
+ return 1;
+ else
+ return pdoc->LinesTotal();
+
+ case SCI_GETMODIFY:
+ return !pdoc->IsSavePoint();
+
+ case SCI_SETSEL: {
+ int nStart = static_cast<int>(wParam);
+ int nEnd = static_cast<int>(lParam);
+ if (nEnd < 0)
+ nEnd = pdoc->Length();
+ if (nStart < 0)
+ nStart = nEnd; // Remove selection
+ InvalidateSelection(SelectionRange(nStart, nEnd));
+ sel.Clear();
+ sel.selType = Selection::selStream;
+ SetSelection(nEnd, nStart);
+ EnsureCaretVisible();
+ }
+ break;
+
+ case SCI_GETSELTEXT: {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ if (lParam == 0) {
+ return selectedText.len ? selectedText.len : 1;
+ } else {
+ char *ptr = CharPtrFromSPtr(lParam);
+ int iChar = 0;
+ if (selectedText.len) {
+ for (; iChar < selectedText.len; iChar++)
+ ptr[iChar] = selectedText.s[iChar];
+ } else {
+ ptr[0] = '\0';
+ }
+ return iChar;
+ }
+ }
+
+ case SCI_LINEFROMPOSITION:
+ if (static_cast<int>(wParam) < 0)
+ return 0;
+ return pdoc->LineFromPosition(wParam);
+
+ case SCI_POSITIONFROMLINE:
+ if (static_cast<int>(wParam) < 0)
+ wParam = pdoc->LineFromPosition(SelectionStart().Position());
+ if (wParam == 0)
+ return 0; // Even if there is no text, there is a first line that starts at 0
+ if (static_cast<int>(wParam) > pdoc->LinesTotal())
+ return -1;
+ //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
+ // return -1;
+ return pdoc->LineStart(wParam);
+
+ // Replacement of the old Scintilla interpretation of EM_LINELENGTH
+ case SCI_LINELENGTH:
+ if ((static_cast<int>(wParam) < 0) ||
+ (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
+ return 0;
+ return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
+
+ case SCI_REPLACESEL: {
+ if (lParam == 0)
+ return 0;
+ UndoGroup ug(pdoc);
+ ClearSelection();
+ char *replacement = CharPtrFromSPtr(lParam);
+ pdoc->InsertCString(sel.MainCaret(), replacement);
+ SetEmptySelection(sel.MainCaret() + istrlen(replacement));
+ EnsureCaretVisible();
+ }
+ break;
+
+ case SCI_SETTARGETSTART:
+ targetStart = wParam;
+ break;
+
+ case SCI_GETTARGETSTART:
+ return targetStart;
+
+ case SCI_SETTARGETEND:
+ targetEnd = wParam;
+ break;
+
+ case SCI_GETTARGETEND:
+ return targetEnd;
+
+ case SCI_TARGETFROMSELECTION:
+ if (sel.MainCaret() < sel.MainAnchor()) {
+ targetStart = sel.MainCaret();
+ targetEnd = sel.MainAnchor();
+ } else {
+ targetStart = sel.MainAnchor();
+ targetEnd = sel.MainCaret();
+ }
+ break;
+
+ case SCI_REPLACETARGET:
+ PLATFORM_ASSERT(lParam);
+ return ReplaceTarget(false, CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_REPLACETARGETRE:
+ PLATFORM_ASSERT(lParam);
+ return ReplaceTarget(true, CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_SEARCHINTARGET:
+ PLATFORM_ASSERT(lParam);
+ return SearchInTarget(CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_SETSEARCHFLAGS:
+ searchFlags = wParam;
+ break;
+
+ case SCI_GETSEARCHFLAGS:
+ return searchFlags;
+
+ case SCI_GETTAG:
+ return GetTag(CharPtrFromSPtr(lParam), wParam);
+
+ case SCI_POSITIONBEFORE:
+ return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);
+
+ case SCI_POSITIONAFTER:
+ return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);
+
+ case SCI_LINESCROLL:
+ ScrollTo(topLine + lParam);
+ HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
+ return 1;
+
+ case SCI_SETXOFFSET:
+ xOffset = wParam;
+ SetHorizontalScrollPos();
+ Redraw();
+ break;
+
+ case SCI_GETXOFFSET:
+ return xOffset;
+
+ case SCI_CHOOSECARETX:
+ SetLastXChosen();
+ break;
+
+ case SCI_SCROLLCARET:
+ EnsureCaretVisible();
+ break;
+
+ case SCI_SETREADONLY:
+ pdoc->SetReadOnly(wParam != 0);
+ return 1;
+
+ case SCI_GETREADONLY:
+ return pdoc->IsReadOnly();
+
+ case SCI_CANPASTE:
+ return CanPaste();
+
+ case SCI_POINTXFROMPOSITION:
+ if (lParam < 0) {
+ return 0;
+ } else {
+ Point pt = LocationFromPosition(lParam);
+ return pt.x;
+ }
+
+ case SCI_POINTYFROMPOSITION:
+ if (lParam < 0) {
+ return 0;
+ } else {
+ Point pt = LocationFromPosition(lParam);
+ return pt.y;
+ }
+
+ case SCI_FINDTEXT:
+ return FindText(wParam, lParam);
+
+ case SCI_GETTEXTRANGE: {
+ if (lParam == 0)
+ return 0;
+ Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
+ int cpMax = tr->chrg.cpMax;
+ if (cpMax == -1)
+ cpMax = pdoc->Length();
+ PLATFORM_ASSERT(cpMax <= pdoc->Length());
+ int len = cpMax - tr->chrg.cpMin; // No -1 as cpMin and cpMax are referring to inter character positions
+ pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+ // Spec says copied text is terminated with a NUL
+ tr->lpstrText[len] = '\0';
+ return len; // Not including NUL
+ }
+
+ case SCI_HIDESELECTION:
+ hideSelection = wParam != 0;
+ Redraw();
+ break;
+
+ case SCI_FORMATRANGE:
+ return FormatRange(wParam != 0, reinterpret_cast<Sci_RangeToFormat *>(lParam));
+
+ case SCI_GETMARGINLEFT:
+ return vs.leftMarginWidth;
+
+ case SCI_GETMARGINRIGHT:
+ return vs.rightMarginWidth;
+
+ case SCI_SETMARGINLEFT:
+ vs.leftMarginWidth = lParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETMARGINRIGHT:
+ vs.rightMarginWidth = lParam;
+ InvalidateStyleRedraw();
+ break;
+
+ // Control specific mesages
+
+ case SCI_ADDTEXT: {
+ if (lParam == 0)
+ return 0;
+ pdoc->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam), wParam);
+ SetEmptySelection(sel.MainCaret() + wParam);
+ return 0;
+ }
+
+ case SCI_ADDSTYLEDTEXT:
+ if (lParam)
+ AddStyledText(CharPtrFromSPtr(lParam), wParam);
+ return 0;
+
+ case SCI_INSERTTEXT: {
+ if (lParam == 0)
+ return 0;
+ int insertPos = wParam;
+ if (static_cast<int>(wParam) == -1)
+ insertPos = CurrentPosition();
+ int newCurrent = CurrentPosition();
+ char *sz = CharPtrFromSPtr(lParam);
+ pdoc->InsertCString(insertPos, sz);
+ if (newCurrent > insertPos)
+ newCurrent += istrlen(sz);
+ SetEmptySelection(newCurrent);
+ return 0;
+ }
+
+ case SCI_APPENDTEXT:
+ pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), wParam);
+ return 0;
+
+ case SCI_CLEARALL:
+ ClearAll();
+ return 0;
+
+ case SCI_CLEARDOCUMENTSTYLE:
+ ClearDocumentStyle();
+ return 0;
+
+ case SCI_SETUNDOCOLLECTION:
+ pdoc->SetUndoCollection(wParam != 0);
+ return 0;
+
+ case SCI_GETUNDOCOLLECTION:
+ return pdoc->IsCollectingUndo();
+
+ case SCI_BEGINUNDOACTION:
+ pdoc->BeginUndoAction();
+ return 0;
+
+ case SCI_ENDUNDOACTION:
+ pdoc->EndUndoAction();
+ return 0;
+
+ case SCI_GETCARETPERIOD:
+ return caret.period;
+
+ case SCI_SETCARETPERIOD:
+ caret.period = wParam;
+ break;
+
+ case SCI_SETWORDCHARS: {
+ pdoc->SetDefaultCharClasses(false);
+ if (lParam == 0)
+ return 0;
+ pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccWord);
+ }
+ break;
+
+ case SCI_SETWHITESPACECHARS: {
+ if (lParam == 0)
+ return 0;
+ pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccSpace);
+ }
+ break;
+
+ case SCI_SETCHARSDEFAULT:
+ pdoc->SetDefaultCharClasses(true);
+ break;
+
+ case SCI_GETLENGTH:
+ return pdoc->Length();
+
+ case SCI_ALLOCATE:
+ pdoc->Allocate(wParam);
+ break;
+
+ case SCI_GETCHARAT:
+ return pdoc->CharAt(wParam);
+
+ case SCI_SETCURRENTPOS:
+ if (sel.IsRectangular()) {
+ sel.Rectangular().caret.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ } else {
+ SetSelection(wParam, sel.MainAnchor());
+ }
+ break;
+
+ case SCI_GETCURRENTPOS:
+ return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();
+
+ case SCI_SETANCHOR:
+ if (sel.IsRectangular()) {
+ sel.Rectangular().anchor.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ } else {
+ SetSelection(sel.MainCaret(), wParam);
+ }
+ break;
+
+ case SCI_GETANCHOR:
+ return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();
+
+ case SCI_SETSELECTIONSTART:
+ SetSelection(Platform::Maximum(sel.MainCaret(), wParam), wParam);
+ break;
+
+ case SCI_GETSELECTIONSTART:
+ return sel.LimitsForRectangularElseMain().start.Position();
+
+ case SCI_SETSELECTIONEND:
+ SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam));
+ break;
+
+ case SCI_GETSELECTIONEND:
+ return sel.LimitsForRectangularElseMain().end.Position();
+
+ case SCI_SETPRINTMAGNIFICATION:
+ printMagnification = wParam;
+ break;
+
+ case SCI_GETPRINTMAGNIFICATION:
+ return printMagnification;
+
+ case SCI_SETPRINTCOLOURMODE:
+ printColourMode = wParam;
+ break;
+
+ case SCI_GETPRINTCOLOURMODE:
+ return printColourMode;
+
+ case SCI_SETPRINTWRAPMODE:
+ printWrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
+ break;
+
+ case SCI_GETPRINTWRAPMODE:
+ return printWrapState;
+
+ case SCI_GETSTYLEAT:
+ if (static_cast<int>(wParam) >= pdoc->Length())
+ return 0;
+ else
+ return pdoc->StyleAt(wParam);
+
+ case SCI_REDO:
+ Redo();
+ break;
+
+ case SCI_SELECTALL:
+ SelectAll();
+ break;
+
+ case SCI_SETSAVEPOINT:
+ pdoc->SetSavePoint();
+ break;
+
+ case SCI_GETSTYLEDTEXT: {
+ if (lParam == 0)
+ return 0;
+ Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
+ int iPlace = 0;
+ for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
+ tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
+ tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
+ }
+ tr->lpstrText[iPlace] = '\0';
+ tr->lpstrText[iPlace + 1] = '\0';
+ return iPlace;
+ }
+
+ case SCI_CANREDO:
+ return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
+
+ case SCI_MARKERLINEFROMHANDLE:
+ return pdoc->LineFromHandle(wParam);
+
+ case SCI_MARKERDELETEHANDLE:
+ pdoc->DeleteMarkFromHandle(wParam);
+ break;
+
+ case SCI_GETVIEWWS:
+ return vs.viewWhitespace;
+
+ case SCI_SETVIEWWS:
+ vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETWHITESPACESIZE:
+ return vs.whitespaceSize;
+
+ case SCI_SETWHITESPACESIZE:
+ vs.whitespaceSize = static_cast<int>(wParam);
+ Redraw();
+ break;
+
+ case SCI_POSITIONFROMPOINT:
+ return PositionFromLocation(Point(wParam, lParam), false, false);
+
+ case SCI_POSITIONFROMPOINTCLOSE:
+ return PositionFromLocation(Point(wParam, lParam), true, false);
+
+ case SCI_CHARPOSITIONFROMPOINT:
+ return PositionFromLocation(Point(wParam, lParam), false, true);
+
+ case SCI_CHARPOSITIONFROMPOINTCLOSE:
+ return PositionFromLocation(Point(wParam, lParam), true, true);
+
+ case SCI_GOTOLINE:
+ GoToLine(wParam);
+ break;
+
+ case SCI_GOTOPOS:
+ SetEmptySelection(wParam);
+ EnsureCaretVisible();
+ Redraw();
+ break;
+
+ case SCI_GETCURLINE: {
+ int lineCurrentPos = pdoc->LineFromPosition(sel.MainCaret());
+ int lineStart = pdoc->LineStart(lineCurrentPos);
+ unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
+ 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++) {
+ ptr[iPlace++] = pdoc->CharAt(iChar);
+ }
+ ptr[iPlace] = '\0';
+ return sel.MainCaret() - lineStart;
+ }
+
+ case SCI_GETENDSTYLED:
+ return pdoc->GetEndStyled();
+
+ case SCI_GETEOLMODE:
+ return pdoc->eolMode;
+
+ case SCI_SETEOLMODE:
+ pdoc->eolMode = wParam;
+ break;
+
+ case SCI_STARTSTYLING:
+ pdoc->StartStyling(wParam, static_cast<char>(lParam));
+ break;
+
+ case SCI_SETSTYLING:
+ pdoc->SetStyleFor(wParam, static_cast<char>(lParam));
+ break;
+
+ case SCI_SETSTYLINGEX: // Specify a complete styling buffer
+ if (lParam == 0)
+ return 0;
+ pdoc->SetStyles(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_SETBUFFEREDDRAW:
+ bufferedDraw = wParam != 0;
+ break;
+
+ case SCI_GETBUFFEREDDRAW:
+ return bufferedDraw;
+
+ case SCI_GETTWOPHASEDRAW:
+ return twoPhaseDraw;
+
+ case SCI_SETTWOPHASEDRAW:
+ twoPhaseDraw = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETFONTQUALITY:
+ vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
+ vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETFONTQUALITY:
+ return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);
+
+ case SCI_SETTABWIDTH:
+ if (wParam > 0) {
+ pdoc->tabInChars = wParam;
+ if (pdoc->indentInChars == 0)
+ pdoc->actualIndentInChars = pdoc->tabInChars;
+ }
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETTABWIDTH:
+ return pdoc->tabInChars;
+
+ case SCI_SETINDENT:
+ pdoc->indentInChars = wParam;
+ if (pdoc->indentInChars != 0)
+ pdoc->actualIndentInChars = pdoc->indentInChars;
+ else
+ pdoc->actualIndentInChars = pdoc->tabInChars;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETINDENT:
+ return pdoc->indentInChars;
+
+ case SCI_SETUSETABS:
+ pdoc->useTabs = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETUSETABS:
+ return pdoc->useTabs;
+
+ case SCI_SETLINEINDENTATION:
+ pdoc->SetLineIndentation(wParam, lParam);
+ break;
+
+ case SCI_GETLINEINDENTATION:
+ return pdoc->GetLineIndentation(wParam);
+
+ case SCI_GETLINEINDENTPOSITION:
+ return pdoc->GetLineIndentPosition(wParam);
+
+ case SCI_SETTABINDENTS:
+ pdoc->tabIndents = wParam != 0;
+ break;
+
+ case SCI_GETTABINDENTS:
+ return pdoc->tabIndents;
+
+ case SCI_SETBACKSPACEUNINDENTS:
+ pdoc->backspaceUnindents = wParam != 0;
+ break;
+
+ case SCI_GETBACKSPACEUNINDENTS:
+ return pdoc->backspaceUnindents;
+
+ case SCI_SETMOUSEDWELLTIME:
+ dwellDelay = wParam;
+ ticksToDwell = dwellDelay;
+ break;
+
+ case SCI_GETMOUSEDWELLTIME:
+ return dwellDelay;
+
+ case SCI_WORDSTARTPOSITION:
+ return pdoc->ExtendWordSelect(wParam, -1, lParam != 0);
+
+ case SCI_WORDENDPOSITION:
+ return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);
+
+ case SCI_SETWRAPMODE:
+ switch (wParam) {
+ case SC_WRAP_WORD:
+ wrapState = eWrapWord;
+ break;
+ case SC_WRAP_CHAR:
+ wrapState = eWrapChar;
+ break;
+ default:
+ wrapState = eWrapNone;
+ break;
+ }
+ xOffset = 0;
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ break;
+
+ case SCI_GETWRAPMODE:
+ return wrapState;
+
+ case SCI_SETWRAPVISUALFLAGS:
+ if (wrapVisualFlags != static_cast<int>(wParam)) {
+ wrapVisualFlags = wParam;
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPVISUALFLAGS:
+ return wrapVisualFlags;
+
+ case SCI_SETWRAPVISUALFLAGSLOCATION:
+ wrapVisualFlagsLocation = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETWRAPVISUALFLAGSLOCATION:
+ return wrapVisualFlagsLocation;
+
+ case SCI_SETWRAPSTARTINDENT:
+ if (wrapVisualStartIndent != static_cast<int>(wParam)) {
+ wrapVisualStartIndent = wParam;
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPSTARTINDENT:
+ return wrapVisualStartIndent;
+
+ case SCI_SETWRAPINDENTMODE:
+ if (wrapIndentMode != static_cast<int>(wParam)) {
+ wrapIndentMode = wParam;
+ InvalidateStyleRedraw();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETWRAPINDENTMODE:
+ return wrapIndentMode;
+
+ case SCI_SETLAYOUTCACHE:
+ llc.SetLevel(wParam);
+ break;
+
+ case SCI_GETLAYOUTCACHE:
+ return llc.GetLevel();
+
+ case SCI_SETPOSITIONCACHE:
+ posCache.SetSize(wParam);
+ break;
+
+ case SCI_GETPOSITIONCACHE:
+ return posCache.GetSize();
+
+ case SCI_SETSCROLLWIDTH:
+ PLATFORM_ASSERT(wParam > 0);
+ if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
+ lineWidthMaxSeen = 0;
+ scrollWidth = wParam;
+ SetScrollBars();
+ }
+ break;
+
+ case SCI_GETSCROLLWIDTH:
+ return scrollWidth;
+
+ case SCI_SETSCROLLWIDTHTRACKING:
+ trackLineWidth = wParam != 0;
+ break;
+
+ case SCI_GETSCROLLWIDTHTRACKING:
+ return trackLineWidth;
+
+ case SCI_LINESJOIN:
+ LinesJoin();
+ break;
+
+ case SCI_LINESSPLIT:
+ LinesSplit(wParam);
+ break;
+
+ case SCI_TEXTWIDTH:
+ PLATFORM_ASSERT(wParam < vs.stylesSize);
+ PLATFORM_ASSERT(lParam);
+ return TextWidth(wParam, CharPtrFromSPtr(lParam));
+
+ case SCI_TEXTHEIGHT:
+ return vs.lineHeight;
+
+ case SCI_SETENDATLASTLINE:
+ PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
+ if (endAtLastLine != (wParam != 0)) {
+ endAtLastLine = wParam != 0;
+ SetScrollBars();
+ }
+ break;
+
+ 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);
+
+ case SCI_FINDCOLUMN:
+ return pdoc->FindColumn(wParam, lParam);
+
+ case SCI_SETHSCROLLBAR :
+ if (horizontalScrollBarVisible != (wParam != 0)) {
+ horizontalScrollBarVisible = wParam != 0;
+ SetScrollBars();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETHSCROLLBAR:
+ return horizontalScrollBarVisible;
+
+ case SCI_SETVSCROLLBAR:
+ if (verticalScrollBarVisible != (wParam != 0)) {
+ verticalScrollBarVisible = wParam != 0;
+ SetScrollBars();
+ ReconfigureScrollBars();
+ }
+ break;
+
+ case SCI_GETVSCROLLBAR:
+ return verticalScrollBarVisible;
+
+ case SCI_SETINDENTATIONGUIDES:
+ vs.viewIndentationGuides = IndentView(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETINDENTATIONGUIDES:
+ return vs.viewIndentationGuides;
+
+ case SCI_SETHIGHLIGHTGUIDE:
+ if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
+ highlightGuideColumn = wParam;
+ Redraw();
+ }
+ break;
+
+ case SCI_GETHIGHLIGHTGUIDE:
+ return highlightGuideColumn;
+
+ case SCI_GETLINEENDPOSITION:
+ return pdoc->LineEnd(wParam);
+
+ case SCI_SETCODEPAGE:
+ if (ValidCodePage(wParam)) {
+ pdoc->dbcsCodePage = wParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETCODEPAGE:
+ return pdoc->dbcsCodePage;
+
+ case SCI_SETUSEPALETTE:
+ palette.allowRealization = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETUSEPALETTE:
+ return palette.allowRealization;
+
+ // Marker definition and setting
+ case SCI_MARKERDEFINE:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].markType = lParam;
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
+ case SCI_MARKERSYMBOLDEFINED:
+ if (wParam <= MARKER_MAX)
+ return vs.markers[wParam].markType;
+ else
+ return 0;
+
+ case SCI_MARKERSETFORE:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].fore.desired = ColourDesired(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETBACK:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].back.desired = ColourDesired(lParam);
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+ case SCI_MARKERSETALPHA:
+ if (wParam <= MARKER_MAX)
+ vs.markers[wParam].alpha = lParam;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_MARKERADD: {
+ 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);
+ break;
+
+ case SCI_MARKERDELETEALL:
+ pdoc->DeleteAllMarks(static_cast<int>(wParam));
+ break;
+
+ case SCI_MARKERGET:
+ return pdoc->GetMark(wParam);
+
+ case SCI_MARKERNEXT: {
+ int lt = pdoc->LinesTotal();
+ for (int iLine = wParam; iLine < lt; iLine++) {
+ if ((pdoc->GetMark(iLine) & lParam) != 0)
+ return iLine;
+ }
+ }
+ return -1;
+
+ case SCI_MARKERPREVIOUS: {
+ for (int iLine = wParam; iLine >= 0; iLine--) {
+ if ((pdoc->GetMark(iLine) & lParam) != 0)
+ return iLine;
+ }
+ }
+ return -1;
+
+ case SCI_MARKERDEFINEPIXMAP:
+ if (wParam <= MARKER_MAX) {
+ vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
+ };
+ InvalidateStyleData();
+ RedrawSelMargin();
+ break;
+
+ case SCI_SETMARGINTYPEN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].style = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINTYPEN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].style;
+ else
+ return 0;
+
+ case SCI_SETMARGINWIDTHN:
+ if (ValidMargin(wParam)) {
+ // Short-circuit if the width is unchanged, to avoid unnecessary redraw.
+ if (vs.ms[wParam].width != lParam) {
+ vs.ms[wParam].width = lParam;
+ InvalidateStyleRedraw();
+ }
+ }
+ break;
+
+ case SCI_GETMARGINWIDTHN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].width;
+ else
+ return 0;
+
+ case SCI_SETMARGINMASKN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].mask = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINMASKN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].mask;
+ else
+ return 0;
+
+ case SCI_SETMARGINSENSITIVEN:
+ if (ValidMargin(wParam)) {
+ vs.ms[wParam].sensitive = lParam != 0;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETMARGINSENSITIVEN:
+ if (ValidMargin(wParam))
+ return vs.ms[wParam].sensitive ? 1 : 0;
+ else
+ return 0;
+
+ case SCI_STYLECLEARALL:
+ vs.ClearStyles();
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_STYLESETFORE:
+ case SCI_STYLESETBACK:
+ case SCI_STYLESETBOLD:
+ case SCI_STYLESETITALIC:
+ case SCI_STYLESETEOLFILLED:
+ case SCI_STYLESETSIZE:
+ case SCI_STYLESETFONT:
+ case SCI_STYLESETUNDERLINE:
+ case SCI_STYLESETCASE:
+ case SCI_STYLESETCHARACTERSET:
+ case SCI_STYLESETVISIBLE:
+ case SCI_STYLESETCHANGEABLE:
+ case SCI_STYLESETHOTSPOT:
+ StyleSetMessage(iMessage, wParam, lParam);
+ break;
+
+ case SCI_STYLEGETFORE:
+ case SCI_STYLEGETBACK:
+ case SCI_STYLEGETBOLD:
+ case SCI_STYLEGETITALIC:
+ case SCI_STYLEGETEOLFILLED:
+ case SCI_STYLEGETSIZE:
+ case SCI_STYLEGETFONT:
+ case SCI_STYLEGETUNDERLINE:
+ case SCI_STYLEGETCASE:
+ case SCI_STYLEGETCHARACTERSET:
+ case SCI_STYLEGETVISIBLE:
+ case SCI_STYLEGETCHANGEABLE:
+ case SCI_STYLEGETHOTSPOT:
+ return StyleGetMessage(iMessage, wParam, lParam);
+
+ case SCI_STYLERESETDEFAULT:
+ vs.ResetDefaultStyle();
+ InvalidateStyleRedraw();
+ break;
+ case SCI_SETSTYLEBITS:
+ vs.EnsureStyle((1 << wParam) - 1);
+ pdoc->SetStylingBits(wParam);
+ break;
+
+ case SCI_GETSTYLEBITS:
+ return pdoc->stylingBits;
+
+ case SCI_SETLINESTATE:
+ return pdoc->SetLineState(wParam, lParam);
+
+ case SCI_GETLINESTATE:
+ return pdoc->GetLineState(wParam);
+
+ case SCI_GETMAXLINESTATE:
+ return pdoc->GetMaxLineState();
+
+ case SCI_GETCARETLINEVISIBLE:
+ return vs.showCaretLineBackground;
+ case SCI_SETCARETLINEVISIBLE:
+ vs.showCaretLineBackground = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_GETCARETLINEBACK:
+ return vs.caretLineBackground.desired.AsLong();
+ case SCI_SETCARETLINEBACK:
+ vs.caretLineBackground.desired = wParam;
+ InvalidateStyleRedraw();
+ break;
+ case SCI_GETCARETLINEBACKALPHA:
+ return vs.caretLineAlpha;
+ case SCI_SETCARETLINEBACKALPHA:
+ vs.caretLineAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ // Folding messages
+
+ case SCI_VISIBLEFROMDOCLINE:
+ return cs.DisplayFromDoc(wParam);
+
+ 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)
+ RedrawSelMargin();
+ return prev;
+ }
+
+ case SCI_GETFOLDLEVEL:
+ return pdoc->GetLevel(wParam);
+
+ case SCI_GETLASTCHILD:
+ return pdoc->GetLastChild(wParam, lParam);
+
+ case SCI_GETFOLDPARENT:
+ return pdoc->GetFoldParent(wParam);
+
+ case SCI_SHOWLINES:
+ cs.SetVisible(wParam, lParam, true);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_HIDELINES:
+ if (wParam > 0)
+ cs.SetVisible(wParam, lParam, false);
+ SetScrollBars();
+ Redraw();
+ break;
+
+ case SCI_GETLINEVISIBLE:
+ return cs.GetVisible(wParam);
+
+ case SCI_SETFOLDEXPANDED:
+ if (cs.SetExpanded(wParam, lParam != 0)) {
+ RedrawSelMargin();
+ }
+ break;
+
+ case SCI_GETFOLDEXPANDED:
+ return cs.GetExpanded(wParam);
+
+ case SCI_SETFOLDFLAGS:
+ foldFlags = wParam;
+ Redraw();
+ break;
+
+ case SCI_TOGGLEFOLD:
+ ToggleContraction(wParam);
+ break;
+
+ case SCI_ENSUREVISIBLE:
+ EnsureLineVisible(wParam, false);
+ break;
+
+ case SCI_ENSUREVISIBLEENFORCEPOLICY:
+ EnsureLineVisible(wParam, true);
+ break;
+
+ case SCI_SEARCHANCHOR:
+ SearchAnchor();
+ break;
+
+ case SCI_SEARCHNEXT:
+ case SCI_SEARCHPREV:
+ return SearchText(iMessage, wParam, lParam);
+
+ case SCI_SETXCARETPOLICY:
+ caretXPolicy = wParam;
+ caretXSlop = lParam;
+ break;
+
+ case SCI_SETYCARETPOLICY:
+ caretYPolicy = wParam;
+ caretYSlop = lParam;
+ break;
+
+ case SCI_SETVISIBLEPOLICY:
+ visiblePolicy = wParam;
+ visibleSlop = lParam;
+ break;
+
+ case SCI_LINESONSCREEN:
+ return LinesOnScreen();
+
+ case SCI_SETSELFORE:
+ vs.selforeset = wParam != 0;
+ vs.selforeground.desired = ColourDesired(lParam);
+ vs.selAdditionalForeground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSELBACK:
+ vs.selbackset = wParam != 0;
+ vs.selbackground.desired = ColourDesired(lParam);
+ vs.selAdditionalBackground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETSELALPHA:
+ vs.selAlpha = wParam;
+ vs.selAdditionalAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETSELALPHA:
+ return vs.selAlpha;
+
+ case SCI_GETSELEOLFILLED:
+ return vs.selEOLFilled;
+
+ case SCI_SETSELEOLFILLED:
+ vs.selEOLFilled = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETWHITESPACEFORE:
+ vs.whitespaceForegroundSet = wParam != 0;
+ vs.whitespaceForeground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETWHITESPACEBACK:
+ vs.whitespaceBackgroundSet = wParam != 0;
+ vs.whitespaceBackground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETCARETFORE:
+ vs.caretcolour.desired = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETFORE:
+ return vs.caretcolour.desired.AsLong();
+
+ case SCI_SETCARETSTYLE:
+ if (wParam >= CARETSTYLE_INVISIBLE && wParam <= CARETSTYLE_BLOCK)
+ vs.caretStyle = wParam;
+ else
+ /* Default to the line caret */
+ vs.caretStyle = CARETSTYLE_LINE;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETSTYLE:
+ return vs.caretStyle;
+
+ case SCI_SETCARETWIDTH:
+ if (wParam <= 0)
+ vs.caretWidth = 0;
+ else if (wParam >= 3)
+ vs.caretWidth = 3;
+ else
+ vs.caretWidth = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETCARETWIDTH:
+ return vs.caretWidth;
+
+ case SCI_ASSIGNCMDKEY:
+ kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
+ Platform::HighShortFromLong(wParam), lParam);
+ break;
+
+ case SCI_CLEARCMDKEY:
+ kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
+ Platform::HighShortFromLong(wParam), SCI_NULL);
+ break;
+
+ case SCI_CLEARALLCMDKEYS:
+ kmap.Clear();
+ break;
+
+ case SCI_INDICSETSTYLE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].style = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETSTYLE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
+
+ case SCI_INDICSETFORE:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].fore.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETFORE:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.desired.AsLong() : 0;
+
+ case SCI_INDICSETUNDER:
+ if (wParam <= INDIC_MAX) {
+ vs.indicators[wParam].under = lParam != 0;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETUNDER:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;
+
+ case SCI_INDICSETALPHA:
+ if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 100) {
+ vs.indicators[wParam].fillAlpha = lParam;
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_INDICGETALPHA:
+ return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0;
+
+ case SCI_SETINDICATORCURRENT:
+ pdoc->decorations.SetCurrentIndicator(wParam);
+ break;
+ case SCI_GETINDICATORCURRENT:
+ return pdoc->decorations.GetCurrentIndicator();
+ case SCI_SETINDICATORVALUE:
+ pdoc->decorations.SetCurrentValue(wParam);
+ break;
+ case SCI_GETINDICATORVALUE:
+ return pdoc->decorations.GetCurrentValue();
+
+ case SCI_INDICATORFILLRANGE:
+ pdoc->DecorationFillRange(wParam, pdoc->decorations.GetCurrentValue(), lParam);
+ break;
+
+ case SCI_INDICATORCLEARRANGE:
+ pdoc->DecorationFillRange(wParam, 0, lParam);
+ break;
+
+ case SCI_INDICATORALLONFOR:
+ return pdoc->decorations.AllOnFor(wParam);
+
+ case SCI_INDICATORVALUEAT:
+ return pdoc->decorations.ValueAt(wParam, lParam);
+
+ case SCI_INDICATORSTART:
+ return pdoc->decorations.Start(wParam, lParam);
+
+ case SCI_INDICATOREND:
+ return pdoc->decorations.End(wParam, lParam);
+
+ case SCI_LINEDOWN:
+ case SCI_LINEDOWNEXTEND:
+ case SCI_PARADOWN:
+ case SCI_PARADOWNEXTEND:
+ case SCI_LINEUP:
+ case SCI_LINEUPEXTEND:
+ case SCI_PARAUP:
+ case SCI_PARAUPEXTEND:
+ case SCI_CHARLEFT:
+ case SCI_CHARLEFTEXTEND:
+ case SCI_CHARRIGHT:
+ case SCI_CHARRIGHTEXTEND:
+ case SCI_WORDLEFT:
+ case SCI_WORDLEFTEXTEND:
+ case SCI_WORDRIGHT:
+ case SCI_WORDRIGHTEXTEND:
+ case SCI_WORDLEFTEND:
+ case SCI_WORDLEFTENDEXTEND:
+ case SCI_WORDRIGHTEND:
+ case SCI_WORDRIGHTENDEXTEND:
+ case SCI_HOME:
+ case SCI_HOMEEXTEND:
+ case SCI_LINEEND:
+ case SCI_LINEENDEXTEND:
+ case SCI_HOMEWRAP:
+ case SCI_HOMEWRAPEXTEND:
+ case SCI_LINEENDWRAP:
+ case SCI_LINEENDWRAPEXTEND:
+ case SCI_DOCUMENTSTART:
+ case SCI_DOCUMENTSTARTEXTEND:
+ case SCI_DOCUMENTEND:
+ case SCI_DOCUMENTENDEXTEND:
+
+ case SCI_STUTTEREDPAGEUP:
+ case SCI_STUTTEREDPAGEUPEXTEND:
+ case SCI_STUTTEREDPAGEDOWN:
+ case SCI_STUTTEREDPAGEDOWNEXTEND:
+
+ case SCI_PAGEUP:
+ case SCI_PAGEUPEXTEND:
+ case SCI_PAGEDOWN:
+ case SCI_PAGEDOWNEXTEND:
+ case SCI_EDITTOGGLEOVERTYPE:
+ case SCI_CANCEL:
+ case SCI_DELETEBACK:
+ case SCI_TAB:
+ case SCI_BACKTAB:
+ case SCI_NEWLINE:
+ case SCI_FORMFEED:
+ case SCI_VCHOME:
+ case SCI_VCHOMEEXTEND:
+ case SCI_VCHOMEWRAP:
+ case SCI_VCHOMEWRAPEXTEND:
+ case SCI_ZOOMIN:
+ case SCI_ZOOMOUT:
+ case SCI_DELWORDLEFT:
+ case SCI_DELWORDRIGHT:
+ case SCI_DELWORDRIGHTEND:
+ case SCI_DELLINELEFT:
+ case SCI_DELLINERIGHT:
+ case SCI_LINECOPY:
+ case SCI_LINECUT:
+ case SCI_LINEDELETE:
+ case SCI_LINETRANSPOSE:
+ case SCI_LINEDUPLICATE:
+ case SCI_LOWERCASE:
+ case SCI_UPPERCASE:
+ case SCI_LINESCROLLDOWN:
+ case SCI_LINESCROLLUP:
+ case SCI_WORDPARTLEFT:
+ case SCI_WORDPARTLEFTEXTEND:
+ case SCI_WORDPARTRIGHT:
+ case SCI_WORDPARTRIGHTEXTEND:
+ case SCI_DELETEBACKNOTLINE:
+ case SCI_HOMEDISPLAY:
+ case SCI_HOMEDISPLAYEXTEND:
+ case SCI_LINEENDDISPLAY:
+ case SCI_LINEENDDISPLAYEXTEND:
+ case SCI_LINEDOWNRECTEXTEND:
+ case SCI_LINEUPRECTEXTEND:
+ case SCI_CHARLEFTRECTEXTEND:
+ case SCI_CHARRIGHTRECTEXTEND:
+ case SCI_HOMERECTEXTEND:
+ case SCI_VCHOMERECTEXTEND:
+ case SCI_LINEENDRECTEXTEND:
+ case SCI_PAGEUPRECTEXTEND:
+ case SCI_PAGEDOWNRECTEXTEND:
+ case SCI_SELECTIONDUPLICATE:
+ return KeyCommand(iMessage);
+
+ case SCI_BRACEHIGHLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
+ break;
+
+ case SCI_BRACEBADLIGHT:
+ SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
+ break;
+
+ case SCI_BRACEMATCH:
+ // wParam is position of char to find brace for,
+ // lParam is maximum amount of text to restyle to find it
+ return pdoc->BraceMatch(wParam, lParam);
+
+ case SCI_GETVIEWEOL:
+ return vs.viewEOL;
+
+ case SCI_SETVIEWEOL:
+ vs.viewEOL = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETZOOM:
+ vs.zoomLevel = wParam;
+ InvalidateStyleRedraw();
+ NotifyZoom();
+ break;
+
+ case SCI_GETZOOM:
+ return vs.zoomLevel;
+
+ case SCI_GETEDGECOLUMN:
+ return theEdge;
+
+ case SCI_SETEDGECOLUMN:
+ theEdge = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGEMODE:
+ return vs.edgeState;
+
+ case SCI_SETEDGEMODE:
+ vs.edgeState = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEDGECOLOUR:
+ return vs.edgecolour.desired.AsLong();
+
+ case SCI_SETEDGECOLOUR:
+ vs.edgecolour.desired = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETDOCPOINTER:
+ return reinterpret_cast<sptr_t>(pdoc);
+
+ case SCI_SETDOCPOINTER:
+ CancelModes();
+ SetDocPointer(reinterpret_cast<Document *>(lParam));
+ return 0;
+
+ case SCI_CREATEDOCUMENT: {
+ Document *doc = new Document();
+ if (doc) {
+ doc->AddRef();
+ }
+ return reinterpret_cast<sptr_t>(doc);
+ }
+
+ case SCI_ADDREFDOCUMENT:
+ (reinterpret_cast<Document *>(lParam))->AddRef();
+ break;
+
+ case SCI_RELEASEDOCUMENT:
+ (reinterpret_cast<Document *>(lParam))->Release();
+ break;
+
+ case SCI_SETMODEVENTMASK:
+ modEventMask = wParam;
+ return 0;
+
+ case SCI_GETMODEVENTMASK:
+ return modEventMask;
+
+ case SCI_CONVERTEOLS:
+ pdoc->ConvertLineEnds(wParam);
+ SetSelection(sel.MainCaret(), sel.MainAnchor()); // Ensure selection inside document
+ return 0;
+
+ case SCI_SETLENGTHFORENCODE:
+ lengthForEncode = wParam;
+ return 0;
+
+ case SCI_SELECTIONISRECTANGLE:
+ return sel.selType == Selection::selRectangle ? 1 : 0;
+
+ case SCI_SETSELECTIONMODE: {
+ switch (wParam) {
+ case SC_SEL_STREAM:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
+ sel.selType = Selection::selStream;
+ break;
+ case SC_SEL_RECTANGLE:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
+ sel.selType = Selection::selRectangle;
+ break;
+ case SC_SEL_LINES:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
+ sel.selType = Selection::selLines;
+ break;
+ case SC_SEL_THIN:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
+ sel.selType = Selection::selThin;
+ break;
+ default:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
+ sel.selType = Selection::selStream;
+ }
+ InvalidateSelection(sel.RangeMain(), true);
+ }
+ case SCI_GETSELECTIONMODE:
+ switch (sel.selType) {
+ case Selection::selStream:
+ return SC_SEL_STREAM;
+ case Selection::selRectangle:
+ return SC_SEL_RECTANGLE;
+ case Selection::selLines:
+ return SC_SEL_LINES;
+ case Selection::selThin:
+ return SC_SEL_THIN;
+ default: // ?!
+ return SC_SEL_STREAM;
+ }
+ case SCI_GETLINESELSTARTPOSITION:
+ case SCI_GETLINESELENDPOSITION: {
+ SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(wParam)),
+ SelectionPosition(pdoc->LineEnd(wParam)));
+ for (size_t r=0; r<sel.Count(); r++) {
+ SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
+ if (portion.start.IsValid()) {
+ return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
+ }
+ }
+ return INVALID_POSITION;
+ }
+
+ case SCI_SETOVERTYPE:
+ inOverstrike = wParam != 0;
+ break;
+
+ case SCI_GETOVERTYPE:
+ return inOverstrike ? 1 : 0;
+
+ case SCI_SETFOCUS:
+ SetFocusState(wParam != 0);
+ break;
+
+ case SCI_GETFOCUS:
+ return hasFocus;
+
+ case SCI_SETSTATUS:
+ errorStatus = wParam;
+ break;
+
+ case SCI_GETSTATUS:
+ return errorStatus;
+
+ case SCI_SETMOUSEDOWNCAPTURES:
+ mouseDownCaptures = wParam != 0;
+ break;
+
+ case SCI_GETMOUSEDOWNCAPTURES:
+ return mouseDownCaptures;
+
+ case SCI_SETCURSOR:
+ cursorMode = wParam;
+ DisplayCursor(Window::cursorText);
+ break;
+
+ case SCI_GETCURSOR:
+ return cursorMode;
+
+ case SCI_SETCONTROLCHARSYMBOL:
+ controlCharSymbol = wParam;
+ break;
+
+ case SCI_GETCONTROLCHARSYMBOL:
+ return controlCharSymbol;
+
+ case SCI_STARTRECORD:
+ recordingMacro = true;
+ return 0;
+
+ case SCI_STOPRECORD:
+ recordingMacro = false;
+ return 0;
+
+ case SCI_MOVECARETINSIDEVIEW:
+ MoveCaretInsideView();
+ break;
+
+ case SCI_SETFOLDMARGINCOLOUR:
+ vs.foldmarginColourSet = wParam != 0;
+ vs.foldmarginColour.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETFOLDMARGINHICOLOUR:
+ vs.foldmarginHighlightColourSet = wParam != 0;
+ vs.foldmarginHighlightColour.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETHOTSPOTACTIVEFORE:
+ vs.hotspotForegroundSet = wParam != 0;
+ vs.hotspotForeground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEFORE:
+ return vs.hotspotForeground.desired.AsLong();
+
+ case SCI_SETHOTSPOTACTIVEBACK:
+ vs.hotspotBackgroundSet = wParam != 0;
+ vs.hotspotBackground.desired = ColourDesired(lParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEBACK:
+ return vs.hotspotBackground.desired.AsLong();
+
+ case SCI_SETHOTSPOTACTIVEUNDERLINE:
+ vs.hotspotUnderline = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTACTIVEUNDERLINE:
+ return vs.hotspotUnderline ? 1 : 0;
+
+ case SCI_SETHOTSPOTSINGLELINE:
+ vs.hotspotSingleLine = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETHOTSPOTSINGLELINE:
+ return vs.hotspotSingleLine ? 1 : 0;
+
+ case SCI_SETPASTECONVERTENDINGS:
+ convertPastes = wParam != 0;
+ break;
+
+ case SCI_GETPASTECONVERTENDINGS:
+ return convertPastes ? 1 : 0;
+
+ case SCI_GETCHARACTERPOINTER:
+ return reinterpret_cast<sptr_t>(pdoc->BufferPointer());
+
+ case SCI_SETEXTRAASCENT:
+ vs.extraAscent = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEXTRAASCENT:
+ return vs.extraAscent;
+
+ case SCI_SETEXTRADESCENT:
+ vs.extraDescent = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETEXTRADESCENT:
+ return vs.extraDescent;
+
+ case SCI_MARGINSETSTYLEOFFSET:
+ vs.marginStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_MARGINGETSTYLEOFFSET:
+ return vs.marginStyleOffset;
+
+ case SCI_MARGINSETTEXT:
+ pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_MARGINGETTEXT: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ if (lParam) {
+ if (st.text)
+ memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.length;
+ }
+
+ case SCI_MARGINSETSTYLE:
+ pdoc->MarginSetStyle(wParam, lParam);
+ break;
+
+ case SCI_MARGINGETSTYLE: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ return st.style;
+ }
+
+ case SCI_MARGINSETSTYLES:
+ pdoc->MarginSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
+ break;
+
+ case SCI_MARGINGETSTYLES: {
+ const StyledText st = pdoc->MarginStyledText(wParam);
+ if (lParam) {
+ if (st.styles)
+ memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.styles ? st.length : 0;
+ }
+
+ case SCI_MARGINTEXTCLEARALL:
+ pdoc->MarginClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETTEXT:
+ pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETTEXT: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ if (lParam) {
+ if (st.text)
+ memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.length;
+ }
+
+ case SCI_ANNOTATIONGETSTYLE: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ return st.style;
+ }
+
+ case SCI_ANNOTATIONSETSTYLE:
+ pdoc->AnnotationSetStyle(wParam, lParam);
+ break;
+
+ case SCI_ANNOTATIONSETSTYLES:
+ pdoc->AnnotationSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
+ break;
+
+ case SCI_ANNOTATIONGETSTYLES: {
+ const StyledText st = pdoc->AnnotationStyledText(wParam);
+ if (lParam) {
+ if (st.styles)
+ memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
+ else
+ strcpy(CharPtrFromSPtr(lParam), "");
+ }
+ return st.styles ? st.length : 0;
+ }
+
+ case SCI_ANNOTATIONGETLINES:
+ return pdoc->AnnotationLines(wParam);
+
+ case SCI_ANNOTATIONCLEARALL:
+ pdoc->AnnotationClearAll();
+ break;
+
+ case SCI_ANNOTATIONSETVISIBLE:
+ SetAnnotationVisible(wParam);
+ break;
+
+ case SCI_ANNOTATIONGETVISIBLE:
+ return vs.annotationVisible;
+
+ case SCI_ANNOTATIONSETSTYLEOFFSET:
+ vs.annotationStyleOffset = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_ANNOTATIONGETSTYLEOFFSET:
+ return vs.annotationStyleOffset;
+
+ case SCI_ADDUNDOACTION:
+ pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
+ break;
+
+ case SCI_SETMULTIPLESELECTION:
+ multipleSelection = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETMULTIPLESELECTION:
+ return multipleSelection;
+
+ case SCI_SETADDITIONALSELECTIONTYPING:
+ additionalSelectionTyping = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALSELECTIONTYPING:
+ return additionalSelectionTyping;
+
+ case SCI_SETMULTIPASTE:
+ multiPasteMode = wParam;
+ break;
+
+ case SCI_GETMULTIPASTE:
+ return multiPasteMode;
+
+ case SCI_SETADDITIONALCARETSBLINK:
+ additionalCaretsBlink = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALCARETSBLINK:
+ return additionalCaretsBlink;
+
+ case SCI_SETADDITIONALCARETSVISIBLE:
+ additionalCaretsVisible = wParam != 0;
+ InvalidateCaret();
+ break;
+
+ case SCI_GETADDITIONALCARETSVISIBLE:
+ return additionalCaretsVisible;
+
+ case SCI_GETSELECTIONS:
+ return sel.Count();
+
+ case SCI_CLEARSELECTIONS:
+ sel.Clear();
+ Redraw();
+ break;
+
+ case SCI_SETSELECTION:
+ sel.SetSelection(SelectionRange(wParam, lParam));
+ Redraw();
+ break;
+
+ case SCI_ADDSELECTION:
+ sel.AddSelection(SelectionRange(wParam, lParam));
+ Redraw();
+ break;
+
+ case SCI_SETMAINSELECTION:
+ sel.SetMain(wParam);
+ Redraw();
+ break;
+
+ case SCI_GETMAINSELECTION:
+ return sel.Main();
+
+ case SCI_SETSELECTIONNCARET:
+ sel.Range(wParam).caret.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNCARET:
+ return sel.Range(wParam).caret.Position();
+
+ case SCI_SETSELECTIONNANCHOR:
+ sel.Range(wParam).anchor.SetPosition(lParam);
+ Redraw();
+ break;
+ case SCI_GETSELECTIONNANCHOR:
+ return sel.Range(wParam).anchor.Position();
+
+ case SCI_SETSELECTIONNCARETVIRTUALSPACE:
+ sel.Range(wParam).caret.SetVirtualSpace(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNCARETVIRTUALSPACE:
+ return sel.Range(wParam).caret.VirtualSpace();
+
+ case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
+ sel.Range(wParam).anchor.SetVirtualSpace(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
+ return sel.Range(wParam).anchor.VirtualSpace();
+
+ case SCI_SETSELECTIONNSTART:
+ sel.Range(wParam).anchor.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNSTART:
+ return sel.Range(wParam).Start().Position();
+
+ case SCI_SETSELECTIONNEND:
+ sel.Range(wParam).caret.SetPosition(lParam);
+ Redraw();
+ break;
+
+ case SCI_GETSELECTIONNEND:
+ return sel.Range(wParam).End().Position();
+
+ case SCI_SETRECTANGULARSELECTIONCARET:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().caret.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONCARET:
+ return sel.Rectangular().caret.Position();
+
+ case SCI_SETRECTANGULARSELECTIONANCHOR:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().anchor.SetPosition(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONANCHOR:
+ return sel.Rectangular().anchor.Position();
+
+ case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().caret.SetVirtualSpace(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
+ return sel.Rectangular().caret.VirtualSpace();
+
+ case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
+ if (!sel.IsRectangular())
+ sel.Clear();
+ sel.selType = Selection::selRectangle;
+ sel.Rectangular().anchor.SetVirtualSpace(wParam);
+ SetRectangularRange();
+ Redraw();
+ break;
+
+ case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
+ return sel.Rectangular().anchor.VirtualSpace();
+
+ case SCI_SETVIRTUALSPACEOPTIONS:
+ virtualSpaceOptions = wParam;
+ break;
+
+ case SCI_GETVIRTUALSPACEOPTIONS:
+ return virtualSpaceOptions;
+
+ case SCI_SETADDITIONALSELFORE:
+ vs.selAdditionalForeground.desired = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETADDITIONALSELBACK:
+ vs.selAdditionalBackground.desired = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_SETADDITIONALSELALPHA:
+ vs.selAdditionalAlpha = wParam;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETADDITIONALSELALPHA:
+ return vs.selAdditionalAlpha;
+
+ case SCI_SETADDITIONALCARETFORE:
+ vs.additionalCaretColour.desired = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_GETADDITIONALCARETFORE:
+ return vs.additionalCaretColour.desired.AsLong();
+
+ case SCI_ROTATESELECTION:
+ sel.RotateMain();
+ InvalidateSelection(sel.RangeMain(), true);
+ break;
+
+ case SCI_SWAPMAINANCHORCARET:
+ InvalidateSelection(sel.RangeMain());
+ sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret);
+ break;
+
+ default:
+ return DefWndProc(iMessage, wParam, lParam);
+ }
+ //Platform::DebugPrintf("end wnd proc\n");
+ return 0l;
+}
diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h
new file mode 100644
index 0000000..b5acc00
--- /dev/null
+++ b/scintilla/src/Editor.h
@@ -0,0 +1,586 @@
+// Scintilla source code edit control
+/** @file Editor.h
+ ** Defines the main editor class.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class Caret {
+public:
+ bool active;
+ bool on;
+ int period;
+
+ Caret();
+};
+
+/**
+ */
+class Timer {
+public:
+ bool ticking;
+ int ticksToWait;
+ enum {tickSize = 100};
+ TickerID tickerID;
+
+ Timer();
+};
+
+/**
+ */
+class Idler {
+public:
+ bool state;
+ IdlerID idlerID;
+
+ Idler();
+};
+
+/**
+ * When platform has a way to generate an event before painting,
+ * accumulate needed styling range in StyleNeeded to avoid unnecessary work.
+ */
+class StyleNeeded {
+public:
+ bool active;
+ Position upTo;
+
+ StyleNeeded() : active(false), upTo(0) {}
+ void Reset() {
+ active = false;
+ upTo = 0;
+ }
+ void NeedUpTo(Position pos) {
+ if (upTo < pos)
+ upTo = pos;
+ }
+};
+
+/**
+ * Hold a piece of text selected for copying or dragging.
+ * The text is expected to hold a terminating '\0' and this is counted in len.
+ */
+class SelectionText {
+public:
+ char *s;
+ int len;
+ bool rectangular;
+ bool lineCopy;
+ int codePage;
+ int characterSet;
+ SelectionText() : s(0), len(0), rectangular(false), lineCopy(false), codePage(0), characterSet(0) {}
+ ~SelectionText() {
+ Free();
+ }
+ void Free() {
+ Set(0, 0, 0, 0, false, false);
+ }
+ void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
+ delete []s;
+ s = s_;
+ if (s)
+ len = len_;
+ else
+ len = 0;
+ codePage = codePage_;
+ characterSet = characterSet_;
+ rectangular = rectangular_;
+ lineCopy = lineCopy_;
+ }
+ void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
+ delete []s;
+ s = 0;
+ s = new char[len_];
+ len = len_;
+ for (int i = 0; i < len_; i++) {
+ s[i] = s_[i];
+ }
+ codePage = codePage_;
+ characterSet = characterSet_;
+ rectangular = rectangular_;
+ lineCopy = lineCopy_;
+ }
+ void Copy(const SelectionText &other) {
+ Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
+ }
+};
+
+/**
+ */
+class Editor : public DocWatcher {
+ // Private so Editor objects can not be copied
+ Editor(const Editor &);
+ Editor &operator=(const Editor &);
+
+protected: // ScintillaBase subclass needs access to much of Editor
+
+ /** On GTK+, Scintilla is a container widget holding two scroll bars
+ * whereas on Windows there is just one window with both scroll bars turned on. */
+ Window wMain; ///< The Scintilla parent window
+
+ /** Style resources may be expensive to allocate so are cached between uses.
+ * When a style attribute is changed, this cache is flushed. */
+ bool stylesValid;
+ ViewStyle vs;
+ Palette palette;
+
+ int printMagnification;
+ int printColourMode;
+ int printWrapState;
+ int cursorMode;
+ int controlCharSymbol;
+
+ bool hasFocus;
+ bool hideSelection;
+ bool inOverstrike;
+ bool mouseDownCaptures;
+
+ /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
+ * the screen. This avoids flashing but is about 30% slower. */
+ bool bufferedDraw;
+ /** In twoPhaseDraw mode, drawing is performed in two phases, first the background
+ * and then the foreground. This avoids chopping off characters that overlap the next run. */
+ bool twoPhaseDraw;
+
+ int xOffset; ///< Horizontal scrolled amount in pixels
+ int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret
+ bool horizontalScrollBarVisible;
+ int scrollWidth;
+ bool trackLineWidth;
+ int lineWidthMaxSeen;
+ bool verticalScrollBarVisible;
+ bool endAtLastLine;
+ bool caretSticky;
+ bool multipleSelection;
+ bool additionalSelectionTyping;
+ int multiPasteMode;
+ bool additionalCaretsBlink;
+ bool additionalCaretsVisible;
+
+ int virtualSpaceOptions;
+
+ Surface *pixmapLine;
+ Surface *pixmapSelMargin;
+ Surface *pixmapSelPattern;
+ Surface *pixmapIndentGuide;
+ Surface *pixmapIndentGuideHighlight;
+
+ LineLayoutCache llc;
+ PositionCache posCache;
+
+ KeyMap kmap;
+
+ Caret caret;
+ Timer timer;
+ Timer autoScrollTimer;
+ enum { autoScrollDelay = 200 };
+
+ Idler idler;
+
+ Point lastClick;
+ unsigned int lastClickTime;
+ int dwellDelay;
+ int ticksToDwell;
+ bool dwelling;
+ enum { selChar, selWord, selLine } selectionType;
+ Point ptMouseLast;
+ enum { ddNone, ddInitial, ddDragging } inDragDrop;
+ bool dropWentOutside;
+ SelectionPosition posDrag;
+ SelectionPosition posDrop;
+ int lastXChosen;
+ int lineAnchor;
+ int originalAnchorPos;
+ int targetStart;
+ int targetEnd;
+ int searchFlags;
+ int topLine;
+ int posTopLine;
+ int lengthForEncode;
+
+ bool needUpdateUI;
+ Position braces[2];
+ int bracesMatchStyle;
+ int highlightGuideColumn;
+
+ int theEdge;
+
+ enum { notPainting, painting, paintAbandoned } paintState;
+ PRectangle rcPaint;
+ bool paintingAllText;
+ StyleNeeded styleNeeded;
+
+ int modEventMask;
+
+ SelectionText drag;
+ Selection sel;
+ bool primarySelection;
+
+ int caretXPolicy;
+ int caretXSlop; ///< Ensure this many pixels visible on both sides of caret
+
+ int caretYPolicy;
+ int caretYSlop; ///< Ensure this many lines visible on both sides of caret
+
+ int visiblePolicy;
+ int visibleSlop;
+
+ int searchAnchor;
+
+ bool recordingMacro;
+
+ int foldFlags;
+ ContractionState cs;
+
+ // Hotspot support
+ int hsStart;
+ int hsEnd;
+
+ // Wrapping support
+ enum { eWrapNone, eWrapWord, eWrapChar } wrapState;
+ enum { wrapLineLarge = 0x7ffffff };
+ int wrapWidth;
+ int wrapStart;
+ int wrapEnd;
+ int wrapVisualFlags;
+ int wrapVisualFlagsLocation;
+ int wrapVisualStartIndent;
+ int wrapAddIndent; // This will be added to initial indent of line
+ int wrapIndentMode; // SC_WRAPINDENT_FIXED, _SAME, _INDENT
+
+ bool convertPastes;
+
+ Document *pdoc;
+
+ Editor();
+ virtual ~Editor();
+ virtual void Initialise() = 0;
+ virtual void Finalise();
+
+ void InvalidateStyleData();
+ void InvalidateStyleRedraw();
+ virtual void RefreshColourPalette(Palette &pal, bool want);
+ void RefreshStyleData();
+ void DropGraphics();
+
+ virtual PRectangle GetClientRectangle();
+ PRectangle GetTextRectangle();
+
+ int LinesOnScreen();
+ int LinesToScroll();
+ int MaxScrollPos();
+ SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const;
+ Point LocationFromPosition(SelectionPosition pos);
+ Point LocationFromPosition(int pos);
+ int XFromPosition(int pos);
+ int XFromPosition(SelectionPosition sp);
+ SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true);
+ int PositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false);
+ SelectionPosition SPositionFromLineX(int lineDoc, int x);
+ int PositionFromLineX(int line, int x);
+ int LineFromLocation(Point pt);
+ void SetTopLine(int topLineNew);
+
+ bool AbandonPaint();
+ void RedrawRect(PRectangle rc);
+ void Redraw();
+ void RedrawSelMargin(int line=-1, bool allAfter=false);
+ PRectangle RectangleFromRange(int start, int end);
+ void InvalidateRange(int start, int end);
+
+ bool UserVirtualSpace() const {
+ return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0);
+ }
+ int CurrentPosition();
+ bool SelectionEmpty();
+ SelectionPosition SelectionStart();
+ SelectionPosition SelectionEnd();
+ void SetRectangularRange();
+ void ThinRectangularRange();
+ void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
+ void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
+ void SetSelection(int currentPos_, int anchor_);
+ void SetSelection(SelectionPosition currentPos_);
+ void SetSelection(int currentPos_);
+ void SetEmptySelection(SelectionPosition currentPos_);
+ void SetEmptySelection(int currentPos_);
+ bool RangeContainsProtected(int start, int end) const;
+ bool SelectionContainsProtected();
+ int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const;
+ SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const;
+ int MovePositionTo(SelectionPosition newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
+ int MovePositionTo(int newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
+ SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir);
+ SelectionPosition MovePositionSoVisible(int pos, int moveDir);
+ Point PointMainCaret();
+ void SetLastXChosen();
+
+ void ScrollTo(int line, bool moveThumb=true);
+ virtual void ScrollText(int linesToMove);
+ void HorizontalScrollTo(int xPos);
+ void MoveCaretInsideView(bool ensureVisible=true);
+ int DisplayFromPosition(int pos);
+
+ struct XYScrollPosition {
+ int xOffset;
+ int topLine;
+ XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {}
+ };
+ XYScrollPosition XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz);
+ void SetXYScroll(XYScrollPosition newXY);
+ void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
+ void ShowCaretAtCurrentPosition();
+ void DropCaret();
+ void InvalidateCaret();
+ virtual void UpdateSystemCaret();
+
+ void NeedWrapping(int docLineStart = 0, int docLineEnd = wrapLineLarge);
+ bool WrapOneLine(Surface *surface, int lineToWrap);
+ bool WrapLines(bool fullWrap, int priorityWrapLineStart);
+ void LinesJoin();
+ void LinesSplit(int pixelWidth);
+
+ int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault);
+ void PaintSelMargin(Surface *surface, PRectangle &rc);
+ LineLayout *RetrieveLineLayout(int lineNumber);
+ void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll,
+ int width=LineLayout::wrapWidthInfinite);
+ ColourAllocated SelectionBackground(ViewStyle &vsDraw, bool main);
+ ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll);
+ void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
+ void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourAllocated wrapColour);
+ void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
+ int line, int lineEnd, int xStart, int subLine, int subLineStart,
+ bool overrideBackground, ColourAllocated background,
+ bool drawWrapMark, ColourAllocated wrapColour);
+ void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under);
+ void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine);
+ void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine);
+ void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
+ int xStart, int offset, int posCaret, PRectangle rcCaret, ColourAllocated caretColour);
+ void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine);
+ void RefreshPixMaps(Surface *surfaceWindow);
+ void Paint(Surface *surfaceWindow, PRectangle rcArea);
+ long FormatRange(bool draw, Sci_RangeToFormat *pfr);
+ int TextWidth(int style, const char *text);
+
+ virtual void SetVerticalScrollPos() = 0;
+ virtual void SetHorizontalScrollPos() = 0;
+ virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
+ virtual void ReconfigureScrollBars();
+ void SetScrollBars();
+ void ChangeSize();
+
+ void FilterSelections();
+ int InsertSpace(int position, unsigned int spaces);
+ void AddChar(char ch);
+ virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
+ void InsertPaste(SelectionPosition selStart, const char *text, int len);
+ void ClearSelection();
+ void ClearAll();
+ void ClearDocumentStyle();
+ void Cut();
+ void PasteRectangular(SelectionPosition pos, const char *ptr, int len);
+ virtual void Copy() = 0;
+ virtual void CopyAllowLine();
+ virtual bool CanPaste();
+ virtual void Paste() = 0;
+ void Clear();
+ void SelectAll();
+ void Undo();
+ void Redo();
+ void DelChar();
+ void DelCharBack(bool allowLineStartDeletion);
+ virtual void ClaimSelection() = 0;
+
+ virtual void NotifyChange() = 0;
+ virtual void NotifyFocus(bool focus);
+ virtual int GetCtrlID() { return ctrlID; }
+ virtual void NotifyParent(SCNotification scn) = 0;
+ virtual void NotifyStyleToNeeded(int endStyleNeeded);
+ void NotifyChar(int ch);
+ void NotifySavePoint(bool isSavePoint);
+ void NotifyModifyAttempt();
+ virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
+ void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
+ void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
+ void NotifyUpdateUI();
+ void NotifyPainted();
+ void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt);
+ bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
+ void NotifyNeedShown(int pos, int len);
+ void NotifyDwelling(Point pt, bool state);
+ void NotifyZoom();
+
+ void NotifyModifyAttempt(Document *document, void *userData);
+ void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
+ void CheckModificationForWrap(DocModification mh);
+ void NotifyModified(Document *document, DocModification mh, void *userData);
+ void NotifyDeleted(Document *document, void *userData);
+ void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
+ void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false);
+ enum { cmSame, cmUpper, cmLower } caseMap;
+ virtual std::string CaseMapString(const std::string &s, int caseMapping);
+ void ChangeCaseOfSelection(int caseMapping);
+ void LineTranspose();
+ void Duplicate(bool forLine);
+ virtual void CancelModes();
+ void NewLine();
+ void CursorUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
+ void ParaUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
+ int StartEndDisplayLine(int pos, bool start);
+ virtual int KeyCommand(unsigned int iMessage);
+ virtual int KeyDefault(int /* key */, int /*modifiers*/);
+ int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0);
+
+ int GetWhitespaceVisible();
+ void SetWhitespaceVisible(int view);
+
+ void Indent(bool forwards);
+
+ virtual CaseFolder *CaseFolderForEncoding();
+ long FindText(uptr_t wParam, sptr_t lParam);
+ void SearchAnchor();
+ long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ long SearchInTarget(const char *text, int length);
+ void GoToLine(int lineNo);
+
+ virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
+ char *CopyRange(int start, int end);
+ void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
+ void CopyRangeToClipboard(int start, int end);
+ void CopyText(int length, const char *text);
+ void SetDragPosition(SelectionPosition newPos);
+ virtual void DisplayCursor(Window::Cursor c);
+ virtual bool DragThreshold(Point ptStart, Point ptNow);
+ virtual void StartDrag();
+ void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular);
+ /** PositionInSelection returns true if position in selection. */
+ bool PositionInSelection(int pos);
+ bool PointInSelection(Point pt);
+ bool PointInSelMargin(Point pt);
+ void LineSelection(int lineCurrent_, int lineAnchor_);
+ void DwellEnd(bool mouseMoved);
+ void MouseLeave();
+ virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+ void ButtonMove(Point pt);
+ void ButtonUp(Point pt, unsigned int curTime, bool ctrl);
+
+ void Tick();
+ bool Idle();
+ virtual void SetTicking(bool on) = 0;
+ virtual bool SetIdle(bool) { return false; }
+ virtual void SetMouseCapture(bool on) = 0;
+ virtual bool HaveMouseCapture() = 0;
+ void SetFocusState(bool focusState);
+
+ int PositionAfterArea(PRectangle rcArea);
+ void StyleToPositionInView(Position pos);
+ void IdleStyling();
+ virtual void QueueStyling(int upTo);
+
+ virtual bool PaintContains(PRectangle rc);
+ bool PaintContainsMargin();
+ void CheckForChangeOutsidePaint(Range r);
+ void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
+
+ void SetAnnotationHeights(int start, int end);
+ void SetDocPointer(Document *document);
+
+ void SetAnnotationVisible(int visible);
+
+ void Expand(int &line, bool doExpand);
+ void ToggleContraction(int line);
+ void EnsureLineVisible(int lineDoc, bool enforcePolicy);
+ int GetTag(char *tagValue, int tagNumber);
+ int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);
+
+ bool PositionIsHotspot(int position);
+ bool PointIsHotspot(Point pt);
+ void SetHotSpotRange(Point *pt);
+ void GetHotSpotRange(int &hsStart, int &hsEnd);
+
+ int CodePage() const;
+ virtual bool ValidCodePage(int /* codePage */) const { return true; }
+ int WrapCount(int line);
+ void AddStyledText(char *buffer, int appendLength);
+
+ virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
+ void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ static const char *StringFromEOLMode(int eolMode);
+
+ static sptr_t StringResult(sptr_t lParam, const char *val);
+
+public:
+ // Public so the COM thunks can access it.
+ bool IsUnicodeMode() const;
+ // Public so scintilla_send_message can use it.
+ virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ // Public so scintilla_set_id can use it.
+ int ctrlID;
+ // Public so COM methods for drag and drop can set it.
+ int errorStatus;
+ friend class AutoSurface;
+ friend class SelectionLineIterator;
+};
+
+/**
+ * A smart pointer class to ensure Surfaces are set up and deleted correctly.
+ */
+class AutoSurface {
+private:
+ Surface *surf;
+public:
+ AutoSurface(Editor *ed) : surf(0) {
+ if (ed->wMain.GetID()) {
+ surf = Surface::Allocate();
+ if (surf) {
+ surf->Init(ed->wMain.GetID());
+ surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
+ surf->SetDBCSMode(ed->CodePage());
+ }
+ }
+ }
+ AutoSurface(SurfaceID sid, Editor *ed) : surf(0) {
+ if (ed->wMain.GetID()) {
+ surf = Surface::Allocate();
+ if (surf) {
+ surf->Init(sid, ed->wMain.GetID());
+ surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
+ surf->SetDBCSMode(ed->CodePage());
+ }
+ }
+ }
+ ~AutoSurface() {
+ delete surf;
+ }
+ Surface *operator->() const {
+ return surf;
+ }
+ operator Surface *() const {
+ return surf;
+ }
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/ExternalLexer.cxx b/scintilla/src/ExternalLexer.cxx
new file mode 100644
index 0000000..586a3fb
--- /dev/null
+++ b/scintilla/src/ExternalLexer.cxx
@@ -0,0 +1,262 @@
+// Scintilla source code edit control
+/** @file ExternalLexer.cxx
+ ** Support external lexers in DLLs.
+ **/
+// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <string>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "DocumentAccessor.h"
+#include "KeyWords.h"
+#include "ExternalLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+LexerManager *LexerManager::theInstance = NULL;
+
+//------------------------------------------
+//
+// ExternalLexerModule
+//
+//------------------------------------------
+
+char **WordListsToStrings(WordList *val[]) {
+ int dim = 0;
+ while (val[dim])
+ dim++;
+ char **wls = new char * [dim + 1];
+ for (int i = 0; i < dim; i++) {
+ std::string words;
+ words = "";
+ for (int n = 0; n < val[i]->len; n++) {
+ words += val[i]->words[n];
+ if (n != val[i]->len - 1)
+ words += " ";
+ }
+ wls[i] = new char[words.length() + 1];
+ strcpy(wls[i], words.c_str());
+ }
+ wls[dim] = 0;
+ return wls;
+}
+
+void DeleteWLStrings(char *strs[]) {
+ int dim = 0;
+ while (strs[dim]) {
+ delete strs[dim];
+ dim++;
+ }
+ delete [] strs;
+}
+
+void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) const {
+ if (!fneLexer)
+ return ;
+
+ char **kwds = WordListsToStrings(keywordlists);
+ char *ps = styler.GetProperties();
+
+ // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
+ // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
+ DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
+ WindowID wID = da.GetWindow();
+
+ fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
+
+ delete ps;
+ DeleteWLStrings(kwds);
+}
+
+void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) const {
+ if (!fneFolder)
+ return ;
+
+ char **kwds = WordListsToStrings(keywordlists);
+ char *ps = styler.GetProperties();
+
+ // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
+ // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
+ DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
+ WindowID wID = da.GetWindow();
+
+ fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
+
+ delete ps;
+ DeleteWLStrings(kwds);
+}
+
+void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
+ fneLexer = fLexer;
+ fneFolder = fFolder;
+ externalLanguage = index;
+}
+
+//------------------------------------------
+//
+// LexerLibrary
+//
+//------------------------------------------
+
+LexerLibrary::LexerLibrary(const char *ModuleName) {
+ // Initialise some members...
+ first = NULL;
+ last = NULL;
+
+ // Load the DLL
+ lib = DynamicLibrary::Load(ModuleName);
+ if (lib->IsValid()) {
+ m_sModuleName = ModuleName;
+ //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
+ GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
+
+ if (GetLexerCount) {
+ ExternalLexerModule *lex;
+ LexerMinder *lm;
+
+ // Find functions in the DLL
+ GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
+ ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
+ ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");
+
+ // Assign a buffer for the lexer name.
+ char lexname[100];
+ strcpy(lexname, "");
+
+ int nl = GetLexerCount();
+
+ for (int i = 0; i < nl; i++) {
+ GetLexerName(i, lexname, 100);
+ lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
+
+ // Create a LexerMinder so we don't leak the ExternalLexerModule...
+ lm = new LexerMinder;
+ lm->self = lex;
+ lm->next = NULL;
+ if (first != NULL) {
+ last->next = lm;
+ last = lm;
+ } else {
+ first = lm;
+ last = lm;
+ }
+
+ // The external lexer needs to know how to call into its DLL to
+ // do its lexing and folding, we tell it here. Folder may be null.
+ lex->SetExternal(Lexer, Folder, i);
+ }
+ }
+ }
+ next = NULL;
+}
+
+LexerLibrary::~LexerLibrary() {
+ Release();
+ delete lib;
+}
+
+void LexerLibrary::Release() {
+ //TODO maintain a list of lexers created, and delete them!
+ LexerMinder *lm;
+ LexerMinder *lmNext;
+ lm = first;
+ while (NULL != lm) {
+ lmNext = lm->next;
+ delete lm->self;
+ delete lm;
+ lm = lmNext;
+ }
+
+ first = NULL;
+ last = NULL;
+}
+
+//------------------------------------------
+//
+// LexerManager
+//
+//------------------------------------------
+
+/// Return the single LexerManager instance...
+LexerManager *LexerManager::GetInstance() {
+ if (!theInstance)
+ theInstance = new LexerManager;
+ return theInstance;
+}
+
+/// Delete any LexerManager instance...
+void LexerManager::DeleteInstance() {
+ delete theInstance;
+ theInstance = NULL;
+}
+
+/// protected constructor - this is a singleton...
+LexerManager::LexerManager() {
+ first = NULL;
+ last = NULL;
+}
+
+LexerManager::~LexerManager() {
+ Clear();
+}
+
+void LexerManager::Load(const char *path) {
+ LoadLexerLibrary(path);
+}
+
+void LexerManager::LoadLexerLibrary(const char *module) {
+ for (LexerLibrary *ll = first; ll; ll= ll->next) {
+ if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
+ return;
+ }
+ LexerLibrary *lib = new LexerLibrary(module);
+ if (NULL != first) {
+ last->next = lib;
+ last = lib;
+ } else {
+ first = lib;
+ last = lib;
+ }
+}
+
+void LexerManager::Clear() {
+ if (NULL != first) {
+ LexerLibrary *cur = first;
+ LexerLibrary *next;
+ while (cur) {
+ next = cur->next;
+ delete cur;
+ cur = next;
+ }
+ first = NULL;
+ last = NULL;
+ }
+}
+
+//------------------------------------------
+//
+// LexerManager
+//
+//------------------------------------------
+
+LMMinder::~LMMinder() {
+ LexerManager::DeleteInstance();
+}
+
+LMMinder minder;
diff --git a/scintilla/src/ExternalLexer.h b/scintilla/src/ExternalLexer.h
new file mode 100644
index 0000000..60ad4a8
--- /dev/null
+++ b/scintilla/src/ExternalLexer.h
@@ -0,0 +1,104 @@
+// Scintilla source code edit control
+/** @file ExternalLexer.h
+ ** Support external lexers in DLLs.
+ **/
+// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EXTERNALLEXER_H
+#define EXTERNALLEXER_H
+
+#if PLAT_WIN
+#define EXT_LEXER_DECL __stdcall
+#else
+#define EXT_LEXER_DECL
+#endif
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+// External Lexer function definitions...
+typedef void (EXT_LEXER_DECL *ExtLexerFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle,
+ char *words[], WindowID window, char *props);
+typedef void (EXT_LEXER_DECL *ExtFoldFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle,
+ char *words[], WindowID window, char *props);
+typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);
+typedef int (EXT_LEXER_DECL *GetLexerCountFn)();
+typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength);
+
+//class DynamicLibrary;
+
+/// Sub-class of LexerModule to use an external lexer.
+class ExternalLexerModule : protected LexerModule {
+protected:
+ ExtLexerFunction fneLexer;
+ ExtFoldFunction fneFolder;
+ int externalLanguage;
+ char name[100];
+public:
+ ExternalLexerModule(int language_, LexerFunction fnLexer_,
+ const char *languageName_=0, LexerFunction fnFolder_=0) : LexerModule(language_, fnLexer_, 0, fnFolder_) {
+ strncpy(name, languageName_, sizeof(name));
+ name[sizeof(name)-1] = '\0';
+ languageName = name;
+ }
+ 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,
+ WordList *keywordlists[], Accessor &styler) const;
+ virtual void SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index);
+};
+
+/// LexerMinder points to an ExternalLexerModule - so we don't leak them.
+class LexerMinder {
+public:
+ ExternalLexerModule *self;
+ LexerMinder *next;
+};
+
+/// LexerLibrary exists for every External Lexer DLL, contains LexerMinders.
+class LexerLibrary {
+ DynamicLibrary *lib;
+ LexerMinder *first;
+ LexerMinder *last;
+
+public:
+ LexerLibrary(const char *ModuleName);
+ ~LexerLibrary();
+ void Release();
+
+ LexerLibrary *next;
+ std::string m_sModuleName;
+};
+
+/// LexerManager manages external lexers, contains LexerLibrarys.
+class LexerManager {
+public:
+ ~LexerManager();
+
+ static LexerManager *GetInstance();
+ static void DeleteInstance();
+
+ void Load(const char *path);
+ void Clear();
+
+private:
+ LexerManager();
+ static LexerManager *theInstance;
+
+ void LoadLexerLibrary(const char *module);
+ LexerLibrary *first;
+ LexerLibrary *last;
+};
+
+class LMMinder {
+public:
+ ~LMMinder();
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/FontQuality.h b/scintilla/src/FontQuality.h
new file mode 100644
index 0000000..3ec94f0
--- /dev/null
+++ b/scintilla/src/FontQuality.h
@@ -0,0 +1,12 @@
+// Scintilla source code edit control
+/** @file FontQuality.h
+ ** Definitions to control font anti-aliasing.
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#define SC_EFF_QUALITY_MASK 0xF
+#define SC_EFF_QUALITY_DEFAULT 0
+#define SC_EFF_QUALITY_NON_ANTIALIASED 1
+#define SC_EFF_QUALITY_ANTIALIASED 2
+#define SC_EFF_QUALITY_LCD_OPTIMIZED 3
diff --git a/scintilla/src/Indicator.cxx b/scintilla/src/Indicator.cxx
new file mode 100644
index 0000000..17c60fc
--- /dev/null
+++ b/scintilla/src/Indicator.cxx
@@ -0,0 +1,81 @@
+// Scintilla source code edit control
+/** @file Indicator.cxx
+ ** Defines the style of indicators which are text decorations such as underlining.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "Indicator.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
+ surface->PenColour(fore.allocated);
+ int ymid = (rc.bottom + rc.top) / 2;
+ if (style == INDIC_SQUIGGLE) {
+ surface->MoveTo(rc.left, rc.top);
+ int x = rc.left + 2;
+ int y = 2;
+ while (x < rc.right) {
+ surface->LineTo(x, rc.top + y);
+ x += 2;
+ y = 2 - y;
+ }
+ surface->LineTo(rc.right, rc.top + y); // Finish the line
+ } else if (style == INDIC_TT) {
+ surface->MoveTo(rc.left, ymid);
+ int x = rc.left + 5;
+ while (x < rc.right) {
+ surface->LineTo(x, ymid);
+ surface->MoveTo(x-3, ymid);
+ surface->LineTo(x-3, ymid+2);
+ x++;
+ surface->MoveTo(x, ymid);
+ x += 5;
+ }
+ surface->LineTo(rc.right, ymid); // Finish the line
+ if (x - 3 <= rc.right) {
+ surface->MoveTo(x-3, ymid);
+ surface->LineTo(x-3, ymid+2);
+ }
+ } else if (style == INDIC_DIAGONAL) {
+ int x = rc.left;
+ while (x < rc.right) {
+ surface->MoveTo(x, rc.top+2);
+ int endX = x+3;
+ int endY = rc.top - 1;
+ if (endX > rc.right) {
+ endY += endX - rc.right;
+ endX = rc.right;
+ }
+ surface->LineTo(endX, endY);
+ x += 4;
+ }
+ } else if (style == INDIC_STRIKE) {
+ surface->MoveTo(rc.left, rc.top - 4);
+ surface->LineTo(rc.right, rc.top - 4);
+ } else if (style == INDIC_HIDDEN) {
+ // Draw nothing
+ } else if (style == INDIC_BOX) {
+ surface->MoveTo(rc.left, ymid+1);
+ surface->LineTo(rc.right, ymid+1);
+ surface->LineTo(rc.right, rcLine.top+1);
+ surface->LineTo(rc.left, rcLine.top+1);
+ surface->LineTo(rc.left, ymid+1);
+ } else if (style == INDIC_ROUNDBOX) {
+ PRectangle rcBox = rcLine;
+ rcBox.top = rcLine.top + 1;
+ rcBox.left = rc.left;
+ rcBox.right = rc.right;
+ surface->AlphaRectangle(rcBox, 1, fore.allocated, fillAlpha, fore.allocated, 50, 0);
+ } else { // Either INDIC_PLAIN or unknown
+ surface->MoveTo(rc.left, ymid);
+ surface->LineTo(rc.right, ymid);
+ }
+}
+
diff --git a/scintilla/src/Indicator.h b/scintilla/src/Indicator.h
new file mode 100644
index 0000000..4af686b
--- /dev/null
+++ b/scintilla/src/Indicator.h
@@ -0,0 +1,32 @@
+// Scintilla source code edit control
+/** @file Indicator.h
+ ** Defines the style of indicators which are text decorations such as underlining.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef INDICATOR_H
+#define INDICATOR_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class Indicator {
+public:
+ int style;
+ bool under;
+ ColourPair fore;
+ int fillAlpha;
+ Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30) {
+ }
+ void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/KeyMap.cxx b/scintilla/src/KeyMap.cxx
new file mode 100644
index 0000000..bab5e27
--- /dev/null
+++ b/scintilla/src/KeyMap.cxx
@@ -0,0 +1,152 @@
+// Scintilla source code edit control
+/** @file KeyMap.cxx
+ ** Defines a mapping between keystrokes and commands.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "KeyMap.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
+ for (int i = 0; MapDefault[i].key; i++) {
+ AssignCmdKey(MapDefault[i].key,
+ MapDefault[i].modifiers,
+ MapDefault[i].msg);
+ }
+}
+
+KeyMap::~KeyMap() {
+ Clear();
+}
+
+void KeyMap::Clear() {
+ delete []kmap;
+ kmap = 0;
+ len = 0;
+ alloc = 0;
+}
+
+void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) {
+ if ((len+1) >= alloc) {
+ KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
+ if (!ktcNew)
+ return;
+ for (int k = 0; k < len; k++)
+ ktcNew[k] = kmap[k];
+ alloc += 5;
+ delete []kmap;
+ kmap = ktcNew;
+ }
+ for (int keyIndex = 0; keyIndex < len; keyIndex++) {
+ if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
+ kmap[keyIndex].msg = msg;
+ return;
+ }
+ }
+ kmap[len].key = key;
+ kmap[len].modifiers = modifiers;
+ kmap[len].msg = msg;
+ len++;
+}
+
+unsigned int KeyMap::Find(int key, int modifiers) {
+ for (int i = 0; i < len; i++) {
+ if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
+ return kmap[i].msg;
+ }
+ }
+ return 0;
+}
+
+const KeyToCommand KeyMap::MapDefault[] = {
+ {SCK_DOWN, SCI_NORM, SCI_LINEDOWN},
+ {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
+ {SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN},
+ {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
+ {SCK_UP, SCI_NORM, SCI_LINEUP},
+ {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
+ {SCK_UP, SCI_CTRL, SCI_LINESCROLLUP},
+ {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
+ {'[', SCI_CTRL, SCI_PARAUP},
+ {'[', SCI_CSHIFT, SCI_PARAUPEXTEND},
+ {']', SCI_CTRL, SCI_PARADOWN},
+ {']', SCI_CSHIFT, SCI_PARADOWNEXTEND},
+ {SCK_LEFT, SCI_NORM, SCI_CHARLEFT},
+ {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
+ {SCK_LEFT, SCI_CTRL, SCI_WORDLEFT},
+ {SCK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND},
+ {SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND},
+ {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
+ {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
+ {SCK_RIGHT, SCI_CTRL, SCI_WORDRIGHT},
+ {SCK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND},
+ {SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND},
+ {'/', SCI_CTRL, SCI_WORDPARTLEFT},
+ {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
+ {'\\', SCI_CTRL, SCI_WORDPARTRIGHT},
+ {'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
+ {SCK_HOME, SCI_NORM, SCI_VCHOME},
+ {SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
+ {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
+ {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
+ {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY},
+// {SCK_HOME, SCI_ASHIFT, SCI_HOMEDISPLAYEXTEND},
+ {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
+ {SCK_END, SCI_NORM, SCI_LINEEND},
+ {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
+ {SCK_END, SCI_CTRL, SCI_DOCUMENTEND},
+ {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
+ {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY},
+// {SCK_END, SCI_ASHIFT, SCI_LINEENDDISPLAYEXTEND},
+ {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
+ {SCK_PRIOR, SCI_NORM, SCI_PAGEUP},
+ {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
+ {SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
+ {SCK_NEXT, SCI_NORM, SCI_PAGEDOWN},
+ {SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
+ {SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
+ {SCK_DELETE, SCI_NORM, SCI_CLEAR},
+ {SCK_DELETE, SCI_SHIFT, SCI_CUT},
+ {SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
+ {SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT},
+ {SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
+ {SCK_INSERT, SCI_SHIFT, SCI_PASTE},
+ {SCK_INSERT, SCI_CTRL, SCI_COPY},
+ {SCK_ESCAPE, SCI_NORM, SCI_CANCEL},
+ {SCK_BACK, SCI_NORM, SCI_DELETEBACK},
+ {SCK_BACK, SCI_SHIFT, SCI_DELETEBACK},
+ {SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
+ {SCK_BACK, SCI_ALT, SCI_UNDO},
+ {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT},
+ {'Z', SCI_CTRL, SCI_UNDO},
+ {'Y', SCI_CTRL, SCI_REDO},
+ {'X', SCI_CTRL, SCI_CUT},
+ {'C', SCI_CTRL, SCI_COPY},
+ {'V', SCI_CTRL, SCI_PASTE},
+ {'A', SCI_CTRL, SCI_SELECTALL},
+ {SCK_TAB, SCI_NORM, SCI_TAB},
+ {SCK_TAB, SCI_SHIFT, SCI_BACKTAB},
+ {SCK_RETURN, SCI_NORM, SCI_NEWLINE},
+ {SCK_RETURN, SCI_SHIFT, SCI_NEWLINE},
+ {SCK_ADD, SCI_CTRL, SCI_ZOOMIN},
+ {SCK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT},
+ {SCK_DIVIDE, SCI_CTRL, SCI_SETZOOM},
+ //'L', SCI_CTRL, SCI_FORMFEED,
+ {'L', SCI_CTRL, SCI_LINECUT},
+ {'L', SCI_CSHIFT, SCI_LINEDELETE},
+ {'T', SCI_CSHIFT, SCI_LINECOPY},
+ {'T', SCI_CTRL, SCI_LINETRANSPOSE},
+ {'D', SCI_CTRL, SCI_SELECTIONDUPLICATE},
+ {'U', SCI_CTRL, SCI_LOWERCASE},
+ {'U', SCI_CSHIFT, SCI_UPPERCASE},
+ {0,0,0},
+};
+
diff --git a/scintilla/src/KeyMap.h b/scintilla/src/KeyMap.h
new file mode 100644
index 0000000..c1b1a10
--- /dev/null
+++ b/scintilla/src/KeyMap.h
@@ -0,0 +1,51 @@
+// Scintilla source code edit control
+/** @file KeyMap.h
+ ** Defines a mapping between keystrokes and commands.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef KEYTOCOMMAND_H
+#define KEYTOCOMMAND_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+#define SCI_NORM 0
+#define SCI_SHIFT SCMOD_SHIFT
+#define SCI_CTRL SCMOD_CTRL
+#define SCI_ALT SCMOD_ALT
+#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
+#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT)
+
+/**
+ */
+class KeyToCommand {
+public:
+ int key;
+ int modifiers;
+ unsigned int msg;
+};
+
+/**
+ */
+class KeyMap {
+ KeyToCommand *kmap;
+ int len;
+ int alloc;
+ static const KeyToCommand MapDefault[];
+
+public:
+ KeyMap();
+ ~KeyMap();
+ void Clear();
+ void AssignCmdKey(int key, int modifiers, unsigned int msg);
+ unsigned int Find(int key, int modifiers); // 0 returned on failure
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/KeyWords.cxx b/scintilla/src/KeyWords.cxx
new file mode 100644
index 0000000..f5d4c6a
--- /dev/null
+++ b/scintilla/src/KeyWords.cxx
@@ -0,0 +1,429 @@
+// Scintilla source code edit control
+/** @file KeyWords.cxx
+ ** Colourise for particular languages.
+ **/
+// 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 <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/**
+ * Creates an array that points into each word in the string and puts \0 terminators
+ * after each word.
+ */
+static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) {
+ int prev = '\n';
+ int words = 0;
+ // For rapid determination of whether a character is a separator, build
+ // a look up table.
+ bool wordSeparator[256];
+ for (int i=0; i<256; i++) {
+ wordSeparator[i] = false;
+ }
+ wordSeparator['\r'] = true;
+ wordSeparator['\n'] = true;
+ if (!onlyLineEnds) {
+ wordSeparator[' '] = true;
+ wordSeparator['\t'] = true;
+ }
+ for (int j = 0; wordlist[j]; j++) {
+ int curr = static_cast<unsigned char>(wordlist[j]);
+ if (!wordSeparator[curr] && wordSeparator[prev])
+ words++;
+ prev = curr;
+ }
+ char **keywords = new char *[words + 1];
+ if (keywords) {
+ words = 0;
+ prev = '\0';
+ size_t slen = strlen(wordlist);
+ for (size_t k = 0; k < slen; k++) {
+ if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
+ if (!prev) {
+ keywords[words] = &wordlist[k];
+ words++;
+ }
+ } else {
+ wordlist[k] = '\0';
+ }
+ prev = wordlist[k];
+ }
+ keywords[words] = &wordlist[slen];
+ *len = words;
+ } else {
+ *len = 0;
+ }
+ return keywords;
+}
+
+void WordList::Clear() {
+ if (words) {
+ delete []list;
+ delete []words;
+ }
+ words = 0;
+ list = 0;
+ len = 0;
+ sorted = false;
+}
+
+void WordList::Set(const char *s) {
+ list = new char[strlen(s) + 1];
+ strcpy(list, s);
+ sorted = false;
+ words = ArrayFromWordList(list, &len, onlyLineEnds);
+}
+
+extern "C" int cmpString(const void *a1, const void *a2) {
+ // Can't work out the correct incantation to use modern casts here
+ return strcmp(*(char **)(a1), *(char **)(a2));
+}
+
+static void SortWordList(char **words, unsigned int len) {
+ qsort(reinterpret_cast<void *>(words), len, sizeof(*words),
+ cmpString);
+}
+
+bool WordList::InList(const char *s) {
+ 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 ((unsigned char)words[j][0] == firstChar) {
+ if (s[1] == words[j][1]) {
+ const char *a = words[j] + 1;
+ const char *b = s + 1;
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ if (!*a && !*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;
+}
+
+/** 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;
+}
+
+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_[],
+ int styleBits_) :
+ language(language_),
+ fnLexer(fnLexer_),
+ fnFolder(fnFolder_),
+ wordListDescriptions(wordListDescriptions_),
+ styleBits(styleBits_),
+ languageName(languageName_) {
+ next = base;
+ base = this;
+ if (language == SCLEX_AUTOMATIC) {
+ language = nextLanguage;
+ nextLanguage++;
+ }
+}
+
+int LexerModule::GetNumWordLists() const {
+ if (wordListDescriptions == NULL) {
+ return -1;
+ } else {
+ int numWordLists = 0;
+
+ while (wordListDescriptions[numWordLists]) {
+ ++numWordLists;
+ }
+
+ return numWordLists;
+ }
+}
+
+const char *LexerModule::GetWordListDescription(int index) const {
+ static const char *emptyStr = "";
+
+ PLATFORM_ASSERT(index < GetNumWordLists());
+ if (index >= GetNumWordLists()) {
+ return emptyStr;
+ } else {
+ return wordListDescriptions[index];
+ }
+}
+
+int LexerModule::GetStyleBitsNeeded() const {
+ return styleBits;
+}
+
+const LexerModule *LexerModule::Find(int language) {
+ const LexerModule *lm = base;
+ while (lm) {
+ if (lm->language == language) {
+ return lm;
+ }
+ lm = lm->next;
+ }
+ return 0;
+}
+
+const LexerModule *LexerModule::Find(const char *languageName) {
+ if (languageName) {
+ const LexerModule *lm = base;
+ while (lm) {
+ if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) {
+ return lm;
+ }
+ lm = lm->next;
+ }
+ }
+ return 0;
+}
+
+void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) const {
+ if (fnLexer)
+ fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
+}
+
+void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) const {
+ if (fnFolder) {
+ int lineCurrent = styler.GetLine(startPos);
+ // Move back one line in case deletion wrecked current line fold state
+ if (lineCurrent > 0) {
+ lineCurrent--;
+ int newStartPos = styler.LineStart(lineCurrent);
+ lengthDoc += startPos - newStartPos;
+ startPos = newStartPos;
+ initStyle = 0;
+ if (startPos > 0) {
+ initStyle = styler.StyleAt(startPos - 1);
+ }
+ }
+ fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
+ }
+}
+
+// Alternative historical name for Scintilla_LinkLexers
+int wxForceScintillaLexers(void) {
+ return Scintilla_LinkLexers();
+}
+
+// To add or remove a lexer, add or remove its file and run LexGen.py.
+
+// Force a reference to all of the Scintilla lexers so that the linker will
+// not remove the code of the lexers.
+int Scintilla_LinkLexers() {
+ static int forcer = 0;
+
+// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
+#define LINK_LEXER(lexer) extern LexerModule lexer; forcer += lexer.GetLanguage();
+
+//++Autogenerated -- run src/LexGen.py to regenerate
+//**\(\tLINK_LEXER(\*);\n\)
+ LINK_LEXER(lmAbaqus);
+ LINK_LEXER(lmAda);
+ LINK_LEXER(lmAns1);
+ LINK_LEXER(lmAPDL);
+ LINK_LEXER(lmAsm);
+ LINK_LEXER(lmASY);
+ 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(lmCmake);
+ LINK_LEXER(lmCOBOL);
+ LINK_LEXER(lmConf);
+ LINK_LEXER(lmCPP);
+ LINK_LEXER(lmCPPNoCase);
+ LINK_LEXER(lmCsound);
+ LINK_LEXER(lmCss);
+ LINK_LEXER(lmD);
+ 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(lmFreeBasic);
+ LINK_LEXER(lmGAP);
+ LINK_LEXER(lmGui4Cli);
+ LINK_LEXER(lmHaskell);
+ LINK_LEXER(lmHTML);
+ LINK_LEXER(lmInno);
+ LINK_LEXER(lmKix);
+ LINK_LEXER(lmLatex);
+ LINK_LEXER(lmLISP);
+ LINK_LEXER(lmLot);
+ LINK_LEXER(lmLout);
+ LINK_LEXER(lmLua);
+ LINK_LEXER(lmMagikSF);
+ LINK_LEXER(lmMake);
+ LINK_LEXER(lmMarkdown);
+ LINK_LEXER(lmMatlab);
+ LINK_LEXER(lmMETAPOST);
+ LINK_LEXER(lmMMIXAL);
+ LINK_LEXER(lmMSSQL);
+ LINK_LEXER(lmMySQL);
+ LINK_LEXER(lmNimrod);
+ LINK_LEXER(lmNncrontab);
+ LINK_LEXER(lmNsis);
+ LINK_LEXER(lmNull);
+ LINK_LEXER(lmOctave);
+ LINK_LEXER(lmOpal);
+ LINK_LEXER(lmPascal);
+ LINK_LEXER(lmPB);
+ LINK_LEXER(lmPerl);
+ LINK_LEXER(lmPHPSCRIPT);
+ LINK_LEXER(lmPLM);
+ LINK_LEXER(lmPo);
+ LINK_LEXER(lmPOV);
+ LINK_LEXER(lmPowerPro);
+ LINK_LEXER(lmPowerShell);
+ LINK_LEXER(lmProgress);
+ LINK_LEXER(lmProps);
+ LINK_LEXER(lmPS);
+ LINK_LEXER(lmPureBasic);
+ LINK_LEXER(lmPython);
+ LINK_LEXER(lmR);
+ LINK_LEXER(lmREBOL);
+ LINK_LEXER(lmRuby);
+ LINK_LEXER(lmScriptol);
+ LINK_LEXER(lmSmalltalk);
+ LINK_LEXER(lmSML);
+ LINK_LEXER(lmSorc);
+ LINK_LEXER(lmSpecman);
+ LINK_LEXER(lmSpice);
+ LINK_LEXER(lmSQL);
+ LINK_LEXER(lmTACL);
+ LINK_LEXER(lmTADS3);
+ LINK_LEXER(lmTAL);
+ 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
+
+ return 1;
+}
diff --git a/scintilla/src/LexAPDL.cxx b/scintilla/src/LexAPDL.cxx
new file mode 100644
index 0000000..a9a6c54
--- /dev/null
+++ b/scintilla/src/LexAPDL.cxx
@@ -0,0 +1,256 @@
+// Scintilla source code edit control
+/** @file LexAPDL.cxx
+ ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus.
+ ** By Hadar Raz.
+ **/
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80 && (isalnum(ch) || ch == '_'));
+}
+
+static inline bool IsAnOperator(char ch) {
+ // '.' 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 == ':' || ch == '%')
+ return true;
+ return false;
+}
+
+static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ int stringStart = ' ';
+
+ WordList &processors = *keywordlists[0];
+ WordList &commands = *keywordlists[1];
+ WordList &slashcommands = *keywordlists[2];
+ WordList &starcommands = *keywordlists[3];
+ WordList &arguments = *keywordlists[4];
+ WordList &functions = *keywordlists[5];
+
+ // Do not leak onto next line
+ initStyle = SCE_APDL_DEFAULT;
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_APDL_NUMBER) {
+ if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
+ ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
+ sc.SetState(SCE_APDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_APDL_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_APDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_APDL_COMMENTBLOCK) {
+ if (sc.atLineEnd) {
+ if (sc.ch == '\r') {
+ sc.Forward();
+ }
+ sc.ForwardSetState(SCE_APDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_APDL_STRING) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_APDL_DEFAULT);
+ } else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) {
+ sc.ForwardSetState(SCE_APDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_APDL_WORD) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (processors.InList(s)) {
+ sc.ChangeState(SCE_APDL_PROCESSOR);
+ } else if (slashcommands.InList(s)) {
+ sc.ChangeState(SCE_APDL_SLASHCOMMAND);
+ } else if (starcommands.InList(s)) {
+ sc.ChangeState(SCE_APDL_STARCOMMAND);
+ } else if (commands.InList(s)) {
+ sc.ChangeState(SCE_APDL_COMMAND);
+ } else if (arguments.InList(s)) {
+ sc.ChangeState(SCE_APDL_ARGUMENT);
+ } else if (functions.InList(s)) {
+ sc.ChangeState(SCE_APDL_FUNCTION);
+ }
+ sc.SetState(SCE_APDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_APDL_OPERATOR) {
+ if (!IsAnOperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_APDL_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_APDL_DEFAULT) {
+ if (sc.ch == '!' && sc.chNext == '!') {
+ sc.SetState(SCE_APDL_COMMENTBLOCK);
+ } else if (sc.ch == '!') {
+ sc.SetState(SCE_APDL_COMMENT);
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_APDL_NUMBER);
+ } else if (sc.ch == '\'' || sc.ch == '\"') {
+ sc.SetState(SCE_APDL_STRING);
+ stringStart = sc.ch;
+ } else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) {
+ sc.SetState(SCE_APDL_WORD);
+ } else if (IsAnOperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_APDL_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+//------------------------------------------------------------------------------
+// 06-27-07 Sergio Lucato
+// - Included code folding for Ansys APDL lexer
+// - Copyied from LexBasic.cxx and modified for APDL
+//------------------------------------------------------------------------------
+
+/* 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, 6, 2, 2, 2, 10, 6,
+ 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 IsIdentifier(int c) {
+ return c < 128 && (character_classification[c] & 4);
+}
+
+static int LowerCase(int c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return 'a' + c - 'A';
+ return c;
+}
+
+static int CheckAPDLFoldPoint(char const *token, int &level) {
+ if (!strcmp(token, "*if") ||
+ !strcmp(token, "*do") ||
+ !strcmp(token, "*dowhile") ) {
+ level |= SC_FOLDLEVELHEADERFLAG;
+ return 1;
+ }
+ if (!strcmp(token, "*endif") ||
+ !strcmp(token, "*enddo") ) {
+ return -1;
+ }
+ return 0;
+}
+
+static void FoldAPDLDoc(unsigned int startPos, int length, int,
+ WordList *[], Accessor &styler) {
+
+ 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 = CheckAPDLFoldPoint(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 const char * const apdlWordListDesc[] = {
+ "processors",
+ "commands",
+ "slashommands",
+ "starcommands",
+ "arguments",
+ "functions",
+ 0
+};
+
+LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc);
diff --git a/scintilla/src/LexASY.cxx b/scintilla/src/LexASY.cxx
new file mode 100644
index 0000000..8a1785a
--- /dev/null
+++ b/scintilla/src/LexASY.cxx
@@ -0,0 +1,270 @@
+// Scintilla source code edit control
+//Author: instanton (email: soft_share<at>126<dot>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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+
+ int visibleChars = 0;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart) {
+ if (sc.state == SCE_ASY_STRING) {
+ sc.SetState(SCE_ASY_STRING);
+ }
+ visibleChars = 0;
+ }
+
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\n' || sc.chNext == '\r') {
+ sc.Forward();
+ if (sc.ch == '\r' && sc.chNext == '\n') {
+ sc.Forward();
+ }
+// continuationLine = true;
+ continue;
+ }
+ }
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_ASY_OPERATOR:
+ sc.SetState(SCE_ASY_DEFAULT);
+ break;
+ case SCE_ASY_NUMBER:
+ if (!setWord.Contains(sc.ch)) {
+ sc.SetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ case SCE_ASY_IDENTIFIER:
+ if (!setWord.Contains(sc.ch) || (sc.ch == '.')) {
+ char s[1000];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_ASY_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_ASY_WORD2);
+ }
+ sc.SetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ case SCE_ASY_COMMENT:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ case SCE_ASY_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ case SCE_ASY_STRING:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_ASY_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ case SCE_ASY_CHARACTER:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_ASY_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_ASY_DEFAULT);
+ }
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_ASY_DEFAULT) {
+ if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
+ sc.SetState(SCE_ASY_IDENTIFIER);
+ } else if (sc.Match('/', '*')) {
+ sc.SetState(SCE_ASY_COMMENT);
+ sc.Forward(); //
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(SCE_ASY_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_ASY_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_ASY_CHARACTER);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_ASY_DEFAULT);
+ }
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_ASY_OPERATOR);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+static bool IsAsyCommentStyle(int style) {
+ return style == SCE_ASY_COMMENT;
+}
+
+
+static inline bool isASYidentifier(int ch) {
+ return
+ ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ;
+}
+
+static int ParseASYWord(unsigned int pos, Accessor &styler, char *word)
+{
+ int length=0;
+ char ch=styler.SafeGetCharAt(pos);
+ *word=0;
+
+ while(isASYidentifier(ch) && length<100){
+ word[length]=ch;
+ length++;
+ ch=styler.SafeGetCharAt(pos+length);
+ }
+ word[length]=0;
+ return length;
+}
+
+static bool IsASYDrawingLine(int line, Accessor &styler) {
+ int pos = styler.LineStart(line);
+ int eol_pos = styler.LineStart(line + 1) - 1;
+
+ int startpos = pos;
+ char buffer[100]="";
+
+ while (startpos<eol_pos){
+ char ch = styler[startpos];
+ ParseASYWord(startpos,styler,buffer);
+ bool drawcommands = strncmp(buffer,"draw",4)==0||
+ strncmp(buffer,"pair",4)==0||strncmp(buffer,"label",5)==0;
+ if (!drawcommands && ch!=' ') return false;
+ else if (drawcommands) return true;
+ startpos++;
+ }
+ return false;
+}
+
+static void FoldAsyDoc(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;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (foldComment && IsAsyCommentStyle(style)) {
+ if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) {
+ levelNext++;
+ } else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) {
+ levelNext--;
+ }
+ }
+ if (style == SCE_ASY_OPERATOR) {
+ if (ch == '{') {
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+
+ if (atEOL && IsASYDrawingLine(lineCurrent, styler)){
+ if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler))
+ levelNext++;
+ else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler)
+ && IsASYDrawingLine(lineCurrent + 1, styler)
+ )
+ levelNext++;
+ else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) &&
+ !IsASYDrawingLine(lineCurrent+1, styler))
+ levelNext--;
+ }
+
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!IsASpace(ch))
+ visibleChars++;
+ }
+}
+
+static const char * const asyWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ 0,
+ };
+
+LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists);
diff --git a/scintilla/src/LexAU3.cxx b/scintilla/src/LexAU3.cxx
new file mode 100644
index 0000000..bcf7929
--- /dev/null
+++ b/scintilla/src/LexAU3.cxx
@@ -0,0 +1,907 @@
+// Scintilla source code edit control
+// @file LexAU3.cxx
+// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3
+// by Jos van der Zande, jvdzande@yahoo.com
+//
+// Changes:
+// March 28, 2004 - Added the standard Folding code
+// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting
+// Fixed Number highlighting
+// Changed default isoperator to IsAOperator to have a better match to AutoIt3
+// Fixed "#comments_start" -> "#comments-start"
+// Fixed "#comments_end" -> "#comments-end"
+// Fixed Sendkeys in Strings when not terminated with }
+// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down}
+// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color.
+// Added logic for #include <xyz.au3> to treat the <> as string
+// Added underscore to IsAOperator.
+// May 17, 2004 - Changed the folding logic from indent to keyword folding.
+// Added Folding logic for blocks of single-commentlines or commentblock.
+// triggered by: fold.comment=1
+// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1
+// Added Special for #region - #endregion syntax highlight and folding.
+// May 30, 2004 - Fixed issue with continuation lines on If statements.
+// June 5, 2004 - Added comma to Operators for better readability.
+// 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.
+// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys.
+// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions.
+// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF)
+// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color.
+// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL.
+// Jul 26, 2007 - Fixed #endregion undetected bug.
+//
+// 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
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsTypeCharacter(const int ch)
+{
+ return ch == '$';
+}
+static inline bool IsAWordChar(const int ch)
+{
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(const int ch)
+{
+ return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.');
+}
+
+static inline bool IsAOperator(char ch) {
+ if (isascii(ch) && isalnum(ch))
+ return false;
+ if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
+ ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' ||
+ ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' )
+ return true;
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// GetSendKey() filters the portion before and after a/multiple space(s)
+// and return the first portion to be looked-up in the table
+// also check if the second portion is valid... (up,down.on.off,toggle or a number)
+///////////////////////////////////////////////////////////////////////////////
+
+static int GetSendKey(const char *szLine, char *szKey)
+{
+ int nFlag = 0;
+ int nStartFound = 0;
+ int nKeyPos = 0;
+ int nSpecPos= 0;
+ int nSpecNum= 1;
+ int nPos = 0;
+ char cTemp;
+ char szSpecial[100];
+
+ // split the portion of the sendkey in the part before and after the spaces
+ while ( ( (cTemp = szLine[nPos]) != '\0'))
+ {
+ // skip leading Ctrl/Shift/Alt state
+ if (cTemp == '{') {
+ nStartFound = 1;
+ }
+ //
+ if (nStartFound == 1) {
+ if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
+ {
+ nFlag = 1;
+ // Add } to the end of the first bit for table lookup later.
+ szKey[nKeyPos++] = '}';
+ }
+ else if (cTemp == ' ')
+ {
+ // skip other spaces
+ }
+ else if (nFlag == 0)
+ {
+ // save first portion into var till space or } is hit
+ szKey[nKeyPos++] = cTemp;
+ }
+ else if ((nFlag == 1) && (cTemp != '}'))
+ {
+ // Save second portion into var...
+ szSpecial[nSpecPos++] = cTemp;
+ // check if Second portion is all numbers for repeat fuction
+ if (isdigit(cTemp) == false) {nSpecNum = 0;}
+ }
+ }
+ nPos++; // skip to next char
+
+ } // End While
+
+
+ // Check if the second portion is either a number or one of these keywords
+ szKey[nKeyPos] = '\0';
+ szSpecial[nSpecPos] = '\0';
+ if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 ||
+ strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 ||
+ strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 )
+ {
+ nFlag = 0;
+ }
+ else
+ {
+ nFlag = 1;
+ }
+ return nFlag; // 1 is bad, 0 is good
+
+} // 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[],
+ 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];
+ // 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
+ 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:
+ {
+ //Reset at line end
+ if (sc.atLineEnd) {
+ ci=0;
+ if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) {
+ if (sc.atLineEnd)
+ sc.SetState(SCE_AU3_DEFAULT);
+ else
+ sc.SetState(SCE_AU3_COMMENTBLOCK);
+ }
+ break;
+ }
+ //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
+ else
+ ci=2; // line doesn't begin with #CE so skip the rest of the line
+ }
+ break;
+ }
+ case SCE_AU3_COMMENT:
+ {
+ if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+ break;
+ }
+ case SCE_AU3_OPERATOR:
+ {
+ // 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.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
+ if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+ break;
+ }
+ case SCE_AU3_KEYWORD:
+ {
+ if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0))))
+ {
+ if (!IsTypeCharacter(sc.ch))
+ {
+ if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 )
+ {
+ sc.ChangeState(SCE_AU3_COMMENTBLOCK);
+ sc.SetState(SCE_AU3_COMMENTBLOCK);
+ break;
+ }
+ else if (keywords.InList(s)) {
+ sc.ChangeState(SCE_AU3_KEYWORD);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_AU3_FUNCTION);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_AU3_MACRO);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_AU3_PREPROCESSOR);
+ sc.SetState(SCE_AU3_DEFAULT);
+ if (strcmp(s, "#include")== 0)
+ {
+ si = 3; // use to determine string start for #inlude <>
+ }
+ }
+ else if (keywords6.InList(s)) {
+ 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 (keywords8.InList(s)) {
+ sc.ChangeState(SCE_AU3_UDF);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ else if (strcmp(s, "_") == 0) {
+ sc.ChangeState(SCE_AU3_OPERATOR);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ else if (!IsAWordChar(sc.ch)) {
+ sc.ChangeState(SCE_AU3_DEFAULT);
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ }
+ }
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_AU3_DEFAULT);}
+ break;
+ }
+ case SCE_AU3_NUMBER:
+ {
+ // 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_COMOBJ:
+ {
+ if (!(IsAWordChar(sc.ch))) {
+ sc.SetState(SCE_AU3_DEFAULT);
+ }
+ break;
+ }
+ case SCE_AU3_STRING:
+ {
+ // check for " to end a double qouted string or
+ // check for ' to end a single qouted string
+ if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>'))
+ {
+ sc.ForwardSetState(SCE_AU3_DEFAULT);
+ si=0;
+ break;
+ }
+ if (sc.atLineEnd)
+ {
+ si=0;
+ // 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);
+ break;
+ }
+ }
+ // find Sendkeys in a STRING
+ if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) {
+ sc.SetState(SCE_AU3_SENT);}
+ break;
+ }
+
+ case 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,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);
+ }
+ else
+ {
+ // check if the start is a valid SendKey start
+ int nPos = 0;
+ int nState = 1;
+ char cTemp;
+ while (!(nState == 2) && ((cTemp = s[nPos]) != '\0'))
+ {
+ if (cTemp == '{' && nState == 1)
+ {
+ nState = 2;
+ }
+ if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' ))
+ {
+ nState = 0;
+ }
+ nPos++;
+ }
+ //Verify characters infront of { ... if not assume regular string
+ if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) {
+ sc.ChangeState(SCE_AU3_STRING);
+ sc.SetState(SCE_AU3_STRING);
+ }
+ // If invalid character found then assume its a regular string
+ if (nState == 0) {
+ 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);
+ si = 0; // reset string indicator
+ }
+ //* check in next characters following a sentkey are again a sent key
+ // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{}
+ if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) {
+ sc.SetState(SCE_AU3_SENT);}
+ // check to see if the string ended...
+ // Sendkey string isn't complete but the string ended....
+ if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
+ {
+ sc.ChangeState(SCE_AU3_STRING);
+ sc.ForwardSetState(SCE_AU3_DEFAULT);
+ }
+ break;
+ }
+ } //switch (sc.state)
+
+ // Determine if a new state should be entered:
+
+ if (sc.state == SCE_AU3_DEFAULT)
+ {
+ 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 == '_') {sc.SetState(SCE_AU3_KEYWORD);}
+ else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include
+ else if (sc.ch == '\"') {
+ sc.SetState(SCE_AU3_STRING);
+ si = 1; }
+ 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);
+ 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())
+
+ //*************************************
+ // 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 if (keywords8.InList(s_save)) {
+ sc.ChangeState(SCE_AU3_UDF);
+ sc.SetState(SCE_AU3_UDF);
+ }
+ 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();
+}
+
+//
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK;
+}
+
+//
+// Routine to find first none space on the current line and return its Style
+// needed for comment lines not starting on pos 1
+static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
+{
+ int nsPos = styler.LineStart(szLine);
+ int nePos = styler.LineStart(szLine+1) - 1;
+ while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos)
+ {
+ nsPos++; // skip to next char
+
+ } // End While
+ return styler.StyleAt(nsPos);
+
+} // GetStyleFirstWord()
+
+
+//
+static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ int endPos = startPos + length;
+ // get settings from the config files for folding comments and preprocessor lines
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
+ // 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);
+ }
+ }
+ // vars for style of previous/current/next lines
+ int style = GetStyleFirstWord(lineCurrent,styler);
+ int stylePrev = 0;
+ // find the first previous line without continuation character at the end
+ while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
+ (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
+ lineCurrent--;
+ startPos = styler.LineStart(lineCurrent);
+ }
+ if (lineCurrent > 0) {
+ stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
+ }
+ // vars for getting first word to check for keywords
+ bool FirstWordStart = false;
+ bool FirstWordEnd = false;
+ char szKeyword[11]="";
+ int szKeywordlen = 0;
+ char szThen[5]="";
+ int szThenlen = 0;
+ bool ThenFoundLast = false;
+ // var for indentlevel
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ int levelNext = levelCurrent;
+ //
+ int visibleChars = 0;
+ char chNext = styler.SafeGetCharAt(startPos);
+ char chPrev = ' ';
+ //
+ for (int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ if (IsAWordChar(ch)) {
+ visibleChars++;
+ }
+ // get the syle for the current character neede to check in comment
+ int stylech = styler.StyleAt(i);
+ // get first word for the line for indent check max 9 characters
+ if (FirstWordStart && (!(FirstWordEnd))) {
+ if (!IsAWordChar(ch)) {
+ FirstWordEnd = true;
+ szKeyword[szKeywordlen] = '\0';
+ }
+ else {
+ if (szKeywordlen < 10) {
+ szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
+ }
+ }
+ }
+ // start the capture of the first word
+ if (!(FirstWordStart)) {
+ if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') {
+ FirstWordStart = true;
+ szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
+ }
+ }
+ // only process this logic when not in comment section
+ if (!(stylech == SCE_AU3_COMMENT)) {
+ if (ThenFoundLast) {
+ if (IsAWordChar(ch)) {
+ ThenFoundLast = false;
+ }
+ }
+ // find out if the word "then" is the last on a "if" line
+ if (FirstWordEnd && strcmp(szKeyword,"if") == 0) {
+ if (szThenlen == 4) {
+ szThen[0] = szThen[1];
+ szThen[1] = szThen[2];
+ szThen[2] = szThen[3];
+ szThen[3] = static_cast<char>(tolower(ch));
+ if (strcmp(szThen,"then") == 0 ) {
+ ThenFoundLast = true;
+ }
+ }
+ else {
+ szThen[szThenlen++] = static_cast<char>(tolower(ch));
+ if (szThenlen == 5) {
+ szThen[4] = '\0';
+ }
+ }
+ }
+ }
+ // End of Line found so process the information
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+ // **************************
+ // Folding logic for Keywords
+ // **************************
+ // if a keyword is found on the current line and the line doesn't end with _ (continuation)
+ // and we are not inside a commentblock.
+ if (szKeywordlen > 0 && (!(chPrev == '_')) &&
+ ((!(IsStreamCommentStyle(style)) || foldInComment)) ) {
+ szKeyword[szKeywordlen] = '\0';
+ // only fold "if" last keyword is "then" (else its a one line if)
+ if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) {
+ levelNext++;
+ }
+ // 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,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) {
+ levelNext++;
+ }
+ // 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,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){
+ levelNext--;
+ levelCurrent--;
+ }
+ // end the fold for these words before the current line and Start new fold
+ if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 ||
+ strcmp(szKeyword,"elseif") == 0 ) {
+ levelCurrent--;
+ }
+ // end the double fold for this word before the current line
+ if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) {
+ levelNext--;
+ levelNext--;
+ levelCurrent--;
+ levelCurrent--;
+ }
+ // end the fold for these words on the current line
+ if (strcmp(szKeyword,"#endregion") == 0 ) {
+ levelNext--;
+ }
+ }
+ // Preprocessor and Comment folding
+ int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
+ // *************************************
+ // Folding logic for preprocessor blocks
+ // *************************************
+ // process preprosessor line
+ if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) {
+ if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) {
+ levelNext++;
+ }
+ // fold till the last line for normal comment lines
+ else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) {
+ levelNext--;
+ }
+ }
+ // *********************************
+ // Folding logic for Comment blocks
+ // *********************************
+ if (foldComment && IsStreamCommentStyle(style)) {
+ // Start of a comment block
+ if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) {
+ levelNext++;
+ }
+ // fold till the last line for normal comment lines
+ else if (IsStreamCommentStyle(stylePrev)
+ && !(styleNext == SCE_AU3_COMMENT)
+ && stylePrev == SCE_AU3_COMMENT
+ && style == SCE_AU3_COMMENT) {
+ levelNext--;
+ }
+ // fold till the one but last line for Blockcomment lines
+ else if (IsStreamCommentStyle(stylePrev)
+ && !(styleNext == SCE_AU3_COMMENTBLOCK)
+ && style == SCE_AU3_COMMENTBLOCK) {
+ levelNext--;
+ levelCurrent--;
+ }
+ }
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ // reset values for the next line
+ lineCurrent++;
+ stylePrev = style;
+ style = styleNext;
+ levelCurrent = levelNext;
+ visibleChars = 0;
+ // if the last character is an Underscore then don't reset since the line continues on the next line.
+ if (!(chPrev == '_')) {
+ szKeywordlen = 0;
+ szThenlen = 0;
+ FirstWordStart = false;
+ FirstWordEnd = false;
+ ThenFoundLast = false;
+ }
+ }
+ // save the last processed character
+ if (!isspacechar(ch)) {
+ chPrev = ch;
+ visibleChars++;
+ }
+ }
+}
+
+
+//
+
+static const char * const AU3WordLists[] = {
+ "#autoit keywords",
+ "#autoit functions",
+ "#autoit macros",
+ "#autoit Sent keys",
+ "#autoit Pre-processors",
+ "#autoit Special",
+ "#autoit Expand",
+ "#autoit UDF",
+ 0
+};
+LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
diff --git a/scintilla/src/LexAVE.cxx b/scintilla/src/LexAVE.cxx
new file mode 100644
index 0000000..4c1758e
--- /dev/null
+++ b/scintilla/src/LexAVE.cxx
@@ -0,0 +1,228 @@
+// SciTE - Scintilla based Text Editor
+/** @file LexAVE.cxx
+ ** Lexer for Avenue.
+ **
+ ** Written by Alexey Yutkin <yutkin@geol.msu.ru>.
+ **/
+// 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 <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+static inline bool IsEnumChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch)|| ch == '_');
+}
+static inline bool IsANumberChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' );
+}
+
+inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+inline bool isAveOperator(char ch) {
+ if (isascii(ch) && 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 == '.' )
+ return true;
+ return false;
+}
+
+static void ColouriseAveDoc(
+ 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];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_AVE_STRINGEOL) {
+ initStyle = SCE_AVE_DEFAULT;
+ }
+
+ 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
+ int currentLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(currentLine, 0);
+ }
+ if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) {
+ // Prevent SCE_AVE_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_AVE_STRING);
+ }
+
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_AVE_OPERATOR) {
+ sc.SetState(SCE_AVE_DEFAULT);
+ } else if (sc.state == SCE_AVE_NUMBER) {
+ if (!IsANumberChar(sc.ch)) {
+ sc.SetState(SCE_AVE_DEFAULT);
+ }
+ } else if (sc.state == SCE_AVE_ENUM) {
+ if (!IsEnumChar(sc.ch)) {
+ sc.SetState(SCE_AVE_DEFAULT);
+ }
+ } else if (sc.state == SCE_AVE_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+ char s[100];
+ //sc.GetCurrent(s, sizeof(s));
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD4);
+ } else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD5);
+ } else if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_AVE_WORD6);
+ }
+ sc.SetState(SCE_AVE_DEFAULT);
+ }
+ } else if (sc.state == SCE_AVE_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_AVE_DEFAULT);
+ }
+ } else if (sc.state == SCE_AVE_STRING) {
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_AVE_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_AVE_STRINGEOL);
+ sc.ForwardSetState(SCE_AVE_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_AVE_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_AVE_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_AVE_IDENTIFIER);
+ } else if (sc.Match('\"')) {
+ sc.SetState(SCE_AVE_STRING);
+ } else if (sc.Match('\'')) {
+ sc.SetState(SCE_AVE_COMMENT);
+ sc.Forward();
+ } else if (isAveOperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_AVE_OPERATOR);
+ } else if (sc.Match('#')) {
+ sc.SetState(SCE_AVE_ENUM);
+ sc.Forward();
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldAveDoc(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 = static_cast<char>(tolower(styler[startPos]));
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ int styleNext = styler.StyleAt(startPos);
+ char s[10];
+
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ char ch = static_cast<char>(tolower(chNext));
+ chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
+ int style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (style == SCE_AVE_WORD) {
+ if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') {
+ for (unsigned int j = 0; j < 6; j++) {
+ if (!iswordchar(styler[i + j])) {
+ break;
+ }
+ s[j] = static_cast<char>(tolower(styler[i + j]));
+ s[j + 1] = '\0';
+ }
+
+ if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
+ levelCurrent++;
+ }
+ 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--;
+ }
+ }
+ } else if (style == SCE_AVE_OPERATOR) {
+ if (ch == '{' || ch == '(') {
+ levelCurrent++;
+ } else if (ch == '}' || ch == ')') {
+ 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);
+}
+
+LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc);
+
diff --git a/scintilla/src/LexAbaqus.cxx b/scintilla/src/LexAbaqus.cxx
new file mode 100644
index 0000000..051a8f4
--- /dev/null
+++ b/scintilla/src/LexAbaqus.cxx
@@ -0,0 +1,617 @@
+// Scintilla source code edit control
+/** @file LexABAQUS.cxx
+ ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz.
+ ** By Sergio Lucato.
+ ** Sort of completely rewritten by Gertjan Kloosterman
+ **/
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// Code folding copyied and modified from LexBasic.cxx
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80 && (isalnum(ch) || (ch == '_')));
+}
+
+static inline bool IsAKeywordChar(const int ch) {
+ return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' ')));
+}
+
+static inline bool IsASetChar(const int ch) {
+ return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-')));
+}
+
+static inline bool IsAnOperator(char ch) {
+ // '.' 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 == ':' || ch == '%')
+ return true;
+ return false;
+}
+
+static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */,
+ Accessor &styler) {
+ enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \
+ DAT_LINE_VAL, DAT_LINE_COMMA,\
+ COMMENT_LINE,\
+ ST_ERROR, LINE_END } state ;
+
+ // Do not leak onto next line
+ state = LINE_END ;
+ initStyle = SCE_ABAQUS_DEFAULT;
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ // Things are actually quite simple
+ // we have commentlines
+ // keywordlines and datalines
+ // On a data line there will only be colouring of numbers
+ // a keyword line is constructed as
+ // *word,[ paramname[=paramvalue]]*
+ // if the line ends with a , the keyword line continues onto the new line
+
+ for (; sc.More(); sc.Forward()) {
+ switch ( state ) {
+ case KW_LINE_KW :
+ if ( sc.atLineEnd ) {
+ // finished the line in keyword state, switch to LINE_END
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ } else if ( IsAKeywordChar(sc.ch) ) {
+ // nothing changes
+ state = KW_LINE_KW ;
+ } else if ( sc.ch == ',' ) {
+ // Well well we say a comma, arguments *MUST* follow
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = KW_LINE_COMMA ;
+ } else {
+ // Flag an error
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ // Done with processing
+ break ;
+ case KW_LINE_COMMA :
+ // acomma on a keywordline was seen
+ if ( IsAKeywordChar(sc.ch)) {
+ sc.SetState(SCE_ABAQUS_ARGUMENT) ;
+ state = KW_LINE_PAR ;
+ } else if ( sc.atLineEnd || (sc.ch == ',') ) {
+ // we remain in keyword mode
+ state = KW_LINE_COMMA ;
+ } else if ( sc.ch == ' ' ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = KW_LINE_COMMA ;
+ } else {
+ // Anything else constitutes an error
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case KW_LINE_PAR :
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) {
+ // remain in this state
+ state = KW_LINE_PAR ;
+ } else if ( sc.ch == ',' ) {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = KW_LINE_COMMA ;
+ } else if ( sc.ch == '=' ) {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = KW_LINE_EQ ;
+ } else {
+ // Anything else constitutes an error
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case KW_LINE_EQ :
+ if ( sc.ch == ' ' ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ // remain in this state
+ state = KW_LINE_EQ ;
+ } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) {
+ sc.SetState(SCE_ABAQUS_NUMBER) ;
+ state = KW_LINE_VAL ;
+ } else if ( IsAKeywordChar(sc.ch) ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = KW_LINE_VAL ;
+ } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
+ sc.SetState(SCE_ABAQUS_STRING) ;
+ state = KW_LINE_VAL ;
+ } else {
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case KW_LINE_VAL :
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) {
+ // nothing changes
+ state = KW_LINE_VAL ;
+ } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
+ ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) &&
+ (sc.state == SCE_ABAQUS_NUMBER)) {
+ // remain in number mode
+ state = KW_LINE_VAL ;
+ } else if (sc.state == SCE_ABAQUS_STRING) {
+ // accept everything until a closing quote
+ if ( sc.ch == '\'' || sc.ch == '\"' ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = KW_LINE_VAL ;
+ }
+ } else if ( sc.ch == ',' ) {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = KW_LINE_COMMA ;
+ } else {
+ // anything else is an error
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case DAT_LINE_VAL :
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) {
+ // nothing changes
+ state = DAT_LINE_VAL ;
+ } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
+ ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) &&
+ (sc.state == SCE_ABAQUS_NUMBER)) {
+ // remain in number mode
+ state = DAT_LINE_VAL ;
+ } else if (sc.state == SCE_ABAQUS_STRING) {
+ // accept everything until a closing quote
+ if ( sc.ch == '\'' || sc.ch == '\"' ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = DAT_LINE_VAL ;
+ }
+ } else if ( sc.ch == ',' ) {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = DAT_LINE_COMMA ;
+ } else {
+ // anything else is an error
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case DAT_LINE_COMMA :
+ // a comma on a data line was seen
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ } else if ( sc.ch == ' ' ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = DAT_LINE_COMMA ;
+ } else if (sc.ch == ',') {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = DAT_LINE_COMMA ;
+ } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) {
+ sc.SetState(SCE_ABAQUS_NUMBER) ;
+ state = DAT_LINE_VAL ;
+ } else if ( IsAKeywordChar(sc.ch) ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = DAT_LINE_VAL ;
+ } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
+ sc.SetState(SCE_ABAQUS_STRING) ;
+ state = DAT_LINE_VAL ;
+ } else {
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ break ;
+ case COMMENT_LINE :
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ }
+ break ;
+ case ST_ERROR :
+ if ( sc.atLineEnd ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = LINE_END ;
+ }
+ break ;
+ case LINE_END :
+ if ( sc.atLineEnd || sc.ch == ' ' ) {
+ // nothing changes
+ state = LINE_END ;
+ } else if ( sc.ch == '*' ) {
+ if ( sc.chNext == '*' ) {
+ state = COMMENT_LINE ;
+ sc.SetState(SCE_ABAQUS_COMMENT) ;
+ } else {
+ state = KW_LINE_KW ;
+ sc.SetState(SCE_ABAQUS_STARCOMMAND) ;
+ }
+ } else {
+ // it must be a data line, things are as if we are in DAT_LINE_COMMA
+ if ( sc.ch == ',' ) {
+ sc.SetState(SCE_ABAQUS_OPERATOR) ;
+ state = DAT_LINE_COMMA ;
+ } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) {
+ sc.SetState(SCE_ABAQUS_NUMBER) ;
+ state = DAT_LINE_VAL ;
+ } else if ( IsAKeywordChar(sc.ch) ) {
+ sc.SetState(SCE_ABAQUS_DEFAULT) ;
+ state = DAT_LINE_VAL ;
+ } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
+ sc.SetState(SCE_ABAQUS_STRING) ;
+ state = DAT_LINE_VAL ;
+ } else {
+ sc.SetState(SCE_ABAQUS_PROCESSOR) ;
+ state = ST_ERROR ;
+ }
+ }
+ break ;
+ }
+ }
+ sc.Complete();
+}
+
+//------------------------------------------------------------------------------
+// This copyied and modified from LexBasic.cxx
+//------------------------------------------------------------------------------
+
+/* 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, 6, 2, 2, 2, 10, 6,
+ 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 IsIdentifier(int c) {
+ return c < 128 && (character_classification[c] & 4);
+}
+
+static int LowerCase(int c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return 'a' + c - 'A';
+ return c;
+}
+
+static int LineEnd(int line, Accessor &styler)
+{
+ const int docLines = styler.GetLine(styler.Length() - 1); // Available last line
+ int eol_pos ;
+ // if the line is the last line, the eol_pos is styler.Length()
+ // eol will contain a new line, or a virtual new line
+ if ( docLines == line )
+ eol_pos = styler.Length() ;
+ else
+ eol_pos = styler.LineStart(line + 1) - 1;
+ return eol_pos ;
+}
+
+static int LineStart(int line, Accessor &styler)
+{
+ return styler.LineStart(line) ;
+}
+
+// LineType
+//
+// bits determines the line type
+// 1 : data line
+// 2 : only whitespace
+// 3 : data line with only whitespace
+// 4 : keyword line
+// 5 : block open keyword line
+// 6 : block close keyword line
+// 7 : keyword line in error
+// 8 : comment line
+static int LineType(int line, Accessor &styler) {
+ int pos = LineStart(line, styler) ;
+ int eol_pos = LineEnd(line, styler) ;
+
+ int c ;
+ char ch = ' ';
+
+ int i = pos ;
+ while ( i < eol_pos ) {
+ c = styler.SafeGetCharAt(i);
+ ch = static_cast<char>(LowerCase(c));
+ // We can say something as soon as no whitespace
+ // was encountered
+ if ( !IsSpace(c) )
+ break ;
+ i++ ;
+ }
+
+ if ( i >= eol_pos ) {
+ // This is a whitespace line, currently
+ // classifies as data line
+ return 3 ;
+ }
+
+ if ( ch != '*' ) {
+ // This is a data line
+ return 1 ;
+ }
+
+ if ( i == eol_pos - 1 ) {
+ // Only a single *, error but make keyword line
+ return 4+3 ;
+ }
+
+ // This means we can have a second character
+ // if that is also a * this means a comment
+ // otherwise it is a keyword.
+ c = styler.SafeGetCharAt(i+1);
+ ch = static_cast<char>(LowerCase(c));
+ if ( ch == '*' ) {
+ return 8 ;
+ }
+
+ // At this point we know this is a keyword line
+ // the character at position i is a *
+ // it is not a comment line
+ char word[256] ;
+ int wlen = 0;
+
+ word[wlen] = '*' ;
+ wlen++ ;
+
+ i++ ;
+ while ( (i < eol_pos) && (wlen < 255) ) {
+ c = styler.SafeGetCharAt(i);
+ ch = static_cast<char>(LowerCase(c));
+
+ if ( (!IsSpace(c)) && (!IsIdentifier(c)) )
+ break ;
+
+ if ( IsIdentifier(c) ) {
+ word[wlen] = ch ;
+ wlen++ ;
+ }
+
+ i++ ;
+ }
+
+ word[wlen] = 0 ;
+
+ // Make a comparison
+ if ( !strcmp(word, "*step") ||
+ !strcmp(word, "*part") ||
+ !strcmp(word, "*instance") ||
+ !strcmp(word, "*assembly")) {
+ return 4+1 ;
+ }
+
+ if ( !strcmp(word, "*endstep") ||
+ !strcmp(word, "*endpart") ||
+ !strcmp(word, "*endinstance") ||
+ !strcmp(word, "*endassembly")) {
+ return 4+2 ;
+ }
+
+ return 4 ;
+}
+
+static void SafeSetLevel(int line, int level, Accessor &styler)
+{
+ if ( line < 0 )
+ return ;
+
+ int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG));
+
+ if ( (level & mask) < 0 )
+ return ;
+
+ if ( styler.LevelAt(line) != level )
+ styler.SetLevel(line, level) ;
+}
+
+static void FoldABAQUSDoc(unsigned int startPos, int length, int,
+WordList *[], Accessor &styler) {
+ int startLine = styler.GetLine(startPos) ;
+ int endLine = styler.GetLine(startPos+length-1) ;
+
+ // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ // We want to deal with all the cases
+ // To know the correct indentlevel, we need to look back to the
+ // previous command line indentation level
+ // order of formatting keyline datalines commentlines
+ int beginData = -1 ;
+ int beginComment = -1 ;
+ int prvKeyLine = startLine ;
+ int prvKeyLineTp = 0 ;
+
+ // Scan until we find the previous keyword line
+ // this will give us the level reference that we need
+ while ( prvKeyLine > 0 ) {
+ prvKeyLine-- ;
+ prvKeyLineTp = LineType(prvKeyLine, styler) ;
+ if ( prvKeyLineTp & 4 )
+ break ;
+ }
+
+ // Determine the base line level of all lines following
+ // the previous keyword
+ // new keyword lines are placed on this level
+ //if ( prvKeyLineTp & 4 ) {
+ int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ;
+ //}
+
+ // uncomment line below if weird behaviour continues
+ prvKeyLine = -1 ;
+
+ // Now start scanning over the lines.
+ for ( int line = startLine; line <= endLine; line++ ) {
+ int lineType = LineType(line, styler) ;
+
+ // Check for comment line
+ if ( lineType == 8 ) {
+ if ( beginComment < 0 ) {
+ beginComment = line ;
+ }
+ }
+
+ // Check for data line
+ if ( (lineType == 1) || (lineType == 3) ) {
+ if ( beginData < 0 ) {
+ if ( beginComment >= 0 ) {
+ beginData = beginComment ;
+ } else {
+ beginData = line ;
+ }
+ }
+ beginComment = -1 ;
+ }
+
+ // Check for keywordline.
+ // As soon as a keyword line is encountered, we can set the
+ // levels of everything from the previous keyword line to this one
+ if ( lineType & 4 ) {
+ // this is a keyword, we can now place the previous keyword
+ // all its data lines and the remainder
+
+ // Write comments and data line
+ if ( beginComment < 0 ) {
+ beginComment = line ;
+ }
+
+ if ( beginData < 0 ) {
+ beginData = beginComment ;
+ if ( prvKeyLineTp != 5 )
+ SafeSetLevel(prvKeyLine, level, styler) ;
+ else
+ SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
+ } else {
+ SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
+ }
+
+ int datLevel = level + 1 ;
+ if ( !(prvKeyLineTp & 4) ) {
+ datLevel = level ;
+ }
+
+ for ( int ll = beginData; ll < beginComment; ll++ )
+ SafeSetLevel(ll, datLevel, styler) ;
+
+ // The keyword we just found is going to be written at another level
+ // if we have a type 5 and type 6
+ if ( prvKeyLineTp == 5 ) {
+ level += 1 ;
+ }
+
+ if ( prvKeyLineTp == 6 ) {
+ level -= 1 ;
+ if ( level < 0 ) {
+ level = 0 ;
+ }
+ }
+
+ for ( int lll = beginComment; lll < line; lll++ )
+ SafeSetLevel(lll, level, styler) ;
+
+ // wrap and reset
+ beginComment = -1 ;
+ beginData = -1 ;
+ prvKeyLine = line ;
+ prvKeyLineTp = lineType ;
+ }
+
+ }
+
+ if ( beginComment < 0 ) {
+ beginComment = endLine + 1 ;
+ } else {
+ // We need to find out whether this comment block is followed by
+ // a data line or a keyword line
+ const int docLines = styler.GetLine(styler.Length() - 1);
+
+ for ( int line = endLine + 1; line <= docLines; line++ ) {
+ int lineType = LineType(line, styler) ;
+
+ if ( lineType != 8 ) {
+ if ( !(lineType & 4) ) {
+ beginComment = endLine + 1 ;
+ }
+ break ;
+ }
+ }
+ }
+
+ if ( beginData < 0 ) {
+ beginData = beginComment ;
+ if ( prvKeyLineTp != 5 )
+ SafeSetLevel(prvKeyLine, level, styler) ;
+ else
+ SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
+ } else {
+ SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
+ }
+
+ int datLevel = level + 1 ;
+ if ( !(prvKeyLineTp & 4) ) {
+ datLevel = level ;
+ }
+
+ for ( int ll = beginData; ll < beginComment; ll++ )
+ SafeSetLevel(ll, datLevel, styler) ;
+
+ if ( prvKeyLineTp == 5 ) {
+ level += 1 ;
+ }
+
+ if ( prvKeyLineTp == 6 ) {
+ level -= 1 ;
+ }
+ for ( int m = beginComment; m <= endLine; m++ )
+ SafeSetLevel(m, level, styler) ;
+}
+
+static const char * const abaqusWordListDesc[] = {
+ "processors",
+ "commands",
+ "slashommands",
+ "starcommands",
+ "arguments",
+ "functions",
+ 0
+};
+
+LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc);
diff --git a/scintilla/src/LexAda.cxx b/scintilla/src/LexAda.cxx
new file mode 100644
index 0000000..ebd23cc
--- /dev/null
+++ b/scintilla/src/LexAda.cxx
@@ -0,0 +1,525 @@
+// Scintilla source code edit control
+/** @file LexAda.cxx
+ ** Lexer for Ada 95
+ **/
+// Copyright 2002 by Sergey Koshcheyev <sergey.k@seznam.cz>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "Platform.h"
+
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
+#include "KeyWords.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+ * Interface
+ */
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler);
+
+static const char * const adaWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc);
+
+/*
+ * Implementation
+ */
+
+// Functions that have apostropheStartsAttribute as a parameter set it according to whether
+// an apostrophe encountered after processing the current token will start an attribute or
+// a character literal.
+static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL);
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);
+
+static inline bool IsDelimiterCharacter(int ch);
+static inline bool IsNumberStartCharacter(int ch);
+static inline bool IsNumberCharacter(int ch);
+static inline bool IsSeparatorOrDelimiterCharacter(int ch);
+static bool IsValidIdentifier(const std::string& identifier);
+static bool IsValidNumber(const std::string& number);
+static inline bool IsWordStartCharacter(int ch);
+static inline bool IsWordCharacter(int ch);
+
+static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+
+ sc.SetState(SCE_ADA_CHARACTER);
+
+ // Skip the apostrophe and one more character (so that '' is shown as non-terminated and '''
+ // is handled correctly)
+ sc.Forward();
+ sc.Forward();
+
+ ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL);
+}
+
+static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) {
+ while (!sc.atLineEnd && !sc.Match(chEnd)) {
+ sc.Forward();
+ }
+
+ if (!sc.atLineEnd) {
+ sc.ForwardSetState(SCE_ADA_DEFAULT);
+ } else {
+ sc.ChangeState(stateEOL);
+ }
+}
+
+static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
+ // Apostrophe meaning is not changed, but the parameter is present for uniformity
+
+ sc.SetState(SCE_ADA_COMMENTLINE);
+
+ while (!sc.atLineEnd) {
+ sc.Forward();
+ }
+}
+
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = sc.Match (')');
+ sc.SetState(SCE_ADA_DELIMITER);
+ sc.ForwardSetState(SCE_ADA_DEFAULT);
+}
+
+static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = false;
+
+ sc.SetState(SCE_ADA_LABEL);
+
+ // Skip "<<"
+ sc.Forward();
+ sc.Forward();
+
+ std::string identifier;
+
+ while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
+ identifier += static_cast<char>(tolower(sc.ch));
+ sc.Forward();
+ }
+
+ // Skip ">>"
+ if (sc.Match('>', '>')) {
+ sc.Forward();
+ sc.Forward();
+ } else {
+ sc.ChangeState(SCE_ADA_ILLEGAL);
+ }
+
+ // If the name is an invalid identifier or a keyword, then make it invalid label
+ if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) {
+ sc.ChangeState(SCE_ADA_ILLEGAL);
+ }
+
+ sc.SetState(SCE_ADA_DEFAULT);
+
+}
+
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+
+ std::string number;
+ sc.SetState(SCE_ADA_NUMBER);
+
+ // Get all characters up to a delimiter or a separator, including points, but excluding
+ // double points (ranges).
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward();
+ }
+
+ // Special case: exponent with sign
+ if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
+ (sc.ch == '+' || sc.ch == '-')) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward ();
+
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward();
+ }
+ }
+
+ if (!IsValidNumber(number)) {
+ sc.ChangeState(SCE_ADA_ILLEGAL);
+ }
+
+ sc.SetState(SCE_ADA_DEFAULT);
+}
+
+static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+
+ sc.SetState(SCE_ADA_STRING);
+ sc.Forward();
+
+ ColouriseContext(sc, '"', SCE_ADA_STRINGEOL);
+}
+
+static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
+ // Apostrophe meaning is not changed, but the parameter is present for uniformity
+ sc.SetState(SCE_ADA_DEFAULT);
+ sc.ForwardSetState(SCE_ADA_DEFAULT);
+}
+
+static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+ sc.SetState(SCE_ADA_IDENTIFIER);
+
+ std::string word;
+
+ while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
+ word += static_cast<char>(tolower(sc.ch));
+ sc.Forward();
+ }
+
+ if (!IsValidIdentifier(word)) {
+ sc.ChangeState(SCE_ADA_ILLEGAL);
+
+ } else if (keywords.InList(word.c_str())) {
+ sc.ChangeState(SCE_ADA_WORD);
+
+ if (word != "all") {
+ apostropheStartsAttribute = false;
+ }
+ }
+
+ sc.SetState(SCE_ADA_DEFAULT);
+}
+
+//
+// ColouriseDocument
+//
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler) {
+ WordList &keywords = *keywordlists[0];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ int lineCurrent = styler.GetLine(startPos);
+ bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
+
+ while (sc.More()) {
+ if (sc.atLineEnd) {
+ // Go to the next line
+ sc.Forward();
+ lineCurrent++;
+
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, apostropheStartsAttribute);
+
+ // Don't continue any styles on the next line
+ sc.SetState(SCE_ADA_DEFAULT);
+ }
+
+ // Comments
+ if (sc.Match('-', '-')) {
+ ColouriseComment(sc, apostropheStartsAttribute);
+
+ // Strings
+ } else if (sc.Match('"')) {
+ ColouriseString(sc, apostropheStartsAttribute);
+
+ // Characters
+ } else if (sc.Match('\'') && !apostropheStartsAttribute) {
+ ColouriseCharacter(sc, apostropheStartsAttribute);
+
+ // Labels
+ } else if (sc.Match('<', '<')) {
+ ColouriseLabel(sc, keywords, apostropheStartsAttribute);
+
+ // Whitespace
+ } else if (IsASpace(sc.ch)) {
+ ColouriseWhiteSpace(sc, apostropheStartsAttribute);
+
+ // Delimiters
+ } else if (IsDelimiterCharacter(sc.ch)) {
+ ColouriseDelimiter(sc, apostropheStartsAttribute);
+
+ // Numbers
+ } else if (IsADigit(sc.ch) || sc.ch == '#') {
+ ColouriseNumber(sc, apostropheStartsAttribute);
+
+ // Keywords or identifiers
+ } else {
+ ColouriseWord(sc, keywords, apostropheStartsAttribute);
+ }
+ }
+
+ sc.Complete();
+}
+
+static inline bool IsDelimiterCharacter(int ch) {
+ switch (ch) {
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+ case '/':
+ case ':':
+ case ';':
+ case '<':
+ case '=':
+ case '>':
+ case '|':
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool IsNumberCharacter(int ch) {
+ return IsNumberStartCharacter(ch) ||
+ ch == '_' ||
+ ch == '.' ||
+ ch == '#' ||
+ (ch >= 'a' && ch <= 'f') ||
+ (ch >= 'A' && ch <= 'F');
+}
+
+static inline bool IsNumberStartCharacter(int ch) {
+ return IsADigit(ch);
+}
+
+static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
+ return IsASpace(ch) || IsDelimiterCharacter(ch);
+}
+
+static bool IsValidIdentifier(const std::string& identifier) {
+ // First character can't be '_', so initialize the flag to true
+ bool lastWasUnderscore = true;
+
+ size_t length = identifier.length();
+
+ // Zero-length identifiers are not valid (these can occur inside labels)
+ if (length == 0) {
+ return false;
+ }
+
+ // Check for valid character at the start
+ if (!IsWordStartCharacter(identifier[0])) {
+ return false;
+ }
+
+ // Check for only valid characters and no double underscores
+ for (size_t i = 0; i < length; i++) {
+ if (!IsWordCharacter(identifier[i]) ||
+ (identifier[i] == '_' && lastWasUnderscore)) {
+ return false;
+ }
+ lastWasUnderscore = identifier[i] == '_';
+ }
+
+ // Check for underscore at the end
+ if (lastWasUnderscore == true) {
+ return false;
+ }
+
+ // All checks passed
+ return true;
+}
+
+static bool IsValidNumber(const std::string& number) {
+ size_t hashPos = number.find("#");
+ bool seenDot = false;
+
+ size_t i = 0;
+ size_t length = number.length();
+
+ if (length == 0)
+ return false; // Just in case
+
+ // Decimal number
+ if (hashPos == std::string::npos) {
+ bool canBeSpecial = false;
+
+ for (; i < length; i++) {
+ if (number[i] == '_') {
+ if (!canBeSpecial) {
+ return false;
+ }
+ canBeSpecial = false;
+ } else if (number[i] == '.') {
+ if (!canBeSpecial || seenDot) {
+ return false;
+ }
+ canBeSpecial = false;
+ seenDot = true;
+ } else if (IsADigit(number[i])) {
+ canBeSpecial = true;
+ } else {
+ break;
+ }
+ }
+
+ if (!canBeSpecial)
+ return false;
+ } else {
+ // Based number
+ bool canBeSpecial = false;
+ int base = 0;
+
+ // Parse base
+ for (; i < length; i++) {
+ int ch = number[i];
+ if (ch == '_') {
+ if (!canBeSpecial)
+ return false;
+ canBeSpecial = false;
+ } else if (IsADigit(ch)) {
+ base = base * 10 + (ch - '0');
+ if (base > 16)
+ return false;
+ canBeSpecial = true;
+ } else if (ch == '#' && canBeSpecial) {
+ break;
+ } else {
+ return false;
+ }
+ }
+
+ if (base < 2)
+ return false;
+ if (i == length)
+ return false;
+
+ i++; // Skip over '#'
+
+ // Parse number
+ canBeSpecial = false;
+
+ for (; i < length; i++) {
+ int ch = tolower(number[i]);
+
+ if (ch == '_') {
+ if (!canBeSpecial) {
+ return false;
+ }
+ canBeSpecial = false;
+
+ } else if (ch == '.') {
+ if (!canBeSpecial || seenDot) {
+ return false;
+ }
+ canBeSpecial = false;
+ seenDot = true;
+
+ } else if (IsADigit(ch)) {
+ if (ch - '0' >= base) {
+ return false;
+ }
+ canBeSpecial = true;
+
+ } else if (ch >= 'a' && ch <= 'f') {
+ if (ch - 'a' + 10 >= base) {
+ return false;
+ }
+ canBeSpecial = true;
+
+ } else if (ch == '#' && canBeSpecial) {
+ break;
+
+ } else {
+ return false;
+ }
+ }
+
+ if (i == length) {
+ return false;
+ }
+
+ i++;
+ }
+
+ // Exponent (optional)
+ if (i < length) {
+ if (number[i] != 'e' && number[i] != 'E')
+ return false;
+
+ i++; // Move past 'E'
+
+ if (i == length) {
+ return false;
+ }
+
+ if (number[i] == '+')
+ i++;
+ else if (number[i] == '-') {
+ if (seenDot) {
+ i++;
+ } else {
+ return false; // Integer literals should not have negative exponents
+ }
+ }
+
+ if (i == length) {
+ return false;
+ }
+
+ bool canBeSpecial = false;
+
+ for (; i < length; i++) {
+ if (number[i] == '_') {
+ if (!canBeSpecial) {
+ return false;
+ }
+ canBeSpecial = false;
+ } else if (IsADigit(number[i])) {
+ canBeSpecial = true;
+ } else {
+ return false;
+ }
+ }
+
+ if (!canBeSpecial)
+ return false;
+ }
+
+ // if i == length, number was parsed successfully.
+ return i == length;
+}
+
+static inline bool IsWordCharacter(int ch) {
+ return IsWordStartCharacter(ch) || IsADigit(ch);
+}
+
+static inline bool IsWordStartCharacter(int ch) {
+ return (isascii(ch) && isalpha(ch)) || ch == '_';
+}
diff --git a/scintilla/src/LexAsm.cxx b/scintilla/src/LexAsm.cxx
new file mode 100644
index 0000000..872ef30
--- /dev/null
+++ b/scintilla/src/LexAsm.cxx
@@ -0,0 +1,180 @@
+// Scintilla source code edit control
+/** @file LexAsm.cxx
+ ** Lexer for Assembler, just for the MASM syntax
+ ** Written by The Black Horus
+ ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10
+ ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring
+ **/
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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 IsAsmOperator(const int ch) {
+ if ((ch < 0x80) && (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 ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &cpuInstruction = *keywordlists[0];
+ WordList &mathInstruction = *keywordlists[1];
+ WordList &registers = *keywordlists[2];
+ WordList &directive = *keywordlists[3];
+ WordList &directiveOperand = *keywordlists[4];
+ WordList &extInstruction = *keywordlists[5];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_ASM_STRINGEOL)
+ initStyle = SCE_ASM_DEFAULT;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+
+ // Prevent SCE_ASM_STRINGEOL from leaking back to previous line
+ if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) {
+ sc.SetState(SCE_ASM_STRING);
+ } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) {
+ sc.SetState(SCE_ASM_CHARACTER);
+ }
+
+ // 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_ASM_OPERATOR) {
+ if (!IsAsmOperator(sc.ch)) {
+ sc.SetState(SCE_ASM_DEFAULT);
+ }
+ }else if (sc.state == SCE_ASM_NUMBER) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_ASM_DEFAULT);
+ }
+ } else if (sc.state == SCE_ASM_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) ) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+
+ if (cpuInstruction.InList(s)) {
+ sc.ChangeState(SCE_ASM_CPUINSTRUCTION);
+ } else if (mathInstruction.InList(s)) {
+ sc.ChangeState(SCE_ASM_MATHINSTRUCTION);
+ } else if (registers.InList(s)) {
+ sc.ChangeState(SCE_ASM_REGISTER);
+ } else if (directive.InList(s)) {
+ sc.ChangeState(SCE_ASM_DIRECTIVE);
+ } else if (directiveOperand.InList(s)) {
+ sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND);
+ } else if (extInstruction.InList(s)) {
+ sc.ChangeState(SCE_ASM_EXTINSTRUCTION);
+ }
+ sc.SetState(SCE_ASM_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_ASM_COMMENT ) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_ASM_DEFAULT);
+ }
+ } else if (sc.state == SCE_ASM_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_ASM_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_ASM_STRINGEOL);
+ sc.ForwardSetState(SCE_ASM_DEFAULT);
+ }
+ } else if (sc.state == SCE_ASM_CHARACTER) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_ASM_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_ASM_STRINGEOL);
+ sc.ForwardSetState(SCE_ASM_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_ASM_DEFAULT) {
+ if (sc.ch == ';'){
+ sc.SetState(SCE_ASM_COMMENT);
+ } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) {
+ sc.SetState(SCE_ASM_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_ASM_IDENTIFIER);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_ASM_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_ASM_CHARACTER);
+ } else if (IsAsmOperator(sc.ch)) {
+ sc.SetState(SCE_ASM_OPERATOR);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+static const char * const asmWordListDesc[] = {
+ "CPU instructions",
+ "FPU instructions",
+ "Registers",
+ "Directives",
+ "Directive operands",
+ "Extended instructions",
+ 0
+};
+
+LexerModule lmAsm(SCLEX_ASM, ColouriseAsmDoc, "asm", 0, asmWordListDesc);
+
diff --git a/scintilla/src/LexAsn1.cxx b/scintilla/src/LexAsn1.cxx
new file mode 100644
index 0000000..28bf6d9
--- /dev/null
+++ b/scintilla/src/LexAsn1.cxx
@@ -0,0 +1,185 @@
+// Scintilla source code edit control
+/** @file LexAsn1.cxx
+ ** Lexer for ASN.1
+ **/
+// Copyright 2004 by Herr Pfarrer rpfarrer <at> yahoo <dot> de
+// Last Updated: 20/07/2004
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Some char test functions
+static bool isAsn1Number(int ch)
+{
+ return (ch >= '0' && ch <= '9');
+}
+
+static bool isAsn1Letter(int ch)
+{
+ return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+static bool isAsn1Char(int ch)
+{
+ return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch);
+}
+
+//
+// Function determining the color of a given code portion
+// Based on a "state"
+//
+static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler)
+{
+ // The keywords
+ WordList &Keywords = *keywordLists[0];
+ WordList &Attributes = *keywordLists[1];
+ WordList &Descriptors = *keywordLists[2];
+ WordList &Types = *keywordLists[3];
+
+ // Parse the whole buffer character by character using StyleContext
+ StyleContext sc(startPos, length, initStyle, styler);
+ for (; sc.More(); sc.Forward())
+ {
+ // The state engine
+ switch (sc.state)
+ {
+ case SCE_ASN1_DEFAULT: // Plain characters
+asn1_default:
+ if (sc.ch == '-' && sc.chNext == '-')
+ // A comment begins here
+ sc.SetState(SCE_ASN1_COMMENT);
+ else if (sc.ch == '"')
+ // A string begins here
+ sc.SetState(SCE_ASN1_STRING);
+ else if (isAsn1Number (sc.ch))
+ // A number starts here (identifier should start with a letter in ASN.1)
+ sc.SetState(SCE_ASN1_SCALAR);
+ else if (isAsn1Char (sc.ch))
+ // An identifier starts here (identifier always start with a letter)
+ sc.SetState(SCE_ASN1_IDENTIFIER);
+ else if (sc.ch == ':')
+ // A ::= operator starts here
+ sc.SetState(SCE_ASN1_OPERATOR);
+ break;
+ case SCE_ASN1_COMMENT: // A comment
+ if (sc.ch == '\r' || sc.ch == '\n')
+ // A comment ends here
+ sc.SetState(SCE_ASN1_DEFAULT);
+ break;
+ case SCE_ASN1_IDENTIFIER: // An identifier (keyword, attribute, descriptor or type)
+ if (!isAsn1Char (sc.ch))
+ {
+ // The end of identifier is here: we can look for it in lists by now and change its state
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (Keywords.InList(s))
+ // It's a keyword, change its state
+ sc.ChangeState(SCE_ASN1_KEYWORD);
+ else if (Attributes.InList(s))
+ // It's an attribute, change its state
+ sc.ChangeState(SCE_ASN1_ATTRIBUTE);
+ else if (Descriptors.InList(s))
+ // It's a descriptor, change its state
+ sc.ChangeState(SCE_ASN1_DESCRIPTOR);
+ else if (Types.InList(s))
+ // It's a type, change its state
+ sc.ChangeState(SCE_ASN1_TYPE);
+
+ // Set to default now
+ sc.SetState(SCE_ASN1_DEFAULT);
+ }
+ break;
+ case SCE_ASN1_STRING: // A string delimited by ""
+ if (sc.ch == '"')
+ {
+ // A string ends here
+ sc.ForwardSetState(SCE_ASN1_DEFAULT);
+
+ // To correctly manage a char sticking to the string quote
+ goto asn1_default;
+ }
+ break;
+ case SCE_ASN1_SCALAR: // A plain number
+ if (!isAsn1Number (sc.ch))
+ // A number ends here
+ sc.SetState(SCE_ASN1_DEFAULT);
+ break;
+ case SCE_ASN1_OPERATOR: // The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap)
+ if (sc.ch == '{')
+ {
+ // An OID definition starts here: enter the sub loop
+ for (; sc.More(); sc.Forward())
+ {
+ if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev)))
+ // The OID number is highlighted
+ sc.SetState(SCE_ASN1_OID);
+ else if (isAsn1Char (sc.ch))
+ // The OID parent identifier is plain
+ sc.SetState(SCE_ASN1_IDENTIFIER);
+ else
+ sc.SetState(SCE_ASN1_DEFAULT);
+
+ if (sc.ch == '}')
+ // Here ends the OID and the operator sub loop: go back to main loop
+ break;
+ }
+ }
+ else if (isAsn1Number (sc.ch))
+ {
+ // A trap number definition starts here: enter the sub loop
+ for (; sc.More(); sc.Forward())
+ {
+ if (isAsn1Number (sc.ch))
+ // The trap number is highlighted
+ sc.SetState(SCE_ASN1_OID);
+ else
+ {
+ // The number ends here: go back to main loop
+ sc.SetState(SCE_ASN1_DEFAULT);
+ break;
+ }
+ }
+ }
+ else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ')
+ // The operator doesn't imply an OID definition nor a trap, back to main loop
+ goto asn1_default; // To be sure to handle actually the state change
+ break;
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler)
+{
+ // No folding enabled, no reason to continue...
+ if( styler.GetPropertyInt("fold") == 0 )
+ return;
+
+ // No folding implemented: doesn't make sense for ASN.1
+}
+
+static const char * const asn1WordLists[] = {
+ "Keywords",
+ "Attributes",
+ "Descriptors",
+ "Types",
+ 0, };
+
+
+LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);
diff --git a/scintilla/src/LexBaan.cxx b/scintilla/src/LexBaan.cxx
new file mode 100644
index 0000000..97dd1f4
--- /dev/null
+++ b/scintilla/src/LexBaan.cxx
@@ -0,0 +1,193 @@
+// Scintilla source code edit control
+/** @file LexBaan.cxx
+ ** Lexer for Baan.
+ ** Based heavily on LexCPP.cxx
+ **/
+// Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':');
+}
+
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
+
+ if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line
+ initStyle = SCE_BAAN_DEFAULT;
+
+ int visibleChars = 0;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_BAAN_OPERATOR) {
+ sc.SetState(SCE_BAAN_DEFAULT);
+ } else if (sc.state == SCE_BAAN_NUMBER) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_BAAN_DEFAULT);
+ }
+ } else if (sc.state == SCE_BAAN_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_BAAN_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_BAAN_WORD2);
+ }
+ sc.SetState(SCE_BAAN_DEFAULT);
+ }
+ } else if (sc.state == SCE_BAAN_PREPROCESSOR) {
+ if (stylingWithinPreprocessor) {
+ if (IsASpace(sc.ch)) {
+ sc.SetState(SCE_BAAN_DEFAULT);
+ }
+ } else {
+ if (sc.atLineEnd && (sc.chNext != '^')) {
+ sc.SetState(SCE_BAAN_DEFAULT);
+ }
+ }
+ } else if (sc.state == SCE_BAAN_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_BAAN_DEFAULT);
+ }
+ } else if (sc.state == SCE_BAAN_COMMENTDOC) {
+ if (sc.MatchIgnoreCase("enddllusage")) {
+ for (unsigned int i = 0; i < 10; i++){
+ sc.Forward();
+ }
+ sc.ForwardSetState(SCE_BAAN_DEFAULT);
+ }
+ } else if (sc.state == SCE_BAAN_STRING) {
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_BAAN_DEFAULT);
+ } else if ((sc.atLineEnd) && (sc.chNext != '^')) {
+ sc.ChangeState(SCE_BAAN_STRINGEOL);
+ sc.ForwardSetState(SCE_C_DEFAULT);
+ visibleChars = 0;
+ }
+ }
+
+ if (sc.state == SCE_BAAN_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_BAAN_NUMBER);
+ } else if (sc.MatchIgnoreCase("dllusage")){
+ sc.SetState(SCE_BAAN_COMMENTDOC);
+ do {
+ sc.Forward();
+ } while ((!sc.atLineEnd) && sc.More());
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_BAAN_IDENTIFIER);
+ } else if (sc.Match('|')){
+ sc.SetState(SCE_BAAN_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_BAAN_STRING);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ // Preprocessor commands are alone on their line
+ sc.SetState(SCE_BAAN_PREPROCESSOR);
+ // Skip whitespace between # and preprocessor word
+ do {
+ sc.Forward();
+ } while (IsASpace(sc.ch) && sc.More());
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_BAAN_OPERATOR);
+ }
+ }
+ if (sc.atLineEnd) {
+ // Reset states to begining of colourise so no surprises
+ // if different sets of lines lexed.
+ visibleChars = 0;
+ }
+ if (!IsASpace(sc.ch)) {
+ visibleChars++;
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldBaanDoc(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 levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (foldComment &&
+ (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) {
+ if (style != stylePrev) {
+ levelCurrent++;
+ } else if ((style != styleNext) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+ if (style == SCE_BAAN_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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);
+}
+
+LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc);
diff --git a/scintilla/src/LexBash.cxx b/scintilla/src/LexBash.cxx
new file mode 100644
index 0000000..ec3e04a
--- /dev/null
+++ b/scintilla/src/LexBash.cxx
@@ -0,0 +1,521 @@
+// Scintilla source code edit control
+/** @file LexBash.cxx
+ ** Lexer for Bash.
+ **/
+// Copyright 2004-2008 by Neil Hodgson <neilh@scintilla.org>
+// Adapted from LexPerl by Kein-Hong Man 2004
+// 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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define HERE_DELIM_MAX 256
+
+// define this if you want 'invalid octals' to be marked as errors
+// usually, this is not a good idea, permissive lexing is better
+#undef PEDANTIC_OCTAL
+
+#define BASH_BASE_ERROR 65
+#define BASH_BASE_DECIMAL 66
+#define BASH_BASE_HEX 67
+#ifdef PEDANTIC_OCTAL
+#define BASH_BASE_OCTAL 68
+#define BASH_BASE_OCTAL_ERROR 69
+#endif
+
+static inline int translateBashDigit(int ch) {
+ if (ch >= '0' && ch <= '9') {
+ return ch - '0';
+ } else if (ch >= 'a' && ch <= 'z') {
+ return ch - 'a' + 10;
+ } else if (ch >= 'A' && ch <= 'Z') {
+ return ch - 'A' + 36;
+ } else if (ch == '@') {
+ return 62;
+ } else if (ch == '_') {
+ return 63;
+ }
+ return BASH_BASE_ERROR;
+}
+
+static inline int getBashNumberBase(char *s) {
+ int i = 0;
+ int base = 0;
+ while (*s) {
+ base = base * 10 + (*s++ - '0');
+ i++;
+ }
+ if (base > 64 || i > 2) {
+ return BASH_BASE_ERROR;
+ }
+ return base;
+}
+
+static int opposite(int ch) {
+ if (ch == '(') return ')';
+ if (ch == '[') return ']';
+ if (ch == '{') return '}';
+ if (ch == '<') return '>';
+ return ch;
+}
+
+static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_");
+ // note that [+-] are often parts of identifiers in shell scripts
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._+-");
+ CharacterSet setBashOperator(CharacterSet::setNone, "^&\\%()-+=|{}[]:;>,*/<?!.~@");
+ CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMACahGLNn");
+ CharacterSet setParam(CharacterSet::setAlphaNum, "$_");
+ CharacterSet setHereDoc(CharacterSet::setAlpha, "_\\-+!");
+ CharacterSet setHereDoc2(CharacterSet::setAlphaNum, "_-+!");
+ CharacterSet setLeftShift(CharacterSet::setDigits, "=$");
+
+ class HereDocCls { // Class to manage HERE document elements
+ public:
+ int State; // 0: '<<' encountered
+ // 1: collect the delimiter
+ // 2: here doc text (lines after the delimiter)
+ int Quote; // the char after '<<'
+ bool Quoted; // true if Quote in ('\'','"','`')
+ bool Indent; // indented delimiter (for <<-)
+ int DelimiterLength; // strlen(Delimiter)
+ 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';
+ }
+ void Append(int ch) {
+ Delimiter[DelimiterLength++] = static_cast<char>(ch);
+ Delimiter[DelimiterLength] = '\0';
+ }
+ ~HereDocCls() {
+ delete []Delimiter;
+ }
+ };
+ HereDocCls HereDoc;
+
+ class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl)
+ public:
+ int Count;
+ int Up, Down;
+ QuoteCls() {
+ Count = 0;
+ Up = '\0';
+ Down = '\0';
+ }
+ void Open(int u) {
+ Count++;
+ Up = u;
+ Down = opposite(Up);
+ }
+ void Start(int u) {
+ Count = 0;
+ Open(u);
+ }
+ };
+ QuoteCls Quote;
+
+ int numBase = 0;
+ int digit;
+ unsigned int endPos = startPos + length;
+
+ // Backtrack to beginning of style if required...
+ // If in a long distance lexical state, backtrack to find quote characters
+ if (initStyle == SCE_SH_HERE_Q) {
+ while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_SH_HERE_DELIM)) {
+ startPos--;
+ }
+ startPos = styler.LineStart(styler.GetLine(startPos));
+ initStyle = styler.StyleAt(startPos - 1);
+ }
+ // Bash strings can be multi-line with embedded newlines, so backtrack.
+ // Bash numbers have additional state during lexing, so backtrack too.
+ if (initStyle == SCE_SH_STRING
+ || initStyle == SCE_SH_BACKTICKS
+ || initStyle == SCE_SH_CHARACTER
+ || initStyle == SCE_SH_NUMBER
+ || initStyle == SCE_SH_IDENTIFIER
+ || initStyle == SCE_SH_COMMENTLINE) {
+ while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) {
+ startPos--;
+ }
+ initStyle = SCE_SH_DEFAULT;
+ }
+
+ StyleContext sc(startPos, endPos - startPos, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_SH_OPERATOR:
+ sc.SetState(SCE_SH_DEFAULT);
+ break;
+ case SCE_SH_WORD:
+ // "." never used in Bash variable names but used in file names
+ if (!setWord.Contains(sc.ch)) {
+ char s[1000];
+ sc.GetCurrent(s, sizeof(s));
+ if (s[0] != '-' && // for file operators
+ !keywords.InList(s)) {
+ sc.ChangeState(SCE_SH_IDENTIFIER);
+ }
+ sc.SetState(SCE_SH_DEFAULT);
+ }
+ break;
+ case SCE_SH_IDENTIFIER:
+ if (sc.chPrev == '\\') { // for escaped chars
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ } else if (!setWord.Contains(sc.ch)) {
+ sc.SetState(SCE_SH_DEFAULT);
+ }
+ break;
+ case SCE_SH_NUMBER:
+ digit = translateBashDigit(sc.ch);
+ if (numBase == BASH_BASE_DECIMAL) {
+ if (sc.ch == '#') {
+ char s[10];
+ sc.GetCurrent(s, sizeof(s));
+ numBase = getBashNumberBase(s);
+ if (numBase != BASH_BASE_ERROR)
+ break;
+ } else if (IsADigit(sc.ch))
+ break;
+ } else if (numBase == BASH_BASE_HEX) {
+ if (IsADigit(sc.ch, 16))
+ break;
+#ifdef PEDANTIC_OCTAL
+ } else if (numBase == BASH_BASE_OCTAL ||
+ numBase == BASH_BASE_OCTAL_ERROR) {
+ if (digit <= 7)
+ break;
+ if (digit <= 9) {
+ numBase = BASH_BASE_OCTAL_ERROR;
+ break;
+ }
+#endif
+ } else if (numBase == BASH_BASE_ERROR) {
+ if (digit <= 9)
+ break;
+ } else { // DD#DDDD number style handling
+ if (digit != BASH_BASE_ERROR) {
+ if (numBase <= 36) {
+ // case-insensitive if base<=36
+ if (digit >= 36) digit -= 26;
+ }
+ if (digit < numBase)
+ break;
+ if (digit <= 9) {
+ numBase = BASH_BASE_ERROR;
+ break;
+ }
+ }
+ }
+ // fallthrough when number is at an end or error
+ if (numBase == BASH_BASE_ERROR
+#ifdef PEDANTIC_OCTAL
+ || numBase == BASH_BASE_OCTAL_ERROR
+#endif
+ ) {
+ sc.ChangeState(SCE_SH_ERROR);
+ }
+ sc.SetState(SCE_SH_DEFAULT);
+ break;
+ case SCE_SH_COMMENTLINE:
+ if (sc.atLineEnd && sc.chPrev != '\\') {
+ sc.SetState(SCE_SH_DEFAULT);
+ }
+ break;
+ case SCE_SH_HERE_DELIM:
+ // From Bash info:
+ // ---------------
+ // Specifier format is: <<[-]WORD
+ // Optional '-' is for removal of leading tabs from here-doc.
+ // Whitespace acceptable after <<[-] operator
+ //
+ if (HereDoc.State == 0) { // '<<' encountered
+ HereDoc.Quote = sc.chNext;
+ HereDoc.Quoted = false;
+ HereDoc.DelimiterLength = 0;
+ HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+ if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ")
+ sc.Forward();
+ HereDoc.Quoted = true;
+ HereDoc.State = 1;
+ } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case
+ HereDoc.Indent = true;
+ } else if (setHereDoc.Contains(sc.chNext)) {
+ // an unquoted here-doc delimiter, no special handling
+ // TODO check what exactly bash considers part of the delim
+ HereDoc.State = 1;
+ } else if (sc.chNext == '<') { // HERE string <<<
+ sc.Forward();
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ } else if (IsASpace(sc.chNext)) {
+ // eat whitespace
+ } else if (setLeftShift.Contains(sc.chNext)) {
+ // left shift << or <<= operator cases
+ sc.ChangeState(SCE_SH_OPERATOR);
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ } else {
+ // symbols terminates; deprecated zero-length delimiter
+ HereDoc.State = 1;
+ }
+ } else if (HereDoc.State == 1) { // collect the delimiter
+ if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') {
+ HereDoc.Append(sc.ch);
+ } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ } else if (sc.ch == '\\') {
+ // skip escape prefix
+ } else {
+ sc.SetState(SCE_SH_DEFAULT);
+ }
+ if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup
+ sc.SetState(SCE_SH_ERROR);
+ HereDoc.State = 0;
+ }
+ }
+ break;
+ case SCE_SH_HERE_Q:
+ // HereDoc.State == 2
+ if (sc.atLineStart) {
+ sc.SetState(SCE_SH_HERE_Q);
+ int prefixws = 0;
+ while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix
+ sc.Forward();
+ prefixws++;
+ }
+ if (prefixws > 0)
+ sc.SetState(SCE_SH_HERE_Q);
+ while (!sc.atLineEnd) {
+ sc.Forward();
+ }
+ char s[HERE_DELIM_MAX];
+ sc.GetCurrent(s, sizeof(s));
+ if (sc.LengthCurrent() == 0)
+ break;
+ if (s[strlen(s) - 1] == '\r')
+ s[strlen(s) - 1] = '\0';
+ if (strcmp(HereDoc.Delimiter, s) == 0) {
+ if ((prefixws > 0 && HereDoc.Indent) || // indentation rule
+ (prefixws == 0 && !HereDoc.Indent)) {
+ sc.SetState(SCE_SH_DEFAULT);
+ break;
+ }
+ }
+ }
+ break;
+ case SCE_SH_SCALAR: // variable names
+ if (!setParam.Contains(sc.ch)) {
+ if (sc.LengthCurrent() == 1) {
+ // Special variable: $(, $_ etc.
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ } else {
+ sc.SetState(SCE_SH_DEFAULT);
+ }
+ }
+ break;
+ case SCE_SH_STRING: // delimited styles
+ case SCE_SH_CHARACTER:
+ case SCE_SH_BACKTICKS:
+ case SCE_SH_PARAM:
+ if (sc.ch == '\\' && Quote.Up != '\\') {
+ sc.Forward();
+ } else if (sc.ch == Quote.Down) {
+ Quote.Count--;
+ if (Quote.Count == 0) {
+ sc.ForwardSetState(SCE_SH_DEFAULT);
+ }
+ } else if (sc.ch == Quote.Up) {
+ Quote.Count++;
+ }
+ break;
+ }
+
+ // Must check end of HereDoc state 1 before default state is handled
+ if (HereDoc.State == 1 && sc.atLineEnd) {
+ // Begin of here-doc (the line after the here-doc delimiter):
+ // Lexically, the here-doc starts from the next line after the >>, but the
+ // first line of here-doc seem to follow the style of the last EOL sequence
+ HereDoc.State = 2;
+ if (HereDoc.Quoted) {
+ if (sc.state == SCE_SH_HERE_DELIM) {
+ // Missing quote at end of string! We are stricter than bash.
+ // Colour here-doc anyway while marking this bit as an error.
+ sc.ChangeState(SCE_SH_ERROR);
+ }
+ // HereDoc.Quote always == '\''
+ }
+ sc.SetState(SCE_SH_HERE_Q);
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_SH_DEFAULT) {
+ if (sc.ch == '\\') { // escaped character
+ sc.SetState(SCE_SH_IDENTIFIER);
+ } else if (IsADigit(sc.ch)) {
+ sc.SetState(SCE_SH_NUMBER);
+ numBase = BASH_BASE_DECIMAL;
+ if (sc.ch == '0') { // hex,octal
+ if (sc.chNext == 'x' || sc.chNext == 'X') {
+ numBase = BASH_BASE_HEX;
+ sc.Forward();
+ } else if (IsADigit(sc.chNext)) {
+#ifdef PEDANTIC_OCTAL
+ numBase = BASH_BASE_OCTAL;
+#else
+ numBase = BASH_BASE_HEX;
+#endif
+ }
+ }
+ } else if (setWordStart.Contains(sc.ch)) {
+ sc.SetState(SCE_SH_WORD);
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_SH_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_SH_STRING);
+ Quote.Start(sc.ch);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_SH_CHARACTER);
+ Quote.Start(sc.ch);
+ } else if (sc.ch == '`') {
+ sc.SetState(SCE_SH_BACKTICKS);
+ Quote.Start(sc.ch);
+ } else if (sc.ch == '$') {
+ sc.SetState(SCE_SH_SCALAR);
+ sc.Forward();
+ if (sc.ch == '{') {
+ sc.ChangeState(SCE_SH_PARAM);
+ } else if (sc.ch == '\'') {
+ sc.ChangeState(SCE_SH_CHARACTER);
+ } else if (sc.ch == '"') {
+ sc.ChangeState(SCE_SH_STRING);
+ } else if (sc.ch == '(' || sc.ch == '`') {
+ sc.ChangeState(SCE_SH_BACKTICKS);
+ if (sc.chNext == '(') { // $(( is lexed as operator
+ sc.ChangeState(SCE_SH_OPERATOR);
+ }
+ } else {
+ continue; // scalar has no delimiter pair
+ }
+ // fallthrough, open delim for $[{'"(`]
+ Quote.Start(sc.ch);
+ } else if (sc.Match('<', '<')) {
+ sc.SetState(SCE_SH_HERE_DELIM);
+ HereDoc.State = 0;
+ HereDoc.Indent = false;
+ } else if (sc.ch == '-' && // one-char file test operators
+ setSingleCharOp.Contains(sc.chNext) &&
+ !setWord.Contains(sc.GetRelative(2)) &&
+ IsASpace(sc.chPrev)) {
+ sc.SetState(SCE_SH_WORD);
+ sc.Forward();
+ } else if (setBashOperator.Contains(sc.ch)) {
+ sc.SetState(SCE_SH_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+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;
+ 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];
+ int styleNext = styler.StyleAt(startPos);
+ 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');
+ // 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_SH_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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 bashWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc);
diff --git a/scintilla/src/LexBasic.cxx b/scintilla/src/LexBasic.cxx
new file mode 100644
index 0000000..9a52186
--- /dev/null
+++ b/scintilla/src/LexBasic.cxx
@@ -0,0 +1,373 @@
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/* 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 || sc.state == SCE_B_PREPROCESSOR) {
+ 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)) {
+ // Hack to make deprecated QBASIC '$Include show
+ // up in freebasic with SCE_B_PREPROCESSOR.
+ if (comment_char == '\'' && sc.Match(comment_char, '$'))
+ sc.SetState(SCE_B_PREPROCESSOR);
+ else
+ 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);
+
diff --git a/scintilla/src/LexBullant.cxx b/scintilla/src/LexBullant.cxx
new file mode 100644
index 0000000..437843f
--- /dev/null
+++ b/scintilla/src/LexBullant.cxx
@@ -0,0 +1,229 @@
+// SciTE - Scintilla based Text Editor
+// LexBullant.cxx - lexer for Bullant
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+ char s[100];
+ s[0] = '\0';
+ 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';
+ }
+ int lev= 0;
+ char chAttr = SCE_C_IDENTIFIER;
+ if (isdigit(s[0]) || (s[0] == '.')){
+ chAttr = SCE_C_NUMBER;
+ }
+ else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_C_WORD;
+ if (strcmp(s, "end") == 0)
+ lev = -1;
+ else if (strcmp(s, "method") == 0 ||
+ strcmp(s, "case") == 0 ||
+ strcmp(s, "class") == 0 ||
+ strcmp(s, "debug") == 0 ||
+ strcmp(s, "test") == 0 ||
+ strcmp(s, "if") == 0 ||
+ strcmp(s, "lock") == 0 ||
+ strcmp(s, "transaction") == 0 ||
+ strcmp(s, "trap") == 0 ||
+ strcmp(s, "until") == 0 ||
+ strcmp(s, "while") == 0)
+ lev = 1;
+ }
+ }
+ styler.ColourTo(end, chAttr);
+ return lev;
+}
+
+static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ WordList &keywords = *keywordlists[0];
+
+ styler.StartAt(startPos);
+
+ bool fold = styler.GetPropertyInt("fold") != 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+
+ int state = initStyle;
+ if (state == SCE_C_STRINGEOL) // Does not leak onto next line
+ state = SCE_C_DEFAULT;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ unsigned int lengthDoc = startPos + length;
+ int visibleChars = 0;
+ styler.StartSegment(startPos);
+ int endFoundThisLine = 0;
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
+ // Avoid triggering two times on Dos/Win
+ // End of line
+ endFoundThisLine = 0;
+ if (state == SCE_C_STRINGEOL) {
+ styler.ColourTo(i, state);
+ state = SCE_C_DEFAULT;
+ }
+ if (fold) {
+ int lev = levelPrev;
+ if (visibleChars == 0)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((levelCurrent > levelPrev) && (visibleChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ levelPrev = levelCurrent;
+ }
+ visibleChars = 0;
+
+/* int indentBlock = GetLineIndentation(lineCurrent);
+ if (blockChange==1){
+ lineCurrent++;
+ int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize);
+ } else if (blockChange==-1) {
+ indentBlock -= indentSize;
+ if (indentBlock < 0)
+ indentBlock = 0;
+ SetLineIndentation(lineCurrent, indentBlock);
+ lineCurrent++;
+ }
+ blockChange=0;
+*/ }
+ if (!(isascii(ch) && isspace(ch)))
+ visibleChars++;
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i-1, state);
+ state = SCE_C_IDENTIFIER;
+ } else if (ch == '@' && chNext == 'o') {
+ if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) {
+ styler.ColourTo(i-1, state);
+ state = SCE_C_COMMENT;
+ }
+ } else if (ch == '#') {
+ styler.ColourTo(i-1, state);
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i-1, state);
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i-1, state);
+ state = SCE_C_CHARACTER;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i-1, state);
+ styler.ColourTo(i, SCE_C_OPERATOR);
+ }
+ } else if (state == SCE_C_IDENTIFIER) {
+ if (!iswordchar(ch)) {
+ int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler);
+ state = SCE_C_DEFAULT;
+ chNext = styler.SafeGetCharAt(i + 1);
+ if (ch == '#') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ state = SCE_C_CHARACTER;
+ } else if (isoperator(ch)) {
+ styler.ColourTo(i, SCE_C_OPERATOR);
+ }
+ if (endFoundThisLine == 0)
+ levelCurrent+=levelChange;
+ if (levelChange == -1)
+ endFoundThisLine=1;
+ }
+ } else if (state == SCE_C_COMMENT) {
+ if (ch == '@' && chNext == 'o') {
+ if (styler.SafeGetCharAt(i+2) == 'n') {
+ styler.ColourTo(i+2, state);
+ state = SCE_C_DEFAULT;
+ i+=2;
+ }
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ endFoundThisLine = 0;
+ styler.ColourTo(i-1, state);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_STRING) {
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_C_DEFAULT;
+ } else if (chNext == '\r' || chNext == '\n') {
+ endFoundThisLine = 0;
+ styler.ColourTo(i-1, SCE_C_STRINGEOL);
+ state = SCE_C_STRINGEOL;
+ }
+ } else if (state == SCE_C_CHARACTER) {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+ endFoundThisLine = 0;
+ styler.ColourTo(i-1, SCE_C_STRINGEOL);
+ state = SCE_C_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_C_DEFAULT;
+ }
+ }
+ chPrev = ch;
+ }
+ styler.ColourTo(lengthDoc - 1, state);
+
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ if (fold) {
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ //styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+
+ }
+}
+
+static const char * const bullantWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc);
diff --git a/scintilla/src/LexCLW.cxx b/scintilla/src/LexCLW.cxx
new file mode 100644
index 0000000..3416bf2
--- /dev/null
+++ b/scintilla/src/LexCLW.cxx
@@ -0,0 +1,679 @@
+// Scintilla source code edit control
+/** @file LexClw.cxx
+ ** Lexer for Clarion.
+ ** 2004/12/17 Updated Lexer
+ **/
+// 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 <stdio.h>
+#include <stdarg.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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// 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'));
+ }
+}
+
+// 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 == ':');
+}
+
+// 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) {
+ return(true);
+ }
+ }
+ // Case sensitive
+ else {
+ if (strchr("ABCDEF", iChar) != NULL) {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+// 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
+ if (strchr("BOHboh", iChar) != NULL) {
+ return(true);
+ }
+ }
+ // Case sensitive
+ else {
+ // If character is a numeric base character
+ if (strchr("BOH", iChar) != NULL) {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+// Set the correct numeric constant state
+inline bool SetNumericConstantState(StyleContext &scDoc) {
+
+ int iPoints = 0; // Point counter
+ char cNumericString[512]; // Numeric string buffer
+
+ // Buffer the current numberic string
+ scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
+ // Loop through the string until end of string (NULL termination)
+ for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
+ // Depending on the character
+ switch (cNumericString[iIndex]) {
+ // Is a . (point)
+ case '.' :
+ // Increment point counter
+ iPoints++;
+ break;
+ default :
+ break;
+ }
+ }
+ // If points found (can be more than one for improper formatted number
+ if (iPoints > 0) {
+ return(true);
+ }
+ // Else no points found
+ else {
+ return(false);
+ }
+}
+
+// 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 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)
+
+ const char wlProcReservedKeywordList[] =
+ "PROCEDURE FUNCTION";
+ WordList wlProcReservedKeywords;
+ wlProcReservedKeywords.Set(wlProcReservedKeywordList);
+
+ 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);
+
+ // lex source code
+ for (; scDoc.More(); scDoc.Forward())
+ {
+ //
+ // Determine if the current state should terminate.
+ //
+
+ // Label State Handling
+ if (scDoc.state == SCE_CLW_LABEL) {
+ // If the character is not a valid label
+ 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 check label
+ else {
+ 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) {
+ StringUpper(cLabel);
+ }
+ // 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
+ scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
+ }
+ // Terminate the label state and set to default state
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ }
+ }
+ // Keyword State Handling
+ else if (scDoc.state == SCE_CLW_KEYWORD) {
+ // If character is : (colon)
+ if (scDoc.ch == ':') {
+ 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) {
+ StringUpper(cEquate);
+ }
+ // If statement string is in the equate list
+ if (wlStandardEquates.InList(cEquate)) {
+ // Change to equate state
+ scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
+ }
+ }
+ // If the character is not a valid label character
+ else if (!IsALabelCharacter(scDoc.ch)) {
+ 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) {
+ StringUpper(cStatement);
+ }
+ // If statement string is in the Clarion keyword list
+ if (wlClarionKeywords.InList(cStatement)) {
+ // 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)) {
+ // 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)) {
+ // 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)) {
+ // 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)) {
+ // 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)) {
+ // 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);
+ }
+ }
+ // String State Handling
+ else if (scDoc.state == SCE_CLW_STRING) {
+ // If the character is an ' (single quote)
+ if (scDoc.ch == '\'') {
+ // Set the state to default and move forward colouring
+ // the ' (single quote) as default state
+ // terminating the string state
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ scDoc.Forward();
+ }
+ // If the next character is an ' (single quote)
+ if (scDoc.chNext == '\'') {
+ // Move forward one character and set to default state
+ // colouring the next ' (single quote) as default state
+ // terminating the string state
+ scDoc.ForwardSetState(SCE_CLW_DEFAULT);
+ scDoc.Forward();
+ }
+ }
+ // Picture String State Handling
+ else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
+ // If the character is an ( (open parenthese)
+ if (scDoc.ch == '(') {
+ // Increment the parenthese level
+ iParenthesesLevel++;
+ }
+ // 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 {
+ // Decrement the parenthese level
+ iParenthesesLevel--;
+ }
+ }
+ }
+ // Standard Equate State Handling
+ else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
+ if (!isalnum(scDoc.ch)) {
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ }
+ // Integer Constant State Handling
+ else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
+ // If the character is not a digit (0-9)
+ // or character is not a hexidecimal character (A-F)
+ // or character is not a . (point)
+ // or character is not a numberic base character (B,O,H)
+ if (!(isdigit(scDoc.ch)
+ || IsAHexCharacter(scDoc.ch, bCaseSensitive)
+ || scDoc.ch == '.'
+ || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
+ // If the number was a real
+ if (SetNumericConstantState(scDoc)) {
+ // Colour the matched string to the real constant state
+ scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
+ }
+ // Else the number was an integer
+ else {
+ // Colour the matched string to an integer constant state
+ scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
+ }
+ // Terminate the integer constant state and set to default state
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ }
+
+ //
+ // Determine if a new state should be entered.
+ //
+
+ // 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);
+ }
+ // else if character is a space or tab
+ else if (IsASpace(scDoc.ch)){
+ // Set to default state
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ // 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);
+ }
+ // else the character is a ? (question mark)
+ else if (scDoc.ch == '?') {
+ // Change to the compiler directive state, move forward,
+ // colouring the ? (question mark), change back to default state.
+ scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
+ scDoc.Forward();
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ // else an invalid character in column 1
+ else {
+ // Set to error state
+ scDoc.SetState(SCE_CLW_ERROR);
+ }
+ }
+ // End of Line Handling
+ else if (scDoc.atLineEnd) {
+ // Reset to the default state at the end of each line.
+ scDoc.SetState(SCE_CLW_DEFAULT);
+ }
+ // Default Handling
+ else {
+ // If in default state
+ if (scDoc.state == SCE_CLW_DEFAULT) {
+ // If is a letter could be a possible statement
+ if (isalpha(scDoc.ch)) {
+ // Set the state to Clarion Keyword and verify later
+ scDoc.SetState(SCE_CLW_KEYWORD);
+ }
+ // else is a number
+ else if (isdigit(scDoc.ch)) {
+ // Set the state to Integer Constant and verify later
+ scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
+ }
+ // else if the start of a comment or a | (line continuation)
+ 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)
+ // Embedded Apostrophe
+ if (scDoc.chNext == '\'') {
+ // Move forward colouring it as default state
+ scDoc.ForwardSetState(SCE_CLW_DEFAULT);
+ }
+ else {
+ // move to the next character and then set the state to comment.
+ scDoc.ForwardSetState(SCE_CLW_STRING);
+ }
+ }
+ // else the character is an @ (ampersand)
+ else if (scDoc.ch == '@') {
+ // Case insensitive.
+ if (!bCaseSensitive) {
+ // If character is a valid picture token character
+ if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
+ // Set to the picture string state
+ scDoc.SetState(SCE_CLW_PICTURE_STRING);
+ }
+ }
+ // Case sensitive
+ else {
+ // If character is a valid picture token character
+ if (strchr("DEKNPST", scDoc.chNext) != NULL) {
+ // Set the picture string state
+ scDoc.SetState(SCE_CLW_PICTURE_STRING);
+ }
+ }
+ }
+ }
+ }
+ }
+ // lexing complete
+ scDoc.Complete();
+}
+
+// Clarion Language Case Sensitive Colouring Procedure
+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 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
+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);
+}
+
+// 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 (Labels)",
+ "Reserved Words (Procedure Labels)",
+ 0,
+};
+
+// Case Sensitive Clarion Language Lexer
+LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
+
+// Case Insensitive Clarion Language Lexer
+LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);
diff --git a/scintilla/src/LexCOBOL.cxx b/scintilla/src/LexCOBOL.cxx
new file mode 100644
index 0000000..eee1fd4
--- /dev/null
+++ b/scintilla/src/LexCOBOL.cxx
@@ -0,0 +1,368 @@
+// Scintilla source code edit control
+/** @file LexCOBOL.cxx
+ ** Lexer for COBOL
+ ** Based on LexPascal.cxx
+ ** Written by Laurent le Tynevez
+ ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
+ ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
+ ** Updated by Rod Falck, Aug 2006 Converted to COBOL
+ **/
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define IN_DIVISION 0x01
+#define IN_DECLARATIVES 0x02
+#define IN_SECTION 0x04
+#define IN_PARAGRAPH 0x08
+#define IN_FLAGS 0xF
+#define NOT_HEADER 0x10
+
+inline bool isCOBOLoperator(char ch)
+ {
+ return isoperator(ch);
+ }
+
+inline bool isCOBOLwordchar(char ch)
+ {
+ return isascii(ch) && (isalnum(ch) || ch == '-');
+
+ }
+
+inline bool isCOBOLwordstart(char ch)
+ {
+ return isascii(ch) && isalnum(ch);
+ }
+
+static int CountBits(int nBits)
+ {
+ int count = 0;
+ for (int i = 0; i < 32; ++i)
+ {
+ count += nBits & 1;
+ nBits >>= 1;
+ }
+ return count;
+ }
+
+static void getRange(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) {
+ styler.ColourTo(end, attr);
+}
+
+
+static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) {
+ int ret = 0;
+
+ WordList& a_keywords = *keywordlists[0];
+ WordList& b_keywords = *keywordlists[1];
+ WordList& c_keywords = *keywordlists[2];
+
+ char s[100];
+ getRange(start, end, styler, s, sizeof(s));
+
+ char chAttr = SCE_C_IDENTIFIER;
+ if (isdigit(s[0]) || (s[0] == '.')) {
+ chAttr = SCE_C_NUMBER;
+ char *p = s + 1;
+ while (*p) {
+ if (!isdigit(*p) && isCOBOLwordchar(*p)) {
+ chAttr = SCE_C_IDENTIFIER;
+ break;
+ }
+ ++p;
+ }
+ }
+ else {
+ if (a_keywords.InList(s)) {
+ chAttr = SCE_C_WORD;
+ }
+ else if (b_keywords.InList(s)) {
+ chAttr = SCE_C_WORD2;
+ }
+ else if (c_keywords.InList(s)) {
+ chAttr = SCE_C_UUID;
+ }
+ }
+ if (*bAarea) {
+ if (strcmp(s, "division") == 0) {
+ ret = IN_DIVISION;
+ // we've determined the containment, anything else is just ignored for those purposes
+ *bAarea = false;
+ } else if (strcmp(s, "declaratives") == 0) {
+ ret = IN_DIVISION | IN_DECLARATIVES;
+ if (nContainment & IN_DECLARATIVES)
+ ret |= NOT_HEADER | IN_SECTION;
+ // we've determined the containment, anything else is just ignored for those purposes
+ *bAarea = false;
+ } else if (strcmp(s, "section") == 0) {
+ ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION;
+ // we've determined the containment, anything else is just ignored for those purposes
+ *bAarea = false;
+ } else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) {
+ ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER;
+ } else {
+ ret = nContainment | IN_PARAGRAPH;
+ }
+ }
+ ColourTo(styler, end, chAttr);
+ return ret;
+}
+
+static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ styler.StartAt(startPos);
+
+ int state = initStyle;
+ if (state == SCE_C_CHARACTER) // Does not leak onto next line
+ state = SCE_C_DEFAULT;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ unsigned int lengthDoc = startPos + length;
+
+ int nContainment;
+
+ int currentLine = styler.GetLine(startPos);
+ if (currentLine > 0) {
+ styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
+ nContainment = styler.GetLineState(currentLine);
+ nContainment &= ~NOT_HEADER;
+ } else {
+ styler.SetLineState(currentLine, 0);
+ nContainment = 0;
+ }
+
+ styler.StartSegment(startPos);
+ bool bNewLine = true;
+ bool bAarea = !isspacechar(chNext);
+ int column = 0;
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ ++column;
+
+ if (bNewLine) {
+ column = 0;
+ }
+ if (column <= 1 && !bAarea) {
+ bAarea = !isspacechar(ch);
+ }
+ bool bSetNewLine = false;
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
+ // Avoid triggering two times on Dos/Win
+ // End of line
+ if (state == SCE_C_CHARACTER) {
+ ColourTo(styler, i, state);
+ state = SCE_C_DEFAULT;
+ }
+ styler.SetLineState(currentLine, nContainment);
+ currentLine++;
+ bSetNewLine = true;
+ if (nContainment & NOT_HEADER)
+ nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION);
+ }
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_IDENTIFIER;
+ } else if (column == 0 && ch == '*' && chNext != '*') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_COMMENTLINE;
+ } else if (column == 0 && ch == '/' && chNext != '*') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_COMMENTLINE;
+ } else if (column == 0 && ch == '*' && chNext == '*') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_COMMENTDOC;
+ } else if (column == 0 && ch == '/' && chNext == '*') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_COMMENTDOC;
+ } else if (ch == '"') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_CHARACTER;
+ } else if (ch == '?' && column == 0) {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_PREPROCESSOR;
+ } else if (isCOBOLoperator(ch)) {
+ ColourTo(styler, i-1, state);
+ ColourTo(styler, i, SCE_C_OPERATOR);
+ }
+ } else if (state == SCE_C_IDENTIFIER) {
+ if (!isCOBOLwordchar(ch)) {
+ int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea);
+
+ if(lStateChange != 0) {
+ styler.SetLineState(currentLine, lStateChange);
+ nContainment = lStateChange;
+ }
+
+ state = SCE_C_DEFAULT;
+ chNext = styler.SafeGetCharAt(i + 1);
+ if (ch == '"') {
+ state = SCE_C_STRING;
+ } else if (ch == '\'') {
+ state = SCE_C_CHARACTER;
+ } else if (isCOBOLoperator(ch)) {
+ ColourTo(styler, i, SCE_C_OPERATOR);
+ }
+ }
+ } else {
+ if (state == SCE_C_PREPROCESSOR) {
+ if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENT) {
+ if (ch == '\r' || ch == '\n') {
+ ColourTo(styler, i, state);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENTDOC) {
+ if (ch == '\r' || ch == '\n') {
+ if (((i > styler.GetStartSegment() + 2) || (
+ (initStyle == SCE_C_COMMENTDOC) &&
+ (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
+ ColourTo(styler, i, state);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ ColourTo(styler, i-1, state);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_STRING) {
+ if (ch == '"') {
+ ColourTo(styler, i, state);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_CHARACTER) {
+ if (ch == '\'') {
+ ColourTo(styler, i, state);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ }
+ chPrev = ch;
+ bNewLine = bSetNewLine;
+ if (bNewLine)
+ {
+ bAarea = false;
+ }
+ }
+ ColourTo(styler, lengthDoc - 1, state);
+}
+
+static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[],
+ Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF;
+ char chNext = styler[startPos];
+
+ bool bNewLine = true;
+ bool bAarea = !isspacechar(chNext);
+ int column = 0;
+ bool bComment = false;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ ++column;
+
+ if (bNewLine) {
+ column = 0;
+ bComment = (ch == '*' || ch == '/' || ch == '?');
+ }
+ if (column <= 1 && !bAarea) {
+ bAarea = !isspacechar(ch);
+ }
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (atEOL) {
+ int nContainment = styler.GetLineState(lineCurrent);
+ int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE;
+ if (bAarea && !bComment)
+ --lev;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) {
+ // this level is at the same level or less than the previous line
+ // therefore these is nothing for the previous header to collapse, so remove the header
+ styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
+ }
+ levelPrev = lev;
+ visibleChars = 0;
+ bAarea = false;
+ bNewLine = true;
+ lineCurrent++;
+ } else {
+ bNewLine = false;
+ }
+
+
+ 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 COBOLWordListDesc[] = {
+ "A Keywords",
+ "B Keywords",
+ "Extended Keywords",
+ 0
+};
+
+LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc);
diff --git a/scintilla/src/LexCPP.cxx b/scintilla/src/LexCPP.cxx
new file mode 100644
index 0000000..94995bc
--- /dev/null
+++ b/scintilla/src/LexCPP.cxx
@@ -0,0 +1,506 @@
+// Scintilla source code edit control
+/** @file LexCPP.cxx
+ ** Lexer for C++, C, Java, and JavaScript.
+ **/
+// 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 <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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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);
+}
+
+// Preconditions: sc.currentPos points to a character after '+' or '-'.
+// The test for pos reaching 0 should be redundant,
+// and is in only for safety measures.
+// Limitation: this code will give the incorrect answer for code like
+// a = b+++/ptn/...
+// Putting a space between the '++' post-inc operator and the '+' binary op
+// fixes this, and is highly recommended for readability anyway.
+static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) {
+ int pos = (int) sc.currentPos;
+ while (--pos > 0) {
+ char ch = styler[pos];
+ if (ch == '+' || ch == '-') {
+ return styler[pos - 1] == ch;
+ }
+ }
+ return false;
+}
+
+static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler, bool caseSensitive) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+
+ // property styling.within.preprocessor
+ // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default)
+ // or only from the initial # to the end of the command word(1).
+ bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
+
+ CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
+ CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
+
+ CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");
+
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+
+ // property lexer.cpp.allow.dollars
+ // Set to 0 to disallow the '$' character in identifiers with the cpp lexer.
+ if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) {
+ setWordStart.Add('$');
+ setWord.Add('$');
+ }
+
+ int chPrevNonWhite = ' ';
+ int visibleChars = 0;
+ bool lastWordWasUUID = false;
+ int styleBeforeDCKeyword = SCE_C_DEFAULT;
+ bool continuationLine = false;
+ bool isIncludePreprocessor = 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) {
+ 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;
+ isIncludePreprocessor = false;
+ }
+
+ // 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();
+ }
+ continuationLine = true;
+ continue;
+ }
+ }
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_C_OPERATOR:
+ sc.SetState(SCE_C_DEFAULT);
+ break;
+ case SCE_C_NUMBER:
+ // We accept almost anything because of hex. and number suffixes
+ if (!setWord.Contains(sc.ch)) {
+ sc.SetState(SCE_C_DEFAULT);
+ }
+ break;
+ case SCE_C_IDENTIFIER:
+ if (!setWord.Contains(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);
+ }
+ 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 {
+ if (sc.Match('/', '*') || sc.Match('/', '/')) {
+ sc.SetState(SCE_C_DEFAULT);
+ }
+ }
+ break;
+ case SCE_C_COMMENT:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_C_DEFAULT);
+ }
+ 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);
+ }
+ }
+ break;
+ case SCE_C_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_C_DEFAULT);
+ }
+ 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();
+ sc.ForwardSetState(SCE_C_DEFAULT);
+ } else if (!setDoxygen.Contains(sc.ch)) {
+ char s[100];
+ if (caseSensitive) {
+ sc.GetCurrent(s, sizeof(s));
+ } else {
+ sc.GetCurrentLowered(s, sizeof(s));
+ }
+ if (!IsASpace(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 (isIncludePreprocessor) {
+ if (sc.ch == '>') {
+ sc.ForwardSetState(SCE_C_DEFAULT);
+ isIncludePreprocessor = false;
+ }
+ } 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);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_C_DEFAULT) {
+ if (sc.Match('@', '\"')) {
+ sc.SetState(SCE_C_VERBATIM);
+ sc.Forward();
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ if (lastWordWasUUID) {
+ sc.SetState(SCE_C_UUID);
+ lastWordWasUUID = false;
+ } else {
+ sc.SetState(SCE_C_NUMBER);
+ }
+ } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
+ if (lastWordWasUUID) {
+ sc.SetState(SCE_C_UUID);
+ lastWordWasUUID = false;
+ } else {
+ sc.SetState(SCE_C_IDENTIFIER);
+ }
+ } else if (sc.Match('/', '*')) {
+ if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style
+ sc.SetState(SCE_C_COMMENTDOC);
+ } else {
+ sc.SetState(SCE_C_COMMENT);
+ }
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
+ // Support of Qt/Doxygen doc. style
+ sc.SetState(SCE_C_COMMENTLINEDOC);
+ else
+ sc.SetState(SCE_C_COMMENTLINE);
+ } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) &&
+ (!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) {
+ sc.SetState(SCE_C_REGEX); // JavaScript's RegEx
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_C_STRING);
+ isIncludePreprocessor = false; // ensure that '>' won't end the string
+ } else if (isIncludePreprocessor && sc.ch == '<') {
+ sc.SetState(SCE_C_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_C_CHARACTER);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ // Preprocessor commands are alone on their line
+ sc.SetState(SCE_C_PREPROCESSOR);
+ // Skip whitespace between # and preprocessor word
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (sc.Match("include")) {
+ isIncludePreprocessor = true;
+ }
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_C_OPERATOR);
+ }
+ }
+
+ 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;
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldCppDoc(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler) {
+
+ // property fold.comment
+ // This option enables folding multi-line comments and explicit fold points when using the C++ lexer.
+ // Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //}
+ // at the end of a section that should fold.
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+
+ // property fold.preprocessor
+ // This option enables folding preprocessor directives when using the C++ lexer.
+ // Includes C#'s explicit #region and #endregion folding directives.
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
+
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+
+ // property fold.at.else
+ // This option enables C++ folding on a "} else {" line of an if statement.
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (foldComment && IsStreamCommentStyle(style)) {
+ if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) {
+ levelNext++;
+ } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelNext--;
+ }
+ }
+ if (foldComment && (style == SCE_C_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelNext++;
+ } else if (chNext2 == '}') {
+ levelNext--;
+ }
+ }
+ }
+ if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
+ if (ch == '#') {
+ unsigned int j = i + 1;
+ while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ j++;
+ }
+ if (styler.Match(j, "region") || styler.Match(j, "if")) {
+ levelNext++;
+ } else if (styler.Match(j, "end")) {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_C_OPERATOR) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} else {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (!IsASpace(ch))
+ visibleChars++;
+ if (atEOL || (i == endPos-1)) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
+ // There is an empty line at end of file so give it same level and empty
+ styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
+ }
+ visibleChars = 0;
+ }
+ }
+}
+
+static const char *const cppWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "Documentation comment keywords",
+ "Unused",
+ "Global classes and typedefs",
+ 0,
+};
+
+static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+
+static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false);
+}
+
+LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc, cppWordLists);
+LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive, "cppnocase", FoldCppDoc, cppWordLists);
diff --git a/scintilla/src/LexCSS.cxx b/scintilla/src/LexCSS.cxx
new file mode 100644
index 0000000..9e4d1d7
--- /dev/null
+++ b/scintilla/src/LexCSS.cxx
@@ -0,0 +1,371 @@
+// Scintilla source code edit control
+/** @file LexCSS.cxx
+ ** Lexer for Cascading Style Sheets
+ ** Written by Jakub Vrána
+ ** Improved by Philippe Lhoste (CSS2)
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+static inline bool IsAWordChar(const unsigned int ch) {
+ /* FIXME:
+ * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars.
+ * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee
+ * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher
+ */
+ return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_';
+}
+
+inline bool IsCssOperator(const int ch) {
+ if (!((ch < 0x80) && isalnum(ch)) &&
+ (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
+ ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
+ /* CSS2 */
+ ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' ||
+ ch == '[' || ch == ']' || ch == '(' || ch == ')')) {
+ return true;
+ }
+ return false;
+}
+
+static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
+ WordList &css1Props = *keywordlists[0];
+ WordList &pseudoClasses = *keywordlists[1];
+ WordList &css2Props = *keywordlists[2];
+ WordList &css3Props = *keywordlists[3];
+ WordList &pseudoElements = *keywordlists[4];
+ WordList &exProps = *keywordlists[5];
+ WordList &exPseudoClasses = *keywordlists[6];
+ WordList &exPseudoElements = *keywordlists[7];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ int lastState = -1; // before operator
+ int lastStateC = -1; // before comment
+ int lastStateS = -1; // before single-quoted/double-quoted string
+ int op = ' '; // last operator
+ int opPrev = ' '; // last operator
+
+ for (; sc.More(); sc.Forward()) {
+ if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
+ if (lastStateC == -1) {
+ // backtrack to get last state:
+ // comments are like whitespace, so we must return to the previous state
+ unsigned int i = startPos;
+ for (; i > 0; i--) {
+ if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
+ if (lastStateC == SCE_CSS_OPERATOR) {
+ op = styler.SafeGetCharAt(i-1);
+ opPrev = styler.SafeGetCharAt(i-2);
+ while (--i) {
+ lastState = styler.StyleAt(i-1);
+ if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
+ break;
+ }
+ if (i == 0)
+ lastState = SCE_CSS_DEFAULT;
+ }
+ break;
+ }
+ }
+ if (i == 0)
+ lastStateC = SCE_CSS_DEFAULT;
+ }
+ sc.Forward();
+ sc.ForwardSetState(lastStateC);
+ }
+
+ if (sc.state == SCE_CSS_COMMENT)
+ continue;
+
+ if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
+ if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
+ continue;
+ unsigned int i = sc.currentPos;
+ while (i && styler[i-1] == '\\')
+ i--;
+ if ((sc.currentPos - i) % 2 == 1)
+ continue;
+ sc.ForwardSetState(lastStateS);
+ }
+
+ if (sc.state == SCE_CSS_OPERATOR) {
+ if (op == ' ') {
+ unsigned int i = startPos;
+ op = styler.SafeGetCharAt(i-1);
+ opPrev = styler.SafeGetCharAt(i-2);
+ while (--i) {
+ lastState = styler.StyleAt(i-1);
+ if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
+ break;
+ }
+ }
+ switch (op) {
+ case '@':
+ if (lastState == SCE_CSS_DEFAULT)
+ sc.SetState(SCE_CSS_DIRECTIVE);
+ break;
+ case '>':
+ case '+':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+ sc.SetState(SCE_CSS_DEFAULT);
+ break;
+ case '[':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || 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_MEDIA)
+ sc.SetState(SCE_CSS_DEFAULT);
+ else if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DIRECTIVE)
+ sc.SetState(SCE_CSS_IDENTIFIER);
+ break;
+ case '}':
+ if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT ||
+ lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_IDENTIFIER3)
+ sc.SetState(SCE_CSS_DEFAULT);
+ break;
+ case '(':
+ if (lastState == SCE_CSS_PSEUDOCLASS)
+ sc.SetState(SCE_CSS_TAG);
+ else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)
+ sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS);
+ break;
+ case ')':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
+ lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT)
+ sc.SetState(SCE_CSS_TAG);
+ break;
+ case ':':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
+ lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT)
+ sc.SetState(SCE_CSS_PSEUDOCLASS);
+ else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 ||
+ lastState == SCE_CSS_IDENTIFIER3 || lastState == SCE_CSS_EXTENDED_IDENTIFIER ||
+ lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
+ sc.SetState(SCE_CSS_VALUE);
+ break;
+ case '.':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+ sc.SetState(SCE_CSS_CLASS);
+ break;
+ case '#':
+ if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
+ lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+ sc.SetState(SCE_CSS_ID);
+ break;
+ case ',':
+ case '|':
+ case '~':
+ if (lastState == SCE_CSS_TAG)
+ sc.SetState(SCE_CSS_DEFAULT);
+ break;
+ case ';':
+ if (lastState == SCE_CSS_DIRECTIVE)
+ sc.SetState(SCE_CSS_DEFAULT);
+ else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT)
+ sc.SetState(SCE_CSS_IDENTIFIER);
+ break;
+ case '!':
+ if (lastState == SCE_CSS_VALUE)
+ sc.SetState(SCE_CSS_IMPORTANT);
+ break;
+ }
+ }
+
+ if (IsAWordChar(sc.ch)) {
+ if (sc.state == SCE_CSS_DEFAULT)
+ sc.SetState(SCE_CSS_TAG);
+ continue;
+ }
+
+ if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) {
+ sc.SetState(SCE_CSS_TAG);
+ continue;
+ }
+
+ if (IsAWordChar(sc.chPrev) && (
+ sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 ||
+ sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER ||
+ sc.state == SCE_CSS_UNKNOWN_IDENTIFIER ||
+ sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
+ sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
+ sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
+ sc.state == SCE_CSS_IMPORTANT ||
+ sc.state == SCE_CSS_DIRECTIVE
+ )) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ char *s2 = s;
+ while (*s2 && !IsAWordChar(*s2))
+ s2++;
+ switch (sc.state) {
+ case SCE_CSS_IDENTIFIER:
+ case SCE_CSS_IDENTIFIER2:
+ case SCE_CSS_IDENTIFIER3:
+ case SCE_CSS_EXTENDED_IDENTIFIER:
+ case SCE_CSS_UNKNOWN_IDENTIFIER:
+ if (css1Props.InList(s2))
+ sc.ChangeState(SCE_CSS_IDENTIFIER);
+ else if (css2Props.InList(s2))
+ sc.ChangeState(SCE_CSS_IDENTIFIER2);
+ else if (css3Props.InList(s2))
+ sc.ChangeState(SCE_CSS_IDENTIFIER3);
+ else if (exProps.InList(s2))
+ sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER);
+ else
+ sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
+ break;
+ case SCE_CSS_PSEUDOCLASS:
+ case SCE_CSS_PSEUDOELEMENT:
+ case SCE_CSS_EXTENDED_PSEUDOCLASS:
+ case SCE_CSS_EXTENDED_PSEUDOELEMENT:
+ case SCE_CSS_UNKNOWN_PSEUDOCLASS:
+ if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2))
+ sc.ChangeState(SCE_CSS_PSEUDOCLASS);
+ else if (opPrev == ':' && pseudoElements.InList(s2))
+ sc.ChangeState(SCE_CSS_PSEUDOELEMENT);
+ else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2))
+ sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS);
+ else if (opPrev == ':' && exPseudoElements.InList(s2))
+ sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT);
+ else
+ sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
+ break;
+ case SCE_CSS_IMPORTANT:
+ if (strcmp(s2, "important") != 0)
+ sc.ChangeState(SCE_CSS_VALUE);
+ break;
+ case SCE_CSS_DIRECTIVE:
+ if (op == '@' && strcmp(s2, "media") == 0)
+ sc.ChangeState(SCE_CSS_MEDIA);
+ break;
+ }
+ }
+
+ if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (
+ sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID ||
+ (sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */
+ sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
+ sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
+ sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
+ ))
+ ))
+ sc.SetState(SCE_CSS_TAG);
+
+ if (sc.Match('/', '*')) {
+ lastStateC = sc.state;
+ sc.SetState(SCE_CSS_COMMENT);
+ sc.Forward();
+ } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE)
+ && (sc.ch == '\"' || sc.ch == '\'')) {
+ lastStateS = sc.state;
+ sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
+ } else if (IsCssOperator(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.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{')
+ ) {
+ if (sc.state != SCE_CSS_OPERATOR)
+ lastState = sc.state;
+ sc.SetState(SCE_CSS_OPERATOR);
+ op = sc.ch;
+ opPrev = sc.chPrev;
+ }
+ }
+
+ sc.Complete();
+}
+
+static void FoldCSSDoc(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_CSS_COMMENT);
+ 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');
+ if (foldComment) {
+ if (!inComment && (style == SCE_CSS_COMMENT))
+ levelCurrent++;
+ else if (inComment && (style != SCE_CSS_COMMENT))
+ levelCurrent--;
+ inComment = (style == SCE_CSS_COMMENT);
+ }
+ if (style == SCE_CSS_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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 cssWordListDesc[] = {
+ "CSS1 Properties",
+ "Pseudo-classes",
+ "CSS2 Properties",
+ "CSS3 Properties",
+ "Pseudo-elements",
+ "Browser-Specific CSS Properties",
+ "Browser-Specific Pseudo-classes",
+ "Browser-Specific Pseudo-elements",
+ 0
+};
+
+LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);
diff --git a/scintilla/src/LexCaml.cxx b/scintilla/src/LexCaml.cxx
new file mode 100644
index 0000000..194063b
--- /dev/null
+++ b/scintilla/src/LexCaml.cxx
@@ -0,0 +1,449 @@
+// Scintilla source code edit control
+/** @file LexCaml.cxx
+ ** Lexer for Objective Caml.
+ **/
+// Copyright 2005-2009 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.
+ 20090629 Add full Standard ML '97 support.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "PropSetSimple.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 == '_';}
+
+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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#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)
+ PropSetSimple 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);
+
+ int chBase = 0, chToken = 0, chLit = 0;
+ WordList& keywords = *keywordlists[0];
+ WordList& keywords2 = *keywordlists[1];
+ WordList& keywords3 = *keywordlists[2];
+ const bool isSML = keywords.InList("andalso");
+ const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);
+
+ // set up [initial] state info (terminating states that shouldn't "bleed")
+ const int state_ = sc.state & 0x0f;
+ if (state_ <= SCE_CAML_CHAR
+ || (isSML && state_ == SCE_CAML_STRING))
+ sc.state = SCE_CAML_DEFAULT;
+ int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 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 (!isSML && sc.Match('`') && iscamlf(sc.chNext))
+ state2 = SCE_CAML_TAGNAME;
+ else if (!isSML && sc.Match('#') && isdigit(sc.chNext))
+ state2 = SCE_CAML_LINENUM;
+ else if (isdigit(sc.ch)) {
+ // it's a number, assume base 10
+ state2 = SCE_CAML_NUMBER, chBase = 10;
+ if (sc.Match('0')) {
+ // there MAY be a base specified...
+ const char* baseC = "bBoOxX";
+ if (isSML) {
+ if (sc.chNext == 'w')
+ sc.Forward(); // (consume SML "word" indicator)
+ baseC = "x";
+ }
+ // ... change to specified base AS REQUIRED
+ if (strchr(baseC, sc.chNext))
+ chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward();
+ }
+ } else if (!isSML && sc.Match('\'')) // (Caml char literal?)
+ state2 = SCE_CAML_CHAR, chLit = 0;
+ else if (isSML && sc.Match('#', '"')) // (SML char literal?)
+ state2 = SCE_CAML_CHAR, sc.Forward();
+ else if (sc.Match('"'))
+ state2 = SCE_CAML_STRING;
+ else if (sc.Match('(', '*'))
+ state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)...
+ else if (strchr("!?~" /* Caml "prefix-symbol" */
+ "=<>@^|&+-*/$%" /* Caml "infix-symbol" */
+ "()[]{};,:.#", sc.ch) // Caml "bracket" or ;,:.#
+ // SML "extra" ident chars
+ || (isSML && (sc.Match('\\') || sc.Match('`'))))
+ 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
+ || (!isSML && sc.Match('`')) // Caml extra term char
+ || (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars
+ // SML extra ident chars
+ && !(isSML && (sc.Match('\\') || sc.Match('`'))))) {
+ // 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
+ if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase))
+ break;
+ // how about an integer suffix?
+ if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n'))
+ && (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase)))
+ break;
+ // or a floating-point literal?
+ if (chBase == 10) {
+ // with a decimal point?
+ if (sc.Match('.')
+ && ((!isSML && sc.chPrev == '_')
+ || IsADigit(sc.chPrev, chBase)))
+ break;
+ // with an exponent? (I)
+ if ((sc.Match('e') || sc.Match('E'))
+ && ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_'))
+ || IsADigit(sc.chPrev, chBase)))
+ break;
+ // with an exponent? (II)
+ if (((!isSML && (sc.Match('+') || sc.Match('-')))
+ || (isSML && 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:
+ if (!isSML) {
+ // [try to] interpret as [additional] char literal char
+ if (sc.Match('\\')) {
+ chLit = 1; // (definitely IS a char literal)
+ if (sc.chPrev == '\\')
+ sc.ch = ' '; // (...\\')
+ // 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;
+ }/* else
+ // fall through for SML char literal (handle like string) */
+
+ case SCE_CAML_STRING:
+ // [try to] interpret as [additional] [SML char/] string literal char
+ if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext))
+ state2 = SCE_CAML_WHITE;
+ else if (sc.Match('\\') && sc.chPrev == '\\')
+ sc.ch = ' '; // (...\\")
+ // should we be terminating - one way or another?
+ else if ((sc.Match('"') && sc.chPrev != '\\')
+ || (isSML && sc.atLineEnd)) {
+ state2 = SCE_CAML_DEFAULT;
+ if (sc.Match('"'))
+ chColor++;
+ }
+ break;
+
+ case SCE_CAML_WHITE:
+ // [try to] interpret as [additional] SML embedded whitespace char
+ if (sc.Match('\\')) {
+ // style this puppy NOW...
+ state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++,
+ styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush();
+ // ... then backtrack to determine original SML literal type
+ int p = chColor - 2;
+ for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ;
+ if (p >= 0)
+ state2 = static_cast<int>(styler.StyleAt(p));
+ // take care of state change NOW
+ sc.ChangeState(state2), state2 = -1;
+ }
+ 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.Forward(), sc.ch = ' ' /* (*)... */, 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, int,
+ int,
+ WordList *[],
+ Accessor &)
+{
+}
+
+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/scintilla/src/LexCmake.cxx b/scintilla/src/LexCmake.cxx
new file mode 100644
index 0000000..483357f
--- /dev/null
+++ b/scintilla/src/LexCmake.cxx
@@ -0,0 +1,457 @@
+// Scintilla source code edit control
+/** @file LexCmake.cxx
+ ** Lexer for Cmake
+ **/
+// Copyright 2007 by Cristian Adam <cristian [dot] adam [at] gmx [dot] net>
+// based on the NSIS lexer
+// 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 "CharClassify.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static bool isCmakeNumber(char ch)
+{
+ return(ch >= '0' && ch <= '9');
+}
+
+static bool isCmakeChar(char ch)
+{
+ return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+static bool isCmakeLetter(char ch)
+{
+ return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+static bool CmakeNextLineHasElse(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 ( styler.Match(firstChar, "ELSE") || styler.Match(firstChar, "else"))
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse)
+{
+ // If the word is too long, it is not what we are looking for
+ if ( end - start > 20 )
+ return foldlevel;
+
+ int newFoldlevel = foldlevel;
+
+ 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';
+ }
+
+ if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0
+ || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0
+ || CompareCaseInsensitive(s, "ELSEIF") == 0 )
+ newFoldlevel++;
+ else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0
+ || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0)
+ newFoldlevel--;
+ else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 )
+ newFoldlevel++;
+ else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 )
+ newFoldlevel++;
+
+ return newFoldlevel;
+}
+
+static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
+{
+ char word[100] = {0};
+ char lowercaseWord[100] = {0};
+
+ WordList &Commands = *keywordLists[0];
+ WordList &Parameters = *keywordLists[1];
+ WordList &UserDefined = *keywordLists[2];
+
+ for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) {
+ word[i] = static_cast<char>( styler[ start + i ] );
+ lowercaseWord[i] = static_cast<char>(tolower(word[i]));
+ }
+
+ // Check for special words...
+ if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 )
+ return SCE_CMAKE_MACRODEF;
+
+ if ( CompareCaseInsensitive(word, "IF") == 0 || CompareCaseInsensitive(word, "ENDIF") == 0 )
+ return SCE_CMAKE_IFDEFINEDEF;
+
+ if ( CompareCaseInsensitive(word, "ELSEIF") == 0 || CompareCaseInsensitive(word, "ELSE") == 0 )
+ return SCE_CMAKE_IFDEFINEDEF;
+
+ if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0)
+ return SCE_CMAKE_WHILEDEF;
+
+ if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0)
+ return SCE_CMAKE_FOREACHDEF;
+
+ if ( Commands.InList(lowercaseWord) )
+ return SCE_CMAKE_COMMANDS;
+
+ if ( Parameters.InList(word) )
+ return SCE_CMAKE_PARAMETERS;
+
+
+ if ( UserDefined.InList(word) )
+ return SCE_CMAKE_USERDEFINED;
+
+ if ( strlen(word) > 3 ) {
+ if ( word[1] == '{' && word[strlen(word)-1] == '}' )
+ return SCE_CMAKE_VARIABLE;
+ }
+
+ // To check for numbers
+ if ( isCmakeNumber( word[0] ) ) {
+ bool bHasSimpleCmakeNumber = true;
+ for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) {
+ if ( !isCmakeNumber( word[j] ) ) {
+ bHasSimpleCmakeNumber = false;
+ break;
+ }
+ }
+
+ if ( bHasSimpleCmakeNumber )
+ return SCE_CMAKE_NUMBER;
+ }
+
+ return SCE_CMAKE_DEFAULT;
+}
+
+static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
+{
+ int state = SCE_CMAKE_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 );
+
+ unsigned int nLengthDoc = startPos + length;
+ styler.StartSegment( startPos );
+
+ char cCurrChar;
+ bool bVarInString = false;
+ bool bClassicVarInString = false;
+
+ unsigned int i;
+ for ( i = startPos; i < nLengthDoc; i++ ) {
+ cCurrChar = styler.SafeGetCharAt( i );
+ char cNextChar = styler.SafeGetCharAt(i+1);
+
+ switch (state) {
+ case SCE_CMAKE_DEFAULT:
+ if ( cCurrChar == '#' ) { // we have a comment line
+ styler.ColourTo(i-1, state );
+ state = SCE_CMAKE_COMMENT;
+ break;
+ }
+ if ( cCurrChar == '"' ) {
+ styler.ColourTo(i-1, state );
+ state = SCE_CMAKE_STRINGDQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+ if ( cCurrChar == '\'' ) {
+ styler.ColourTo(i-1, state );
+ state = SCE_CMAKE_STRINGRQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+ if ( cCurrChar == '`' ) {
+ styler.ColourTo(i-1, state );
+ state = SCE_CMAKE_STRINGLQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+
+ // CMake Variable
+ if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) {
+ styler.ColourTo(i-1,state);
+ state = SCE_CMAKE_VARIABLE;
+
+ // If it is a number, we must check and set style here first...
+ if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
+ styler.ColourTo( i, SCE_CMAKE_NUMBER);
+
+ break;
+ }
+
+ break;
+ case SCE_CMAKE_COMMENT:
+ if ( cNextChar == '\n' || cNextChar == '\r' ) {
+ // Special case:
+ if ( cCurrChar == '\\' ) {
+ styler.ColourTo(i-2,state);
+ styler.ColourTo(i,SCE_CMAKE_DEFAULT);
+ }
+ else {
+ styler.ColourTo(i,state);
+ state = SCE_CMAKE_DEFAULT;
+ }
+ }
+ break;
+ case SCE_CMAKE_STRINGDQ:
+ case SCE_CMAKE_STRINGLQ:
+ case SCE_CMAKE_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_CMAKE_STRINGDQ ) {
+ styler.ColourTo(i,state);
+ state = SCE_CMAKE_DEFAULT;
+ break;
+ }
+
+ if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) {
+ styler.ColourTo(i,state);
+ state = SCE_CMAKE_DEFAULT;
+ break;
+ }
+
+ if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) {
+ styler.ColourTo(i,state);
+ state = SCE_CMAKE_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_CMAKE_DEFAULT;
+ }
+ }
+ break;
+
+ case SCE_CMAKE_VARIABLE:
+
+ // CMake Variable:
+ if ( cCurrChar == '$' )
+ state = SCE_CMAKE_DEFAULT;
+ else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
+ state = SCE_CMAKE_DEFAULT;
+ else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) {
+ state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler );
+ styler.ColourTo( i, state);
+ state = SCE_CMAKE_DEFAULT;
+ }
+ else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) {
+ if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER )
+ styler.ColourTo( i-1, SCE_CMAKE_NUMBER );
+
+ state = SCE_CMAKE_DEFAULT;
+
+ if ( cCurrChar == '"' ) {
+ state = SCE_CMAKE_STRINGDQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if ( cCurrChar == '`' ) {
+ state = SCE_CMAKE_STRINGLQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if ( cCurrChar == '\'' ) {
+ state = SCE_CMAKE_STRINGRQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if ( cCurrChar == '#' ) {
+ state = SCE_CMAKE_COMMENT;
+ }
+ }
+ break;
+ }
+
+ if ( state == SCE_CMAKE_COMMENT) {
+ styler.ColourTo(i,state);
+ }
+ else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) {
+ bool bIngoreNextDollarSign = false;
+
+ if ( bVarInString && cCurrChar == '$' ) {
+ bVarInString = false;
+ bIngoreNextDollarSign = true;
+ }
+ else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) {
+ styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
+ bVarInString = false;
+ bIngoreNextDollarSign = false;
+ }
+
+ else if ( bVarInString && !isCmakeChar(cNextChar) ) {
+ int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler);
+ if ( nWordState == SCE_CMAKE_VARIABLE )
+ styler.ColourTo( i, SCE_CMAKE_STRINGVAR);
+ bVarInString = false;
+ }
+ // Covers "${TEST}..."
+ else if ( bClassicVarInString && cNextChar == '}' ) {
+ styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
+ bClassicVarInString = false;
+ }
+
+ // Start of var in string
+ if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) {
+ styler.ColourTo( i-1, state);
+ bClassicVarInString = true;
+ bVarInString = false;
+ }
+ else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) {
+ styler.ColourTo( i-1, state);
+ bVarInString = true;
+ bClassicVarInString = false;
+ }
+ }
+ }
+
+ // Colourise remaining document
+ styler.ColourTo(nLengthDoc-1,state);
+}
+
+static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ // No folding enabled, no reason to continue...
+ if ( styler.GetPropertyInt("fold") == 0 )
+ return;
+
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
+
+ int lineCurrent = styler.GetLine(startPos);
+ unsigned int safeStartPos = styler.LineStart( lineCurrent );
+
+ bool bArg1 = true;
+ int nWordStart = -1;
+
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ int levelNext = levelCurrent;
+
+ for (unsigned int i = safeStartPos; i < startPos + length; i++) {
+ char chCurr = styler.SafeGetCharAt(i);
+
+ if ( bArg1 ) {
+ if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) {
+ nWordStart = i;
+ }
+ else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) {
+ int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse);
+
+ if ( newLevel == levelNext ) {
+ if ( foldAtElse ) {
+ if ( CmakeNextLineHasElse(i, startPos + length, styler) )
+ levelNext--;
+ }
+ }
+ else
+ levelNext = newLevel;
+ bArg1 = false;
+ }
+ }
+
+ if ( chCurr == '\n' ) {
+ if ( bArg1 && foldAtElse) {
+ if ( CmakeNextLineHasElse(i, startPos + length, styler) )
+ levelNext--;
+ }
+
+ // If we are on a new line...
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (levelUse < levelNext )
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+
+ lineCurrent++;
+ levelCurrent = levelNext;
+ bArg1 = true; // New line, lets look at first argument again
+ nWordStart = -1;
+ }
+ }
+
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+}
+
+static const char * const cmakeWordLists[] = {
+ "Commands",
+ "Parameters",
+ "UserDefined",
+ 0,
+ 0,};
+
+LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists);
diff --git a/scintilla/src/LexConf.cxx b/scintilla/src/LexConf.cxx
new file mode 100644
index 0000000..5bacae9
--- /dev/null
+++ b/scintilla/src/LexConf.cxx
@@ -0,0 +1,188 @@
+// Scintilla source code edit control
+/** @file LexConf.cxx
+ ** Lexer for Apache Configuration Files.
+ **
+ ** First working version contributed by Ahmad Zawawi <zeus_go64@hotmail.com> on October 28, 2000.
+ ** i created this lexer because i needed something pretty when dealing
+ ** when Apache Configuration files...
+ **/
+// Copyright 1998-2001 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 "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
+{
+ int state = SCE_CONF_DEFAULT;
+ char chNext = styler[startPos];
+ int lengthDoc = startPos + length;
+ // create a buffer large enough to take the largest chunk...
+ char *buffer = new char[length];
+ int bufferCount = 0;
+
+ // this assumes that we have 2 keyword list in conf.properties
+ WordList &directives = *keywordLists[0];
+ WordList &params = *keywordLists[1];
+
+ // go through all provided text segment
+ // using the hand-written state machine shown below
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ for (int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ i++;
+ continue;
+ }
+ switch(state) {
+ case SCE_CONF_DEFAULT:
+ if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
+ // whitespace is simply ignored here...
+ styler.ColourTo(i,SCE_CONF_DEFAULT);
+ break;
+ } else if( ch == '#' ) {
+ // signals the start of a comment...
+ state = SCE_CONF_COMMENT;
+ styler.ColourTo(i,SCE_CONF_COMMENT);
+ } else if( ch == '.' /*|| ch == '/'*/) {
+ // signals the start of a file...
+ state = SCE_CONF_EXTENSION;
+ styler.ColourTo(i,SCE_CONF_EXTENSION);
+ } else if( ch == '"') {
+ state = SCE_CONF_STRING;
+ styler.ColourTo(i,SCE_CONF_STRING);
+ } else if( isascii(ch) && ispunct(ch) ) {
+ // signals an operator...
+ // no state jump necessary for this
+ // simple case...
+ styler.ColourTo(i,SCE_CONF_OPERATOR);
+ } else if( isascii(ch) && isalpha(ch) ) {
+ // signals the start of an identifier
+ bufferCount = 0;
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ state = SCE_CONF_IDENTIFIER;
+ } else if( isascii(ch) && isdigit(ch) ) {
+ // signals the start of a number
+ bufferCount = 0;
+ buffer[bufferCount++] = ch;
+ //styler.ColourTo(i,SCE_CONF_NUMBER);
+ state = SCE_CONF_NUMBER;
+ } else {
+ // style it the default style..
+ styler.ColourTo(i,SCE_CONF_DEFAULT);
+ }
+ break;
+
+ case SCE_CONF_COMMENT:
+ // if we find a newline here,
+ // we simply go to default state
+ // else continue to work on it...
+ if( ch == '\n' || ch == '\r' ) {
+ state = SCE_CONF_DEFAULT;
+ } else {
+ styler.ColourTo(i,SCE_CONF_COMMENT);
+ }
+ break;
+
+ case SCE_CONF_EXTENSION:
+ // if we find a non-alphanumeric char,
+ // we simply go to default state
+ // else we're still dealing with an extension...
+ if( (isascii(ch) && isalnum(ch)) || (ch == '_') ||
+ (ch == '-') || (ch == '$') ||
+ (ch == '/') || (ch == '.') || (ch == '*') )
+ {
+ styler.ColourTo(i,SCE_CONF_EXTENSION);
+ } else {
+ state = SCE_CONF_DEFAULT;
+ chNext = styler[i--];
+ }
+ break;
+
+ case SCE_CONF_STRING:
+ // if we find the end of a string char, we simply go to default state
+ // else we're still dealing with an string...
+ if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) {
+ state = SCE_CONF_DEFAULT;
+ }
+ styler.ColourTo(i,SCE_CONF_STRING);
+ break;
+
+ case SCE_CONF_IDENTIFIER:
+ // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
+ if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) {
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ } else {
+ state = SCE_CONF_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // check if the buffer contains a keyword, and highlight it if it is a keyword...
+ if(directives.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_CONF_DIRECTIVE );
+ } else if(params.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_CONF_PARAMETER );
+ } else if(strchr(buffer,'/') || strchr(buffer,'.')) {
+ styler.ColourTo(i-1,SCE_CONF_EXTENSION);
+ } else {
+ styler.ColourTo(i-1,SCE_CONF_DEFAULT);
+ }
+
+ // push back the faulty character
+ chNext = styler[i--];
+
+ }
+ break;
+
+ case SCE_CONF_NUMBER:
+ // stay in CONF_NUMBER state until we find a non-numeric
+ if( (isascii(ch) && isdigit(ch)) || ch == '.') {
+ buffer[bufferCount++] = ch;
+ } else {
+ state = SCE_CONF_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // Colourize here...
+ if( strchr(buffer,'.') ) {
+ // it is an IP address...
+ styler.ColourTo(i-1,SCE_CONF_IP);
+ } else {
+ // normal number
+ styler.ColourTo(i-1,SCE_CONF_NUMBER);
+ }
+
+ // push back a character
+ chNext = styler[i--];
+ }
+ break;
+
+ }
+ }
+ delete []buffer;
+}
+
+static const char * const confWordListDesc[] = {
+ "Directives",
+ "Parameters",
+ 0
+};
+
+LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc);
diff --git a/scintilla/src/LexCrontab.cxx b/scintilla/src/LexCrontab.cxx
new file mode 100644
index 0000000..29ef74e
--- /dev/null
+++ b/scintilla/src/LexCrontab.cxx
@@ -0,0 +1,222 @@
+// Scintilla source code edit control
+/** @file LexCrontab.cxx
+ ** Lexer to use with extended crontab files used by a powerful
+ ** Windows scheduler/event monitor/automation manager nnCron.
+ ** (http://nemtsev.eserv.ru/)
+ **/
+// Copyright 1998-2001 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 "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList
+*keywordLists[], Accessor &styler)
+{
+ int state = SCE_NNCRONTAB_DEFAULT;
+ char chNext = styler[startPos];
+ int lengthDoc = startPos + length;
+ // create a buffer large enough to take the largest chunk...
+ char *buffer = new char[length];
+ int bufferCount = 0;
+ // used when highliting environment variables inside quoted string:
+ bool insideString = false;
+
+ // this assumes that we have 3 keyword list in conf.properties
+ WordList &section = *keywordLists[0];
+ WordList &keyword = *keywordLists[1];
+ WordList &modifier = *keywordLists[2];
+
+ // go through all provided text segment
+ // using the hand-written state machine shown below
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ for (int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ i++;
+ continue;
+ }
+ switch(state) {
+ case SCE_NNCRONTAB_DEFAULT:
+ if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
+ // whitespace is simply ignored here...
+ styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
+ break;
+ } else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') {
+ // signals the start of a task...
+ state = SCE_NNCRONTAB_TASK;
+ styler.ColourTo(i,SCE_NNCRONTAB_TASK);
+ }
+ else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' ||
+ styler.SafeGetCharAt(i+1) == '\t')) {
+ // signals the start of an extended comment...
+ state = SCE_NNCRONTAB_COMMENT;
+ styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
+ } else if( ch == '#' ) {
+ // signals the start of a plain comment...
+ state = SCE_NNCRONTAB_COMMENT;
+ styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
+ } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') {
+ // signals the end of a task...
+ state = SCE_NNCRONTAB_TASK;
+ styler.ColourTo(i,SCE_NNCRONTAB_TASK);
+ } else if( ch == '"') {
+ state = SCE_NNCRONTAB_STRING;
+ styler.ColourTo(i,SCE_NNCRONTAB_STRING);
+ } else if( ch == '%') {
+ // signals environment variables
+ state = SCE_NNCRONTAB_ENVIRONMENT;
+ styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
+ } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') {
+ // signals environment variables
+ state = SCE_NNCRONTAB_ENVIRONMENT;
+ styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
+ } else if( ch == '*' ) {
+ // signals an asterisk
+ // no state jump necessary for this simple case...
+ styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK);
+ } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) {
+ // signals the start of an identifier
+ bufferCount = 0;
+ buffer[bufferCount++] = ch;
+ state = SCE_NNCRONTAB_IDENTIFIER;
+ } else if( isascii(ch) && isdigit(ch) ) {
+ // signals the start of a number
+ bufferCount = 0;
+ buffer[bufferCount++] = ch;
+ state = SCE_NNCRONTAB_NUMBER;
+ } else {
+ // style it the default style..
+ styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
+ }
+ break;
+
+ case SCE_NNCRONTAB_COMMENT:
+ // if we find a newline here,
+ // we simply go to default state
+ // else continue to work on it...
+ if( ch == '\n' || ch == '\r' ) {
+ state = SCE_NNCRONTAB_DEFAULT;
+ } else {
+ styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
+ }
+ break;
+
+ case SCE_NNCRONTAB_TASK:
+ // if we find a newline here,
+ // we simply go to default state
+ // else continue to work on it...
+ if( ch == '\n' || ch == '\r' ) {
+ state = SCE_NNCRONTAB_DEFAULT;
+ } else {
+ styler.ColourTo(i,SCE_NNCRONTAB_TASK);
+ }
+ break;
+
+ case SCE_NNCRONTAB_STRING:
+ if( ch == '%' ) {
+ state = SCE_NNCRONTAB_ENVIRONMENT;
+ insideString = true;
+ styler.ColourTo(i-1,SCE_NNCRONTAB_STRING);
+ break;
+ }
+ // if we find the end of a string char, we simply go to default state
+ // else we're still dealing with an string...
+ if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') ||
+ (ch == '\n') || (ch == '\r') ) {
+ state = SCE_NNCRONTAB_DEFAULT;
+ }
+ styler.ColourTo(i,SCE_NNCRONTAB_STRING);
+ break;
+
+ case SCE_NNCRONTAB_ENVIRONMENT:
+ // if we find the end of a string char, we simply go to default state
+ // else we're still dealing with an string...
+ if( ch == '%' && insideString ) {
+ state = SCE_NNCRONTAB_STRING;
+ insideString = false;
+ break;
+ }
+ if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\')
+ || (ch == '\n') || (ch == '\r') || (ch == '>') ) {
+ state = SCE_NNCRONTAB_DEFAULT;
+ styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
+ break;
+ }
+ styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT);
+ break;
+
+ case SCE_NNCRONTAB_IDENTIFIER:
+ // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
+ if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') ||
+ (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') ||
+ (ch == '@') ) {
+ buffer[bufferCount++] = ch;
+ } else {
+ state = SCE_NNCRONTAB_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // check if the buffer contains a keyword,
+ // and highlight it if it is a keyword...
+ if(section.InList(buffer)) {
+ styler.ColourTo(i,SCE_NNCRONTAB_SECTION );
+ } else if(keyword.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD );
+ } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
+ // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
+ // }
+ else if(modifier.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER );
+ } else {
+ styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT);
+ }
+ // push back the faulty character
+ chNext = styler[i--];
+ }
+ break;
+
+ case SCE_NNCRONTAB_NUMBER:
+ // stay in CONF_NUMBER state until we find a non-numeric
+ if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) {
+ buffer[bufferCount++] = ch;
+ } else {
+ state = SCE_NNCRONTAB_DEFAULT;
+ buffer[bufferCount] = '\0';
+ // Colourize here... (normal number)
+ styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER);
+ // push back a character
+ chNext = styler[i--];
+ }
+ break;
+ }
+ }
+ delete []buffer;
+}
+
+static const char * const cronWordListDesc[] = {
+ "Section keywords and Forth words",
+ "nnCrontab keywords",
+ "Modifiers",
+ 0
+};
+
+LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc);
diff --git a/scintilla/src/LexCsound.cxx b/scintilla/src/LexCsound.cxx
new file mode 100644
index 0000000..13eae88
--- /dev/null
+++ b/scintilla/src/LexCsound.cxx
@@ -0,0 +1,210 @@
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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 (isascii(ch) && 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);
diff --git a/scintilla/src/LexD.cxx b/scintilla/src/LexD.cxx
new file mode 100644
index 0000000..f116014
--- /dev/null
+++ b/scintilla/src/LexD.cxx
@@ -0,0 +1,399 @@
+/** @file LexD.cxx
+ ** Lexer for D.
+ **
+ ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com>
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/* Nested comments require keeping the value of the nesting level for every
+ position in the document. But since scintilla always styles line by line,
+ we only need to store one value per line. The non-negative number indicates
+ nesting level at the end of the line.
+*/
+
+// Underscore, letter, digit and universal alphas from C99 Appendix D.
+
+static bool IsWordStart(int ch) {
+ return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch);
+}
+
+static bool IsWord(int ch) {
+ return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch);
+}
+
+static bool IsDoxygen(int ch) {
+ if (isascii(ch) && islower(ch))
+ return true;
+ if (ch == '$' || ch == '@' || ch == '\\' ||
+ ch == '&' || ch == '#' || ch == '<' || ch == '>' ||
+ ch == '{' || ch == '}' || ch == '[' || ch == ']')
+ return true;
+ return false;
+}
+
+static bool IsStringSuffix(int ch) {
+ return ch == 'c' || ch == 'w' || ch == 'd';
+}
+
+
+static void ColouriseDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler, bool caseSensitive) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2]; //doxygen
+ WordList &keywords4 = *keywordlists[3];
+ WordList &keywords5 = *keywordlists[4];
+ WordList &keywords6 = *keywordlists[5];
+ WordList &keywords7 = *keywordlists[6];
+
+ int styleBeforeDCKeyword = SCE_D_DEFAULT;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ int curLine = styler.GetLine(startPos);
+ int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0;
+ bool numFloat = false; // Float literals have '+' and '-' signs
+ bool numHex = false;
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart) {
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, curNcLevel);
+ }
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_D_OPERATOR:
+ sc.SetState(SCE_D_DEFAULT);
+ break;
+ case SCE_D_NUMBER:
+ // We accept almost anything because of hex. and number suffixes
+ if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) {
+ continue;
+ } else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) {
+ // Don't parse 0..2 as number.
+ numFloat=true;
+ continue;
+ } else if ( ( sc.ch == '-' || sc.ch == '+' ) && ( /*sign and*/
+ ( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/
+ ( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) { /*hex*/
+ // Parse exponent sign in float literals: 2e+10 0x2e+10
+ continue;
+ } else {
+ sc.SetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_IDENTIFIER:
+ if (!IsWord(sc.ch)) {
+ char s[1000];
+ if (caseSensitive) {
+ sc.GetCurrent(s, sizeof(s));
+ } else {
+ sc.GetCurrentLowered(s, sizeof(s));
+ }
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_D_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_D_WORD2);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_D_TYPEDEF);
+ } else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_D_WORD5);
+ } else if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_D_WORD6);
+ } else if (keywords7.InList(s)) {
+ sc.ChangeState(SCE_D_WORD7);
+ }
+ sc.SetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_COMMENT:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_COMMENTDOC:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_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_D_COMMENTDOC;
+ sc.SetState(SCE_D_COMMENTDOCKEYWORD);
+ }
+ }
+ break;
+ case SCE_D_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_COMMENTLINEDOC:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_D_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_D_COMMENTLINEDOC;
+ sc.SetState(SCE_D_COMMENTDOCKEYWORD);
+ }
+ }
+ break;
+ case SCE_D_COMMENTDOCKEYWORD:
+ if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) {
+ sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ } else if (!IsDoxygen(sc.ch)) {
+ char s[100];
+ if (caseSensitive) {
+ sc.GetCurrent(s, sizeof(s));
+ } else {
+ sc.GetCurrentLowered(s, sizeof(s));
+ }
+ if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
+ sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
+ }
+ sc.SetState(styleBeforeDCKeyword);
+ }
+ break;
+ case SCE_D_COMMENTNESTED:
+ if (sc.Match('+', '/')) {
+ if (curNcLevel > 0)
+ curNcLevel -= 1;
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, curNcLevel);
+ sc.Forward();
+ if (curNcLevel == 0) {
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ } else if (sc.Match('/','+')) {
+ curNcLevel += 1;
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, curNcLevel);
+ sc.Forward();
+ }
+ break;
+ case SCE_D_STRING:
+ if (sc.ch == '\\') {
+ if (sc.chNext == '"' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '"') {
+ if(IsStringSuffix(sc.chNext))
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_CHARACTER:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_D_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ // Char has no suffixes
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_STRINGEOL:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_STRINGB:
+ if (sc.ch == '`') {
+ if(IsStringSuffix(sc.chNext))
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ break;
+ case SCE_D_STRINGR:
+ if (sc.ch == '"') {
+ if(IsStringSuffix(sc.chNext))
+ sc.Forward();
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ }
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_D_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_D_NUMBER);
+ numFloat = sc.ch == '.';
+ // Remember hex literal
+ numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' );
+ } else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q')
+ && sc.chNext == '"' ) {
+ // Limited support for hex and delimited strings: parse as r""
+ sc.SetState(SCE_D_STRINGR);
+ sc.Forward();
+ } else if (IsWordStart(sc.ch) || sc.ch == '$') {
+ sc.SetState(SCE_D_IDENTIFIER);
+ } else if (sc.Match('/','+')) {
+ curNcLevel += 1;
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, curNcLevel);
+ sc.SetState(SCE_D_COMMENTNESTED);
+ sc.Forward();
+ } else if (sc.Match('/', '*')) {
+ if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style
+ sc.SetState(SCE_D_COMMENTDOC);
+ } else {
+ sc.SetState(SCE_D_COMMENT);
+ }
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
+ // Support of Qt/Doxygen doc. style
+ sc.SetState(SCE_D_COMMENTLINEDOC);
+ else
+ sc.SetState(SCE_D_COMMENTLINE);
+ } else if (sc.ch == '"') {
+ sc.SetState(SCE_D_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_D_CHARACTER);
+ } else if (sc.ch == '`') {
+ sc.SetState(SCE_D_STRINGB);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_D_OPERATOR);
+ if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_D_COMMENT ||
+ style == SCE_D_COMMENTDOC ||
+ style == SCE_D_COMMENTDOCKEYWORD ||
+ style == SCE_D_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
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+
+ // property lexer.d.fold.at.else
+ // This option enables D folding on a "} else {" line of an if statement.
+ bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else",
+ styler.GetPropertyInt("fold.at.else", 0)) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ 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 (style == SCE_D_OPERATOR) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} else {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (atEOL) {
+ if (foldComment) { // Handle nested comments
+ int nc;
+ nc = styler.GetLineState(lineCurrent);
+ nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;
+ levelNext += nc;
+ }
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!IsASpace(ch))
+ visibleChars++;
+ }
+}
+
+static void FoldDDoc(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler) {
+ FoldDoc(startPos, length, initStyle, styler);
+}
+
+static const char * const dWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "Documentation comment keywords",
+ "Type definitions and aliases",
+ "Keywords 5",
+ "Keywords 6",
+ "Keywords 7",
+ 0,
+ };
+
+static void ColouriseDDoc(unsigned int startPos, int length,
+ int initStyle, WordList *keywordlists[], Accessor &styler) {
+ ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+
+LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists);
diff --git a/scintilla/src/LexEScript.cxx b/scintilla/src/LexEScript.cxx
new file mode 100644
index 0000000..3e53627
--- /dev/null
+++ b/scintilla/src/LexEScript.cxx
@@ -0,0 +1,273 @@
+// Scintilla source code edit control
+/** @file LexESCRIPT.cxx
+ ** Lexer for ESCRIPT
+ **/
+// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com)
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+
+
+static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+
+ // Do not leak onto next line
+ /*if (initStyle == SCE_ESCRIPT_STRINGEOL)
+ initStyle = SCE_ESCRIPT_DEFAULT;*/
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0;
+
+ for (; sc.More(); sc.Forward()) {
+
+ /*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) {
+ // Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_ESCRIPT_STRING);
+ }*/
+
+ // 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_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) {
+ sc.SetState(SCE_ESCRIPT_DEFAULT);
+ } else if (sc.state == SCE_ESCRIPT_NUMBER) {
+ if (!IsADigit(sc.ch) || sc.ch != '.') {
+ sc.SetState(SCE_ESCRIPT_DEFAULT);
+ }
+ } else if (sc.state == SCE_ESCRIPT_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+ char s[100];
+ if (caseSensitive) {
+ sc.GetCurrent(s, sizeof(s));
+ } else {
+ sc.GetCurrentLowered(s, sizeof(s));
+ }
+
+// sc.GetCurrentLowered(s, sizeof(s));
+
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_ESCRIPT_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_ESCRIPT_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_ESCRIPT_WORD3);
+ // sc.state = SCE_ESCRIPT_IDENTIFIER;
+ }
+ sc.SetState(SCE_ESCRIPT_DEFAULT);
+ }
+ } else if (sc.state == SCE_ESCRIPT_COMMENT) {
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
+ }
+ } else if (sc.state == SCE_ESCRIPT_COMMENTDOC) {
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
+ }
+ } else if (sc.state == SCE_ESCRIPT_COMMENTLINE) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_ESCRIPT_DEFAULT);
+ }
+ } else if (sc.state == SCE_ESCRIPT_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_ESCRIPT_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_ESCRIPT_NUMBER);
+ } else if (IsAWordStart(sc.ch) || (sc.ch == '#')) {
+ sc.SetState(SCE_ESCRIPT_IDENTIFIER);
+ } else if (sc.Match('/', '*')) {
+ sc.SetState(SCE_ESCRIPT_COMMENT);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(SCE_ESCRIPT_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_ESCRIPT_STRING);
+ //} else if (isoperator(static_cast<char>(sc.ch))) {
+ } else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') {
+ sc.SetState(SCE_ESCRIPT_OPERATOR);
+ } else if (sc.ch == '{' || sc.ch == '}') {
+ sc.SetState(SCE_ESCRIPT_BRACE);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+
+static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) {
+ int lev = 0;
+ if (strcmp(prevWord, "end") == 0) return lev;
+ if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0)
+ return -1;
+
+ if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0
+ || strcmp(s, "program") == 0 || strcmp(s, "function") == 0
+ || strcmp(s, "while") == 0 || strcmp(s, "case") == 0
+ || strcmp(s, "if") == 0 ) {
+ lev = 1;
+ } else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0
+ || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0
+ || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0
+ || strcmp(s, "endif") == 0 ) {
+ lev = -1;
+ }
+
+ return lev;
+}
+
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_ESCRIPT_COMMENT ||
+ style == SCE_ESCRIPT_COMMENTDOC ||
+ style == SCE_ESCRIPT_COMMENTLINE;
+}
+
+static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
+ //~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ // Do not know how to fold the comment at the moment.
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldComment = true;
+ 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];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+
+ int lastStart = 0;
+ char prevWord[32] = "";
+
+ 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)) {
+ levelCurrent++;
+ } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+
+ if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelCurrent++;
+ } else if (chNext2 == '}') {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3)
+ {
+ // Store last word start point.
+ lastStart = i;
+ }
+
+ if (style == SCE_ESCRIPT_WORD3) {
+ if(iswordchar(ch) && !iswordchar(chNext)) {
+ char s[32];
+ unsigned int j;
+ for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) {
+ s[j] = static_cast<char>(tolower(styler[lastStart + j]));
+ }
+ s[j] = '\0';
+ levelCurrent += classifyFoldPointESCRIPT(s, prevWord);
+ strcpy(prevWord, s);
+ }
+ }
+ 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;
+ strcpy(prevWord, "");
+ }
+
+ 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 ESCRIPTWordLists[] = {
+ "Primary keywords and identifiers",
+ "Intrinsic functions",
+ "Extended and user defined functions",
+ 0,
+};
+
+LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists);
diff --git a/scintilla/src/LexEiffel.cxx b/scintilla/src/LexEiffel.cxx
new file mode 100644
index 0000000..4f8e7e2
--- /dev/null
+++ b/scintilla/src/LexEiffel.cxx
@@ -0,0 +1,238 @@
+// Scintilla source code edit control
+/** @file LexEiffel.cxx
+ ** Lexer for Eiffel.
+ **/
+// Copyright 1998-2001 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 <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool isEiffelOperator(unsigned int ch) {
+ // '.' left out as it is used to make up numbers
+ return ch == '*' || 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(unsigned int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(unsigned int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static void ColouriseEiffelDoc(unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_EIFFEL_STRINGEOL) {
+ if (sc.ch != '\r' && sc.ch != '\n') {
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ } else if (sc.state == SCE_EIFFEL_OPERATOR) {
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ } else if (sc.state == SCE_EIFFEL_WORD) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (!keywords.InList(s)) {
+ sc.ChangeState(SCE_EIFFEL_IDENTIFIER);
+ }
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ } else if (sc.state == SCE_EIFFEL_NUMBER) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ } else if (sc.state == SCE_EIFFEL_COMMENTLINE) {
+ if (sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ } else if (sc.state == SCE_EIFFEL_STRING) {
+ if (sc.ch == '%') {
+ sc.Forward();
+ } else if (sc.ch == '\"') {
+ sc.Forward();
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ } else if (sc.state == SCE_EIFFEL_CHARACTER) {
+ if (sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_EIFFEL_STRINGEOL);
+ } else if (sc.ch == '%') {
+ sc.Forward();
+ } else if (sc.ch == '\'') {
+ sc.Forward();
+ sc.SetState(SCE_EIFFEL_DEFAULT);
+ }
+ }
+
+ if (sc.state == SCE_EIFFEL_DEFAULT) {
+ if (sc.ch == '-' && sc.chNext == '-') {
+ sc.SetState(SCE_EIFFEL_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_EIFFEL_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_EIFFEL_CHARACTER);
+ } else if (IsADigit(sc.ch) || (sc.ch == '.')) {
+ sc.SetState(SCE_EIFFEL_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_EIFFEL_WORD);
+ } else if (isEiffelOperator(sc.ch)) {
+ sc.SetState(SCE_EIFFEL_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static bool IsEiffelComment(Accessor &styler, int pos, int len) {
+ return len>1 && styler[pos]=='-' && styler[pos+1]=='-';
+}
+
+static void FoldEiffelDocIndent(unsigned int startPos, int length, int,
+ WordList *[], Accessor &styler) {
+ int lengthDoc = 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, IsEiffelComment);
+ char chNext = styler[startPos];
+ for (int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
+ int lev = indentCurrent;
+ int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment);
+ 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, IsEiffelComment);
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ }
+ indentCurrent = indentNext;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ }
+ }
+}
+
+static void FoldEiffelDocKeyWords(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);
+ // lastDeferred should be determined by looking back to last keyword in case
+ // the "deferred" is on a line before "class"
+ bool lastDeferred = false;
+ 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_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) {
+ 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, "check") == 0) ||
+ (strcmp(s, "debug") == 0) ||
+ (strcmp(s, "deferred") == 0) ||
+ (strcmp(s, "do") == 0) ||
+ (strcmp(s, "from") == 0) ||
+ (strcmp(s, "if") == 0) ||
+ (strcmp(s, "inspect") == 0) ||
+ (strcmp(s, "once") == 0)
+ )
+ levelCurrent++;
+ if (!lastDeferred && (strcmp(s, "class") == 0))
+ levelCurrent++;
+ if (strcmp(s, "end") == 0)
+ levelCurrent--;
+ lastDeferred = strcmp(s, "deferred") == 0;
+ }
+
+ 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 eiffelWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc);
+LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc);
diff --git a/scintilla/src/LexErlang.cxx b/scintilla/src/LexErlang.cxx
new file mode 100644
index 0000000..43cff21
--- /dev/null
+++ b/scintilla/src/LexErlang.cxx
@@ -0,0 +1,619 @@
+// Scintilla source code edit control
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+/** @file LexErlang.cxx
+ ** Lexer for Erlang.
+ ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com)
+ ** Originally wrote by Peter-Henry Mander,
+ ** based on Matlab lexer by José Fonseca.
+ **/
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static int is_radix(int radix, int ch) {
+ int digit;
+
+ if (36 < radix || 2 > radix)
+ return 0;
+
+ if (isdigit(ch)) {
+ digit = ch - '0';
+ } else if (isalnum(ch)) {
+ digit = toupper(ch) - 'A' + 10;
+ } else {
+ return 0;
+ }
+
+ return (digit < radix);
+}
+
+typedef enum {
+ STATE_NULL,
+ COMMENT,
+ COMMENT_FUNCTION,
+ COMMENT_MODULE,
+ COMMENT_DOC,
+ COMMENT_DOC_MACRO,
+ ATOM_UNQUOTED,
+ ATOM_QUOTED,
+ NODE_NAME_UNQUOTED,
+ NODE_NAME_QUOTED,
+ MACRO_START,
+ MACRO_UNQUOTED,
+ MACRO_QUOTED,
+ RECORD_START,
+ RECORD_UNQUOTED,
+ RECORD_QUOTED,
+ NUMERAL_START,
+ NUMERAL_BASE_VALUE,
+ NUMERAL_FLOAT,
+ NUMERAL_EXPONENT,
+ PREPROCESSOR
+} atom_parse_state_t;
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_');
+}
+
+static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ StyleContext sc(startPos, length, initStyle, styler);
+ WordList &reservedWords = *keywordlists[0];
+ WordList &erlangBIFs = *keywordlists[1];
+ WordList &erlangPreproc = *keywordlists[2];
+ WordList &erlangModulesAtt = *keywordlists[3];
+ WordList &erlangDoc = *keywordlists[4];
+ WordList &erlangDocMacro = *keywordlists[5];
+ int radix_digits = 0;
+ int exponent_digits = 0;
+ atom_parse_state_t parse_state = STATE_NULL;
+ atom_parse_state_t old_parse_state = STATE_NULL;
+ bool to_late_to_comment = false;
+ char cur[100];
+ int old_style = SCE_ERLANG_DEFAULT;
+
+ styler.StartAt(startPos);
+
+ for (; sc.More(); sc.Forward()) {
+ int style = SCE_ERLANG_DEFAULT;
+ if (STATE_NULL != parse_state) {
+
+ switch (parse_state) {
+
+ case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break;
+
+ /* COMMENTS ------------------------------------------------------*/
+ case COMMENT : {
+ if (sc.ch != '%') {
+ to_late_to_comment = true;
+ } else if (!to_late_to_comment && sc.ch == '%') {
+ // Switch to comment level 2 (Function)
+ sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION);
+ old_style = SCE_ERLANG_COMMENT_FUNCTION;
+ parse_state = COMMENT_FUNCTION;
+ sc.Forward();
+ }
+ }
+ // V--- Falling through!
+ case COMMENT_FUNCTION : {
+ if (sc.ch != '%') {
+ to_late_to_comment = true;
+ } else if (!to_late_to_comment && sc.ch == '%') {
+ // Switch to comment level 3 (Module)
+ sc.ChangeState(SCE_ERLANG_COMMENT_MODULE);
+ old_style = SCE_ERLANG_COMMENT_MODULE;
+ parse_state = COMMENT_MODULE;
+ sc.Forward();
+ }
+ }
+ // V--- Falling through!
+ case COMMENT_MODULE : {
+ if (parse_state != COMMENT) {
+ // Search for comment documentation
+ if (sc.chNext == '@') {
+ old_parse_state = parse_state;
+ parse_state = ('{' == sc.ch)
+ ? COMMENT_DOC_MACRO
+ : COMMENT_DOC;
+ sc.ForwardSetState(sc.state);
+ }
+ }
+
+ // All comments types fall here.
+ if (sc.atLineEnd) {
+ to_late_to_comment = false;
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case COMMENT_DOC :
+ // V--- Falling through!
+ case COMMENT_DOC_MACRO : {
+
+ if (!isalnum(sc.ch)) {
+ // Try to match documentation comment
+ sc.GetCurrent(cur, sizeof(cur));
+
+ if (parse_state == COMMENT_DOC_MACRO
+ && erlangDocMacro.InList(cur)) {
+ sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO);
+ while (sc.ch != '}' && !sc.atLineEnd)
+ sc.Forward();
+ } else if (erlangDoc.InList(cur)) {
+ sc.ChangeState(SCE_ERLANG_COMMENT_DOC);
+ } else {
+ sc.ChangeState(old_style);
+ }
+
+ // Switch back to old state
+ sc.SetState(old_style);
+ parse_state = old_parse_state;
+ }
+
+ if (sc.atLineEnd) {
+ to_late_to_comment = false;
+ sc.ChangeState(old_style);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Atoms ---------------------------------------------------------*/
+ case ATOM_UNQUOTED : {
+ if ('@' == sc.ch){
+ parse_state = NODE_NAME_UNQUOTED;
+ } else if (sc.ch == ':') {
+ // Searching for module name
+ if (sc.chNext == ' ') {
+ // error
+ sc.ChangeState(SCE_ERLANG_UNKNOWN);
+ parse_state = STATE_NULL;
+ } else {
+ sc.Forward();
+ if (isalnum(sc.ch)) {
+ sc.GetCurrent(cur, sizeof(cur));
+ sc.ChangeState(SCE_ERLANG_MODULES);
+ sc.SetState(SCE_ERLANG_MODULES);
+ }
+ }
+ } else if (!IsAWordChar(sc.ch)) {
+
+ sc.GetCurrent(cur, sizeof(cur));
+ if (reservedWords.InList(cur)) {
+ style = SCE_ERLANG_KEYWORD;
+ } else if (erlangBIFs.InList(cur)
+ && strcmp(cur,"erlang:")){
+ style = SCE_ERLANG_BIFS;
+ } else if (sc.ch == '(' || '/' == sc.ch){
+ style = SCE_ERLANG_FUNCTION_NAME;
+ } else {
+ style = SCE_ERLANG_ATOM;
+ }
+
+ sc.ChangeState(style);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+
+ } break;
+
+ case ATOM_QUOTED : {
+ if ( '@' == sc.ch ){
+ parse_state = NODE_NAME_QUOTED;
+ } else if ('\'' == sc.ch && '\\' != sc.chPrev) {
+ sc.ChangeState(SCE_ERLANG_ATOM);
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Node names ----------------------------------------------------*/
+ case NODE_NAME_UNQUOTED : {
+ if ('@' == sc.ch) {
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ } else if (!IsAWordChar(sc.ch)) {
+ sc.ChangeState(SCE_ERLANG_NODE_NAME);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case NODE_NAME_QUOTED : {
+ if ('@' == sc.ch) {
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ } else if ('\'' == sc.ch && '\\' != sc.chPrev) {
+ sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED);
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Records -------------------------------------------------------*/
+ case RECORD_START : {
+ if ('\'' == sc.ch) {
+ parse_state = RECORD_QUOTED;
+ } else if (isalpha(sc.ch) && islower(sc.ch)) {
+ parse_state = RECORD_UNQUOTED;
+ } else { // error
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case RECORD_UNQUOTED : {
+ if (!IsAWordChar(sc.ch)) {
+ sc.ChangeState(SCE_ERLANG_RECORD);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case RECORD_QUOTED : {
+ if ('\'' == sc.ch && '\\' != sc.chPrev) {
+ sc.ChangeState(SCE_ERLANG_RECORD_QUOTED);
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Macros --------------------------------------------------------*/
+ case MACRO_START : {
+ if ('\'' == sc.ch) {
+ parse_state = MACRO_QUOTED;
+ } else if (isalpha(sc.ch)) {
+ parse_state = MACRO_UNQUOTED;
+ } else { // error
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case MACRO_UNQUOTED : {
+ if (!IsAWordChar(sc.ch)) {
+ sc.ChangeState(SCE_ERLANG_MACRO);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ case MACRO_QUOTED : {
+ if ('\'' == sc.ch && '\\' != sc.chPrev) {
+ sc.ChangeState(SCE_ERLANG_MACRO_QUOTED);
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Numerics ------------------------------------------------------*/
+ /* Simple integer */
+ case NUMERAL_START : {
+ if (isdigit(sc.ch)) {
+ radix_digits *= 10;
+ radix_digits += sc.ch - '0'; // Assuming ASCII here!
+ } else if ('#' == sc.ch) {
+ if (2 > radix_digits || 36 < radix_digits) {
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ } else {
+ parse_state = NUMERAL_BASE_VALUE;
+ }
+ } else if ('.' == sc.ch && isdigit(sc.chNext)) {
+ radix_digits = 0;
+ parse_state = NUMERAL_FLOAT;
+ } else if ('e' == sc.ch || 'E' == sc.ch) {
+ exponent_digits = 0;
+ parse_state = NUMERAL_EXPONENT;
+ } else {
+ radix_digits = 0;
+ sc.ChangeState(SCE_ERLANG_NUMBER);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* Integer in other base than 10 (x#yyy) */
+ case NUMERAL_BASE_VALUE : {
+ if (!is_radix(radix_digits,sc.ch)) {
+ radix_digits = 0;
+
+ if (!isalnum(sc.ch))
+ sc.ChangeState(SCE_ERLANG_NUMBER);
+
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* Float (x.yyy) */
+ case NUMERAL_FLOAT : {
+ if ('e' == sc.ch || 'E' == sc.ch) {
+ exponent_digits = 0;
+ parse_state = NUMERAL_EXPONENT;
+ } else if (!isdigit(sc.ch)) {
+ sc.ChangeState(SCE_ERLANG_NUMBER);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ /* Exponent, either integer or float (xEyy, x.yyEzzz) */
+ case NUMERAL_EXPONENT : {
+ if (('-' == sc.ch || '+' == sc.ch)
+ && (isdigit(sc.chNext))) {
+ sc.Forward();
+ } else if (!isdigit(sc.ch)) {
+ if (0 < exponent_digits)
+ sc.ChangeState(SCE_ERLANG_NUMBER);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ } else {
+ ++exponent_digits;
+ }
+ } break;
+
+ /* -------------------------------------------------------------- */
+ /* Preprocessor --------------------------------------------------*/
+ case PREPROCESSOR : {
+ if (!IsAWordChar(sc.ch)) {
+
+ sc.GetCurrent(cur, sizeof(cur));
+ if (erlangPreproc.InList(cur)) {
+ style = SCE_ERLANG_PREPROC;
+ } else if (erlangModulesAtt.InList(cur)) {
+ style = SCE_ERLANG_MODULES_ATT;
+ }
+
+ sc.ChangeState(style);
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ parse_state = STATE_NULL;
+ }
+ } break;
+
+ }
+
+ } /* End of : STATE_NULL != parse_state */
+ else
+ {
+ switch (sc.state) {
+ case SCE_ERLANG_VARIABLE : {
+ if (!IsAWordChar(sc.ch))
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ } break;
+ case SCE_ERLANG_STRING : {
+ if (sc.ch == '\"' && sc.chPrev != '\\')
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ } break;
+ case SCE_ERLANG_COMMENT : {
+ if (sc.atLineEnd)
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ } break;
+ case SCE_ERLANG_CHARACTER : {
+ if (sc.chPrev == '\\') {
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ } else if (sc.ch != '\\') {
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ }
+ } break;
+ case SCE_ERLANG_OPERATOR : {
+ if (sc.chPrev == '.') {
+ if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\'
+ || sc.ch == '^') {
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+ } else {
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ }
+ } else {
+ sc.SetState(SCE_ERLANG_DEFAULT);
+ }
+ } break;
+ }
+ }
+
+ if (sc.state == SCE_ERLANG_DEFAULT) {
+ bool no_new_state = false;
+
+ switch (sc.ch) {
+ case '\"' : sc.SetState(SCE_ERLANG_STRING); break;
+ case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break;
+ case '%' : {
+ parse_state = COMMENT;
+ sc.SetState(SCE_ERLANG_COMMENT);
+ } break;
+ case '#' : {
+ parse_state = RECORD_START;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } break;
+ case '?' : {
+ parse_state = MACRO_START;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } break;
+ case '\'' : {
+ parse_state = ATOM_QUOTED;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } break;
+ case '+' :
+ case '-' : {
+ if (IsADigit(sc.chNext)) {
+ parse_state = NUMERAL_START;
+ radix_digits = 0;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } else if (sc.ch != '+') {
+ parse_state = PREPROCESSOR;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ }
+ } break;
+ default : no_new_state = true;
+ }
+
+ if (no_new_state) {
+ if (isdigit(sc.ch)) {
+ parse_state = NUMERAL_START;
+ radix_digits = sc.ch - '0';
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } else if (isupper(sc.ch) || '_' == sc.ch) {
+ sc.SetState(SCE_ERLANG_VARIABLE);
+ } else if (isalpha(sc.ch)) {
+ parse_state = ATOM_UNQUOTED;
+ sc.SetState(SCE_ERLANG_UNKNOWN);
+ } else if (isoperator(static_cast<char>(sc.ch))
+ || sc.ch == '\\') {
+ sc.SetState(SCE_ERLANG_OPERATOR);
+ }
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+static int ClassifyErlangFoldPoint(
+ Accessor &styler,
+ int styleNext,
+ int keyword_start
+) {
+ int lev = 0;
+ if (styler.Match(keyword_start,"case")
+ || (
+ styler.Match(keyword_start,"fun")
+ && (SCE_ERLANG_FUNCTION_NAME != styleNext)
+ )
+ || styler.Match(keyword_start,"if")
+ || styler.Match(keyword_start,"query")
+ || styler.Match(keyword_start,"receive")
+ ) {
+ ++lev;
+ } else if (styler.Match(keyword_start,"end")) {
+ --lev;
+ }
+
+ return lev;
+}
+
+static void FoldErlangDoc(
+ unsigned int startPos, int length, int initStyle,
+ WordList** /*keywordlists*/, Accessor &styler
+) {
+ unsigned int endPos = startPos + length;
+ int currentLine = styler.GetLine(startPos);
+ int lev;
+ int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK;
+ int currentLevel = previousLevel;
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ int stylePrev;
+ int keyword_start = 0;
+ char ch;
+ char chNext = styler.SafeGetCharAt(startPos);
+ bool atEOL;
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ // Get styles
+ stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n');
+
+ if (stylePrev != SCE_ERLANG_KEYWORD
+ && style == SCE_ERLANG_KEYWORD) {
+ keyword_start = i;
+ }
+
+ // Fold on keywords
+ if (stylePrev == SCE_ERLANG_KEYWORD
+ && style != SCE_ERLANG_KEYWORD
+ && style != SCE_ERLANG_ATOM
+ ) {
+ currentLevel += ClassifyErlangFoldPoint(styler,
+ styleNext,
+ keyword_start);
+ }
+
+ // Fold on comments
+ if (style == SCE_ERLANG_COMMENT
+ || style == SCE_ERLANG_COMMENT_MODULE
+ || style == SCE_ERLANG_COMMENT_FUNCTION) {
+
+ if (ch == '%' && chNext == '{') {
+ currentLevel++;
+ } else if (ch == '%' && chNext == '}') {
+ currentLevel--;
+ }
+ }
+
+ // Fold on braces
+ if (style == SCE_ERLANG_OPERATOR) {
+ if (ch == '{' || ch == '(' || ch == '[') {
+ currentLevel++;
+ } else if (ch == '}' || ch == ')' || ch == ']') {
+ currentLevel--;
+ }
+ }
+
+
+ if (atEOL) {
+ lev = previousLevel;
+
+ if (currentLevel > previousLevel)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+
+ if (lev != styler.LevelAt(currentLine))
+ styler.SetLevel(currentLine, lev);
+
+ currentLine++;
+ previousLevel = currentLevel;
+ }
+
+ }
+
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ styler.SetLevel(currentLine,
+ previousLevel
+ | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK));
+}
+
+static const char * const erlangWordListDesc[] = {
+ "Erlang Reserved words",
+ "Erlang BIFs",
+ "Erlang Preprocessor",
+ "Erlang Module Attributes",
+ "Erlang Documentation",
+ "Erlang Documentation Macro",
+ 0
+};
+
+LexerModule lmErlang(
+ SCLEX_ERLANG,
+ ColouriseErlangDoc,
+ "erlang",
+ FoldErlangDoc,
+ erlangWordListDesc);
diff --git a/scintilla/src/LexFlagship.cxx b/scintilla/src/LexFlagship.cxx
new file mode 100644
index 0000000..c2bfe19
--- /dev/null
+++ b/scintilla/src/LexFlagship.cxx
@@ -0,0 +1,352 @@
+// Scintilla source code edit control
+/** @file LexFlagShip.cxx
+ ** Lexer for Harbour and FlagShip.
+ ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.)
+ **/
+// Copyright 2005 by Randy Butler
+// Copyright 2010 by Xavi <jarabal/at/gmail.com> (Harbour)
+// 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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch)
+{
+ return ch >= 0x80 ||
+ (isalnum(ch) || ch == '_');
+}
+
+static void ColouriseFlagShipDoc(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];
+
+ // property lexer.flagship.styling.within.preprocessor
+ // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the
+ // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code.
+ bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0;
+
+ CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");
+
+ int visibleChars = 0;
+ int closeStringChar = 0;
+ int styleBeforeDCKeyword = SCE_FS_DEFAULT;
+ bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_FS_OPERATOR:
+ case SCE_FS_OPERATOR_C:
+ case SCE_FS_WORDOPERATOR:
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ break;
+ case SCE_FS_IDENTIFIER:
+ case SCE_FS_IDENTIFIER_C:
+ if (!IsAWordChar(sc.ch)) {
+ char s[64];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C);
+ } else if (bEnableCode && keywords3.InList(s)) {
+ sc.ChangeState(SCE_FS_KEYWORD3);
+ } else if (bEnableCode && keywords4.InList(s)) {
+ sc.ChangeState(SCE_FS_KEYWORD4);
+ }// Else, it is really an identifier...
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ }
+ break;
+ case SCE_FS_NUMBER:
+ if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_FS_DEFAULT);
+ }
+ break;
+ case SCE_FS_NUMBER_C:
+ if (!IsAWordChar(sc.ch) && sc.ch != '.') {
+ sc.SetState(SCE_FS_DEFAULT_C);
+ }
+ break;
+ case SCE_FS_CONSTANT:
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_FS_DEFAULT);
+ }
+ break;
+ case SCE_FS_STRING:
+ case SCE_FS_STRING_C:
+ if (sc.ch == closeStringChar) {
+ sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C);
+ }
+ break;
+ case SCE_FS_STRINGEOL:
+ case SCE_FS_STRINGEOL_C:
+ if (sc.atLineStart) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ }
+ break;
+ case SCE_FS_COMMENTDOC:
+ case SCE_FS_COMMENTDOC_C:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ } 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 = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C;
+ sc.SetState(SCE_FS_COMMENTDOCKEYWORD);
+ }
+ }
+ break;
+ case SCE_FS_COMMENT:
+ case SCE_FS_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_FS_DEFAULT);
+ }
+ break;
+ case SCE_FS_COMMENTLINEDOC:
+ case SCE_FS_COMMENTLINEDOC_C:
+ if (sc.atLineStart) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ } 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 = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C;
+ sc.SetState(SCE_FS_COMMENTDOCKEYWORD);
+ }
+ }
+ break;
+ case SCE_FS_COMMENTDOCKEYWORD:
+ if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) &&
+ sc.Match('*', '/')) {
+ sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR);
+ sc.Forward();
+ sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ } else if (!setDoxygen.Contains(sc.ch)) {
+ char s[64];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) {
+ sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR);
+ }
+ sc.SetState(styleBeforeDCKeyword);
+ }
+ break;
+ case SCE_FS_PREPROCESSOR:
+ case SCE_FS_PREPROCESSOR_C:
+ if (sc.atLineEnd) {
+ if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ }
+ } else if (stylingWithinPreprocessor) {
+ if (IsASpaceOrTab(sc.ch)) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ }
+ } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ }
+ break;
+ case SCE_FS_DISABLEDCODE:
+ if (sc.ch == '#' && visibleChars == 0) {
+ sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C);
+ do { // Skip whitespace between # and preprocessor word
+ sc.Forward();
+ } while (IsASpaceOrTab(sc.ch) && sc.More());
+ if (sc.MatchIgnoreCase("pragma")) {
+ sc.Forward(6);
+ do { // Skip more whitespace until keyword
+ sc.Forward();
+ } while (IsASpaceOrTab(sc.ch) && sc.More());
+ if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) {
+ bEnableCode = true;
+ sc.SetState(SCE_FS_DISABLEDCODE);
+ sc.Forward(sc.ch == '_' ? 8 : 6);
+ sc.ForwardSetState(SCE_FS_DEFAULT);
+ } else {
+ sc.ChangeState(SCE_FS_DISABLEDCODE);
+ }
+ } else {
+ sc.ChangeState(SCE_FS_DISABLEDCODE);
+ }
+ }
+ break;
+ case SCE_FS_DATE:
+ if (sc.ch == '}') {
+ sc.ForwardSetState(SCE_FS_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_FS_STRINGEOL);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) {
+ if (bEnableCode &&
+ (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) {
+ sc.SetState(SCE_FS_WORDOPERATOR);
+ sc.Forward(4);
+ } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) {
+ sc.SetState(SCE_FS_WORDOPERATOR);
+ sc.Forward(3);
+ } else if (bEnableCode &&
+ (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") ||
+ (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) {
+ sc.SetState(SCE_FS_CONSTANT);
+ sc.Forward(2);
+ } else if (sc.Match('/', '*')) {
+ sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C);
+ sc.Forward();
+ } else if (bEnableCode && sc.Match('&', '&')) {
+ sc.SetState(SCE_FS_COMMENTLINE);
+ sc.Forward();
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C);
+ sc.Forward();
+ } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) {
+ sc.SetState(SCE_FS_COMMENT);
+ } else if (sc.ch == '\"' || sc.ch == '\'') {
+ sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C);
+ closeStringChar = sc.ch;
+ } else if (closeStringChar == '>' && sc.ch == '<') {
+ sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C);
+ do { // Skip whitespace between # and preprocessor word
+ sc.Forward();
+ } while (IsASpaceOrTab(sc.ch) && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
+ } else if (sc.MatchIgnoreCase("include")) {
+ if (stylingWithinPreprocessor) {
+ closeStringChar = '>';
+ }
+ } else if (sc.MatchIgnoreCase("pragma")) {
+ sc.Forward(6);
+ do { // Skip more whitespace until keyword
+ sc.Forward();
+ } while (IsASpaceOrTab(sc.ch) && sc.More());
+ if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) {
+ bEnableCode = false;
+ if (stylingWithinPreprocessor) {
+ sc.SetState(SCE_FS_DISABLEDCODE);
+ sc.Forward(8);
+ sc.ForwardSetState(SCE_FS_DEFAULT_C);
+ } else {
+ sc.SetState(SCE_FS_DISABLEDCODE);
+ }
+ } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) {
+ bEnableCode = true;
+ sc.SetState(SCE_FS_DISABLEDCODE);
+ sc.Forward(sc.ch == '_' ? 8 : 6);
+ sc.ForwardSetState(SCE_FS_DEFAULT);
+ }
+ }
+ } else if (bEnableCode && sc.ch == '{') {
+ int p = 0;
+ int chSeek;
+ unsigned int endPos(startPos + length);
+ do { // Skip whitespace
+ chSeek = sc.GetRelative(++p);
+ } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos));
+ if (chSeek == '^') {
+ sc.SetState(SCE_FS_DATE);
+ } else {
+ sc.SetState(SCE_FS_OPERATOR);
+ }
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C);
+ } else if (IsAWordChar(sc.ch)) {
+ sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C);
+ } else if (isoperator(static_cast<char>(sc.ch)) || (bEnableCode && sc.ch == '@')) {
+ sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C);
+ }
+ }
+
+ if (sc.atLineEnd) {
+ visibleChars = 0;
+ closeStringChar = 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 && lineCurrent > 0) {
+ lineCurrent--;
+ startPos = styler.LineStart(lineCurrent);
+ }
+ int spaceFlags = 0;
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
+ 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-1)) {
+ int lev = indentCurrent;
+ int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
+ int spaceFlags2 = 0;
+ int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2);
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ }
+ indentCurrent = indentNext;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ }
+ }
+}
+
+static const char * const FSWordListDesc[] = {
+ "Keywords Commands",
+ "Std Library Functions",
+ "Procedure, return, exit",
+ "Class (oop)",
+ "Doxygen keywords",
+ 0
+};
+
+LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);
diff --git a/scintilla/src/LexForth.cxx b/scintilla/src/LexForth.cxx
new file mode 100644
index 0000000..6365f6c
--- /dev/null
+++ b/scintilla/src/LexForth.cxx
@@ -0,0 +1,176 @@
+// Scintilla source code edit control
+/** @file LexForth.cxx
+ ** Lexer for FORTH
+ **/
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
+ ch == '_' || ch == '?' || ch == '"' || ch == '@' ||
+ ch == '!' || ch == '[' || ch == ']' || ch == '/' ||
+ ch == '+' || ch == '-' || ch == '*' || ch == '<' ||
+ ch == '>' || ch == '=' || ch == ';' || ch == '(' ||
+ ch == ')' );
+}
+
+static inline bool IsAWordStart(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
+}
+
+static inline bool IsANumChar(int ch) {
+ return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
+}
+
+static inline bool IsASpaceChar(int ch) {
+ return (ch < 0x80) && isspace(ch);
+}
+
+static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
+ Accessor &styler) {
+
+ WordList &control = *keywordLists[0];
+ WordList &keyword = *keywordLists[1];
+ WordList &defword = *keywordLists[2];
+ WordList &preword1 = *keywordLists[3];
+ WordList &preword2 = *keywordLists[4];
+ WordList &strings = *keywordLists[5];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_FORTH_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_FORTH_DEFAULT);
+ }
+ }else if (sc.state == SCE_FORTH_COMMENT_ML) {
+ if (sc.ch == ')') {
+ sc.ForwardSetState(SCE_FORTH_DEFAULT);
+ }
+ }else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
+ // handle numbers here too, because what we thought was a number might
+ // turn out to be a keyword e.g. 2DUP
+ if (IsASpaceChar(sc.ch) ) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
+ if (control.InList(s)) {
+ sc.ChangeState(SCE_FORTH_CONTROL);
+ } else if (keyword.InList(s)) {
+ sc.ChangeState(SCE_FORTH_KEYWORD);
+ } else if (defword.InList(s)) {
+ sc.ChangeState(SCE_FORTH_DEFWORD);
+ } else if (preword1.InList(s)) {
+ sc.ChangeState(SCE_FORTH_PREWORD1);
+ } else if (preword2.InList(s)) {
+ sc.ChangeState(SCE_FORTH_PREWORD2);
+ } else if (strings.InList(s)) {
+ sc.ChangeState(SCE_FORTH_STRING);
+ newState = SCE_FORTH_STRING;
+ }
+ sc.SetState(newState);
+ }
+ if (sc.state == SCE_FORTH_NUMBER) {
+ if (IsASpaceChar(sc.ch)) {
+ sc.SetState(SCE_FORTH_DEFAULT);
+ } else if (!IsANumChar(sc.ch)) {
+ sc.ChangeState(SCE_FORTH_IDENTIFIER);
+ }
+ }
+ }else if (sc.state == SCE_FORTH_STRING) {
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_FORTH_DEFAULT);
+ }
+ }else if (sc.state == SCE_FORTH_LOCALE) {
+ if (sc.ch == '}') {
+ sc.ForwardSetState(SCE_FORTH_DEFAULT);
+ }
+ }else if (sc.state == SCE_FORTH_DEFWORD) {
+ if (IsASpaceChar(sc.ch)) {
+ sc.SetState(SCE_FORTH_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_FORTH_DEFAULT) {
+ if (sc.ch == '\\'){
+ sc.SetState(SCE_FORTH_COMMENT);
+ } else if (sc.ch == '(' &&
+ (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
+ (sc.atLineEnd || IsASpaceChar(sc.chNext))) {
+ sc.SetState(SCE_FORTH_COMMENT_ML);
+ } else if ( (sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) {
+ // number starting with $ is a hex number
+ sc.SetState(SCE_FORTH_NUMBER);
+ while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext))
+ sc.Forward();
+ } else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
+ // number starting with % is binary
+ sc.SetState(SCE_FORTH_NUMBER);
+ while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
+ sc.Forward();
+ } else if ( isascii(sc.ch) &&
+ (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) )
+ ){
+ sc.SetState(SCE_FORTH_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_FORTH_IDENTIFIER);
+ } else if (sc.ch == '{') {
+ sc.SetState(SCE_FORTH_LOCALE);
+ } else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) {
+ // highlight word definitions e.g. : GCD ( n n -- n ) ..... ;
+ // ^ ^^^
+ sc.SetState(SCE_FORTH_DEFWORD);
+ while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext))
+ sc.Forward();
+ } else if (sc.ch == ';' &&
+ (sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
+ (sc.atLineEnd || IsASpaceChar(sc.chNext)) ) {
+ // mark the ';' that ends a word
+ sc.SetState(SCE_FORTH_DEFWORD);
+ sc.ForwardSetState(SCE_FORTH_DEFAULT);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+static void FoldForthDoc(unsigned int, int, int, WordList *[],
+ Accessor &) {
+}
+
+static const char * const forthWordLists[] = {
+ "control keywords",
+ "keywords",
+ "definition words",
+ "prewords with one argument",
+ "prewords with two arguments",
+ "string definition keywords",
+ 0,
+ };
+
+LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);
+
+
diff --git a/scintilla/src/LexFortran.cxx b/scintilla/src/LexFortran.cxx
new file mode 100644
index 0000000..c1b3fee
--- /dev/null
+++ b/scintilla/src/LexFortran.cxx
@@ -0,0 +1,466 @@
+// Scintilla source code edit control
+/** @file LexFortran.cxx
+ ** Lexer for Fortran.
+ ** Writen by Chuan-jian Shen, Last changed Sep. 2003
+ **/
+// Copyright 1998-2001 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/***********************************************/
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%');
+}
+/**********************************************/
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch));
+}
+/***************************************/
+inline bool IsABlank(unsigned int ch) {
+ return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ;
+}
+/***************************************/
+inline bool IsALineEnd(char ch) {
+ return ((ch == '\n') || (ch == '\r')) ;
+}
+/***************************************/
+unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) {
+ while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue;
+ if (styler.SafeGetCharAt(pos) == '\n') pos++;
+ while (IsABlank(styler.SafeGetCharAt(pos++))) continue;
+ char chCur = styler.SafeGetCharAt(pos);
+ if (chCur == '&') {
+ while (IsABlank(styler.SafeGetCharAt(++pos))) continue;
+ return pos;
+ } else {
+ return pos;
+ }
+}
+/***************************************/
+static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler, bool isFixFormat) {
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ /***************************************/
+ int posLineStart = 0, numNonBlank = 0, prevState = 0;
+ int endPos = startPos + length;
+ /***************************************/
+ // backtrack to the nearest keyword
+ while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) {
+ startPos--;
+ }
+ startPos = styler.LineStart(styler.GetLine(startPos));
+ initStyle = styler.StyleAt(startPos - 1);
+ StyleContext sc(startPos, endPos-startPos, initStyle, styler);
+ /***************************************/
+ for (; sc.More(); sc.Forward()) {
+ // remember the start position of the line
+ if (sc.atLineStart) {
+ posLineStart = sc.currentPos;
+ numNonBlank = 0;
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ if (!IsASpaceOrTab(sc.ch)) numNonBlank ++;
+ /***********************************************/
+ // Handle the fix format generically
+ int toLineStart = sc.currentPos - posLineStart;
+ if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) {
+ if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') {
+ if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") ||
+ sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") ||
+ sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") ||
+ sc.chNext == '$') {
+ sc.SetState(SCE_F_PREPROCESSOR);
+ } else {
+ sc.SetState(SCE_F_COMMENT);
+ }
+
+ while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end
+ } else if (toLineStart > 72) {
+ sc.SetState(SCE_F_COMMENT);
+ while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end
+ } else if (toLineStart < 5) {
+ if (IsADigit(sc.ch))
+ sc.SetState(SCE_F_LABEL);
+ else
+ sc.SetState(SCE_F_DEFAULT);
+ } else if (toLineStart == 5) {
+ if (!IsASpace(sc.ch) && sc.ch != '0') {
+ sc.SetState(SCE_F_CONTINUATION);
+ sc.ForwardSetState(prevState);
+ } else
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ continue;
+ }
+ /***************************************/
+ // Handle line continuation generically.
+ if (!isFixFormat && sc.ch == '&') {
+ char chTemp = ' ';
+ int j = 1;
+ while (IsABlank(chTemp) && j<132) {
+ chTemp = static_cast<char>(sc.GetRelative(j));
+ j++;
+ }
+ if (chTemp == '!') {
+ sc.SetState(SCE_F_CONTINUATION);
+ if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT);
+ } else if (chTemp == '\r' || chTemp == '\n') {
+ int currentState = sc.state;
+ sc.SetState(SCE_F_CONTINUATION);
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ while (IsASpace(sc.ch) && sc.More()) sc.Forward();
+ if (sc.ch == '&') {
+ sc.SetState(SCE_F_CONTINUATION);
+ sc.Forward();
+ }
+ sc.SetState(currentState);
+ }
+ }
+ /***************************************/
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_F_OPERATOR) {
+ sc.SetState(SCE_F_DEFAULT);
+ } else if (sc.state == SCE_F_NUMBER) {
+ if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) {
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ } else if (sc.state == SCE_F_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) || (sc.ch == '%')) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_F_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_F_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_F_WORD3);
+ }
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ } else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) {
+ if (sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ } else if (sc.state == SCE_F_STRING1) {
+ prevState = sc.state;
+ if (sc.ch == '\'') {
+ if (sc.chNext == '\'') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ prevState = SCE_F_DEFAULT;
+ }
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_F_STRINGEOL);
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ }
+ } else if (sc.state == SCE_F_STRING2) {
+ prevState = sc.state;
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_F_STRINGEOL);
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ } else if (sc.ch == '\"') {
+ if (sc.chNext == '\"') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ prevState = SCE_F_DEFAULT;
+ }
+ }
+ } else if (sc.state == SCE_F_OPERATOR2) {
+ if (sc.ch == '.') {
+ sc.ForwardSetState(SCE_F_DEFAULT);
+ }
+ } else if (sc.state == SCE_F_CONTINUATION) {
+ sc.SetState(SCE_F_DEFAULT);
+ } else if (sc.state == SCE_F_LABEL) {
+ if (!IsADigit(sc.ch)) {
+ sc.SetState(SCE_F_DEFAULT);
+ } else {
+ if (isFixFormat && sc.currentPos-posLineStart > 4)
+ sc.SetState(SCE_F_DEFAULT);
+ else if (numNonBlank > 5)
+ sc.SetState(SCE_F_DEFAULT);
+ }
+ }
+ /***************************************/
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_F_DEFAULT) {
+ if (sc.ch == '!') {
+ if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") ||
+ sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') {
+ sc.SetState(SCE_F_PREPROCESSOR);
+ } else {
+ sc.SetState(SCE_F_COMMENT);
+ }
+ } else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) {
+ sc.SetState(SCE_F_LABEL);
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_F_NUMBER);
+ } else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' ||
+ tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) {
+ sc.SetState(SCE_F_NUMBER);
+ sc.Forward();
+ } else if (sc.ch == '.' && isalpha(sc.chNext)) {
+ sc.SetState(SCE_F_OPERATOR2);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_F_IDENTIFIER);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_F_STRING2);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_F_STRING1);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_F_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+/***************************************/
+// To determine the folding level depending on keywords
+static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) {
+ int lev = 0;
+ if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0)
+ return -1;
+ if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0
+ || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0
+ || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0
+ || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0
+ || strcmp(s, "module") == 0 || strcmp(s, "program") == 0
+ || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0
+ || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){
+ if (strcmp(prevWord, "end") == 0)
+ lev = 0;
+ else
+ lev = 1;
+ } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=')
+ || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0
+ || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0
+ || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0
+ || strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0
+ || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0
+ || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0
+ || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0
+ || strcmp(s, "endwhere") == 0
+ || strcmp(s, "procedure") == 0 ) { // Take care of the module procedure statement
+ lev = -1;
+ } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if
+ lev = 0;
+ }
+ return lev;
+}
+// Folding the code
+static void FoldFortranDoc(unsigned int startPos, int length, int initStyle,
+ Accessor &styler, bool isFixFormat) {
+ //
+ // bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ // Do not know how to fold the comment at the moment.
+ //
+ 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];
+ char chNextNonBlank;
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ /***************************************/
+ int lastStart = 0;
+ char prevWord[32] = "";
+ char Label[6] = "";
+ // Variables for do label folding.
+ static int doLabels[100];
+ static int posLabel=-1;
+ /***************************************/
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ chNextNonBlank = chNext;
+ unsigned int j=i+1;
+ while(IsABlank(chNextNonBlank) && j<endPos) {
+ j ++ ;
+ chNextNonBlank = styler.SafeGetCharAt(j);
+ }
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ //
+ if (stylePrev == SCE_F_DEFAULT && (style == SCE_F_WORD || style == SCE_F_LABEL)) {
+ // Store last word and label start point.
+ lastStart = i;
+ }
+ /***************************************/
+ if (style == SCE_F_WORD) {
+ if(iswordchar(ch) && !iswordchar(chNext)) {
+ char s[32];
+ unsigned int k;
+ for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) {
+ s[k] = static_cast<char>(tolower(styler[lastStart+k]));
+ }
+ s[k] = '\0';
+ // Handle the forall and where statement and structure.
+ if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) {
+ if (strcmp(prevWord, "end") != 0) {
+ j = i + 1;
+ char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j);
+ // Find the position of the first (
+ while (ch1 != chBrace && j<endPos) {
+ j++;
+ ch1 = styler.SafeGetCharAt(j);
+ }
+ char styBrace = styler.StyleAt(j);
+ int depth = 1;
+ char chAtPos;
+ char styAtPos;
+ while (j<endPos) {
+ j++;
+ chAtPos = styler.SafeGetCharAt(j);
+ styAtPos = styler.StyleAt(j);
+ if (styAtPos == styBrace) {
+ if (chAtPos == chBrace) depth++;
+ if (chAtPos == chSeek) depth--;
+ if (depth == 0) break;
+ }
+ }
+ while (j<endPos) {
+ j++;
+ chAtPos = styler.SafeGetCharAt(j);
+ styAtPos = styler.StyleAt(j);
+ if (styAtPos == SCE_F_COMMENT || IsABlank(chAtPos)) continue;
+ if (isFixFormat) {
+ if (!IsALineEnd(chAtPos)) {
+ break;
+ } else {
+ if (lineCurrent < styler.GetLine(styler.Length()-1)) {
+ j = styler.LineStart(lineCurrent+1);
+ if (styler.StyleAt(j+5) == SCE_F_CONTINUATION) {
+ j += 5;
+ continue;
+ } else {
+ levelCurrent++;
+ break;
+ }
+ }
+ }
+ } else {
+ if (chAtPos == '&' && styler.StyleAt(j) == SCE_F_CONTINUATION) {
+ j = GetContinuedPos(j+1, styler);
+ continue;
+ } else if (IsALineEnd(chAtPos)) {
+ levelCurrent ++;
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ levelCurrent += classifyFoldPointFortran(s, prevWord, chNextNonBlank);
+ // Store the do Labels into array
+ if (strcmp(s, "do") == 0 && IsADigit(chNextNonBlank)) {
+ unsigned int k = 0;
+ for (i=j; (i<j+5 && i<endPos); i++) {
+ ch = styler.SafeGetCharAt(i);
+ if (IsADigit(ch))
+ Label[k++] = ch;
+ else
+ break;
+ }
+ Label[k] = '\0';
+ posLabel ++;
+ doLabels[posLabel] = atoi(Label);
+ }
+ }
+ strcpy(prevWord, s);
+ }
+ } else if (style == SCE_F_LABEL) {
+ if(IsADigit(ch) && !IsADigit(chNext)) {
+ for(j = 0; ( j < 5 ) && ( j < i-lastStart+1 ); j++) {
+ ch = styler.SafeGetCharAt(lastStart + j);
+ if (IsADigit(ch) && styler.StyleAt(lastStart+j) == SCE_F_LABEL)
+ Label[j] = ch;
+ else
+ break;
+ }
+ Label[j] = '\0';
+ while (doLabels[posLabel] == atoi(Label) && posLabel > -1) {
+ levelCurrent--;
+ posLabel--;
+ }
+ }
+ }
+ 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;
+ strcpy(prevWord, "");
+ }
+ /***************************************/
+ 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 FortranWordLists[] = {
+ "Primary keywords and identifiers",
+ "Intrinsic functions",
+ "Extended and user defined functions",
+ 0,
+};
+/***************************************/
+static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false);
+}
+/***************************************/
+static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+/***************************************/
+static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler) {
+ FoldFortranDoc(startPos, length, initStyle,styler, false);
+}
+/***************************************/
+static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler) {
+ FoldFortranDoc(startPos, length, initStyle,styler, true);
+}
+/***************************************/
+LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists);
+LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists);
diff --git a/scintilla/src/LexGAP.cxx b/scintilla/src/LexGAP.cxx
new file mode 100644
index 0000000..a477909
--- /dev/null
+++ b/scintilla/src/LexGAP.cxx
@@ -0,0 +1,263 @@
+// Scintilla source code edit control
+/** @file LexGAP.cxx
+ ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
+ ** http://www.gap-system.org
+ **/
+// Copyright 2007 by Istvan Szollosi ( szteven <at> gmail <dot> 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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsGAPOperator(char ch) {
+ if (isascii(ch) && isalnum(ch)) return false;
+ if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
+ ch == '^' || ch == ',' || ch == '!' || ch == '.' ||
+ ch == '=' || ch == '<' || ch == '>' || ch == '(' ||
+ ch == ')' || ch == ';' || ch == '[' || ch == ']' ||
+ ch == '{' || ch == '}' || ch == ':' )
+ return true;
+ return false;
+}
+
+static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(styler[start + i]);
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords1 = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ // Prevent SCE_GAP_STRINGEOL from leaking back to previous line
+ if ( sc.atLineStart ) {
+ if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING);
+ if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR);
+ }
+
+ // 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
+ switch (sc.state) {
+ case SCE_GAP_OPERATOR :
+ sc.SetState(SCE_GAP_DEFAULT);
+ break;
+
+ case SCE_GAP_NUMBER :
+ if (!IsADigit(sc.ch)) {
+ if (sc.ch == '\\') {
+ if (!sc.atLineEnd) {
+ if (!IsADigit(sc.chNext)) {
+ sc.Forward();
+ sc.ChangeState(SCE_GAP_IDENTIFIER);
+ }
+ }
+ } else if (isalpha(sc.ch) || sc.ch == '_') {
+ sc.ChangeState(SCE_GAP_IDENTIFIER);
+ }
+ else sc.SetState(SCE_GAP_DEFAULT);
+ }
+ break;
+
+ case SCE_GAP_IDENTIFIER :
+ if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
+ if (sc.ch == '\\') sc.Forward();
+ else {
+ char s[1000];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords1.InList(s)) {
+ sc.ChangeState(SCE_GAP_KEYWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_GAP_KEYWORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_GAP_KEYWORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_GAP_KEYWORD4);
+ }
+ sc.SetState(SCE_GAP_DEFAULT);
+ }
+ }
+ break;
+
+ case SCE_GAP_COMMENT :
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_GAP_DEFAULT);
+ }
+ break;
+
+ case SCE_GAP_STRING:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_GAP_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_GAP_DEFAULT);
+ }
+ break;
+
+ case SCE_GAP_CHAR:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_GAP_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_GAP_DEFAULT);
+ }
+ break;
+
+ case SCE_GAP_STRINGEOL:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_GAP_DEFAULT);
+ }
+ break;
+ }
+
+ // Determine if a new state should be entered
+ if (sc.state == SCE_GAP_DEFAULT) {
+ if (IsGAPOperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_GAP_OPERATOR);
+ }
+ else if (IsADigit(sc.ch)) {
+ sc.SetState(SCE_GAP_NUMBER);
+ } else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') {
+ sc.SetState(SCE_GAP_IDENTIFIER);
+ if (sc.ch == '\\') sc.Forward();
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_GAP_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_GAP_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_GAP_CHAR);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+static int ClassifyFoldPointGAP(const char* s) {
+ int level = 0;
+ if (strcmp(s, "function") == 0 ||
+ strcmp(s, "do") == 0 ||
+ strcmp(s, "if") == 0 ||
+ strcmp(s, "repeat") == 0 ) {
+ level = 1;
+ } else if (strcmp(s, "end") == 0 ||
+ strcmp(s, "od") == 0 ||
+ strcmp(s, "fi") == 0 ||
+ strcmp(s, "until") == 0 ) {
+ level = -1;
+ }
+ return level;
+}
+
+static void FoldGAPDoc( unsigned int startPos, int length, int initStyle, WordList** , Accessor &styler) {
+ 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];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+
+ int lastStart = 0;
+
+ 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 (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) {
+ // Store last word start point.
+ lastStart = i;
+ }
+
+ if (stylePrev == SCE_GAP_KEYWORD) {
+ if(iswordchar(ch) && !iswordchar(chNext)) {
+ char s[100];
+ GetRange(lastStart, i, styler, s, sizeof(s));
+ levelCurrent += ClassifyFoldPointGAP(s);
+ }
+ }
+
+ if (atEOL) {
+ int lev = levelPrev;
+ 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++;
+ }
+
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static const char * const GAPWordListDesc[] = {
+ "Keywords 1",
+ "Keywords 2",
+ "Keywords 3 (unused)",
+ "Keywords 4 (unused)",
+ 0
+};
+
+LexerModule lmGAP(
+ SCLEX_GAP,
+ ColouriseGAPDoc,
+ "gap",
+ FoldGAPDoc,
+ GAPWordListDesc);
diff --git a/scintilla/src/LexGen.py b/scintilla/src/LexGen.py
new file mode 100644
index 0000000..7c60752
--- /dev/null
+++ b/scintilla/src/LexGen.py
@@ -0,0 +1,287 @@
+# LexGen.py - implemented 2002 by Neil Hodgson neilh@scintilla.org
+# Released to the public domain.
+
+# Regenerate the Scintilla and SciTE source files that list
+# all the lexers and all the properties files.
+# Should be run whenever a new lexer is added or removed.
+# Requires Python 2.4 or later
+# Most files are regenerated in place with templates stored in comments.
+# The VS .NET project file is generated into a different file as the
+# VS .NET environment will not retain comments when modifying the file.
+# The files are copied to a string apart from sections between a
+# ++Autogenerated comment and a --Autogenerated comment which is
+# generated by the CopyWithInsertion function. After the whole
+# string is instantiated, it is compared with the target file and
+# if different the file is rewritten.
+# Does not regenerate the Visual C++ 6 project files but does the VS .NET
+# project file.
+
+import string
+import sys
+import os
+import glob
+
+# EOL constants
+CR = "\r"
+LF = "\n"
+CRLF = "\r\n"
+if sys.platform == "win32":
+ NATIVE = CRLF
+else:
+ # Yes, LF is the native EOL even on Mac OS X. CR is just for
+ # Mac OS <=9 (a.k.a. "Mac Classic")
+ NATIVE = LF
+
+# Automatically generated sections contain start and end comments,
+# a definition line and the results.
+# The results are replaced by regenerating based on the definition line.
+# The definition line is a comment prefix followed by "**".
+# If there is a digit after the ** then this indicates which list to use
+# and the digit and next character are not part of the definition
+# Backslash is used as an escape within the definition line.
+# The part between \( and \) is repeated for each item in the list.
+# \* is replaced by each list item. \t, and \n are tab and newline.
+def CopyWithInsertion(input, commentPrefix, retainDefs, eolType, *lists):
+ copying = 1
+ listid = 0
+ output = []
+ for line in input.splitlines(0):
+ isStartGenerated = line.startswith(commentPrefix + "++Autogenerated")
+ if copying and not isStartGenerated:
+ output.append(line)
+ if isStartGenerated:
+ if retainDefs:
+ output.append(line)
+ copying = 0
+ definition = ""
+ elif not copying and line.startswith(commentPrefix + "**"):
+ if retainDefs:
+ output.append(line)
+ definition = line[len(commentPrefix + "**"):]
+ if (commentPrefix == "<!--") and (" -->" in definition):
+ definition = definition.replace(" -->", "")
+ listid = 0
+ if definition[0] in string.digits:
+ listid = int(definition[:1])
+ definition = definition[2:]
+ # Hide double slashes as a control character
+ definition = definition.replace("\\\\", "\001")
+ # Do some normal C style transforms
+ definition = definition.replace("\\n", "\n")
+ definition = definition.replace("\\t", "\t")
+ # Get the doubled backslashes back as single backslashes
+ definition = definition.replace("\001", "\\")
+ startRepeat = definition.find("\\(")
+ endRepeat = definition.find("\\)")
+ intro = definition[:startRepeat]
+ out = ""
+ if intro.endswith("\n"):
+ pos = 0
+ else:
+ pos = len(intro)
+ out += intro
+ middle = definition[startRepeat+2:endRepeat]
+ for i in lists[listid]:
+ item = middle.replace("\\*", i)
+ if pos and (pos + len(item) >= 80):
+ out += "\\\n"
+ pos = 0
+ out += item
+ pos += len(item)
+ if item.endswith("\n"):
+ pos = 0
+ outro = definition[endRepeat+2:]
+ out += outro
+ out = out.replace("\n", eolType) # correct EOLs in generated content
+ output.append(out)
+ elif line.startswith(commentPrefix + "--Autogenerated"):
+ copying = 1
+ if retainDefs:
+ output.append(line)
+ output = [line.rstrip(" \t") for line in output] # trim trailing whitespace
+ return eolType.join(output) + eolType
+
+def UpdateFile(filename, updated):
+ """ If the file is different to updated then copy updated
+ into the file else leave alone so CVS and make don't treat
+ it as modified. """
+ try:
+ infile = open(filename, "rb")
+ except IOError: # File is not there yet
+ out = open(filename, "wb")
+ out.write(updated.encode('utf-8'))
+ out.close()
+ print("New %s" % filename)
+ return
+ original = infile.read()
+ infile.close()
+ original = original.decode('utf-8')
+ if updated != original:
+ os.unlink(filename)
+ out = open(filename, "wb")
+ out.write(updated.encode('utf-8'))
+ out.close()
+ print("Changed %s " % filename)
+ #~ else:
+ #~ print "Unchanged", filename
+
+def Generate(inpath, outpath, commentPrefix, eolType, *lists):
+ """Generate 'outpath' from 'inpath'.
+
+ "eolType" indicates the type of EOLs to use in the generated
+ file. It should be one of following constants: LF, CRLF,
+ CR, or NATIVE.
+ """
+ #print "generate '%s' -> '%s' (comment prefix: %r, eols: %r)"\
+ # % (inpath, outpath, commentPrefix, eolType)
+ try:
+ infile = open(inpath, "rb")
+ except IOError:
+ print("Can not open %s" % inpath)
+ return
+ original = infile.read()
+ infile.close()
+ original = original.decode('utf-8')
+ updated = CopyWithInsertion(original, commentPrefix,
+ inpath == outpath, eolType, *lists)
+ UpdateFile(outpath, updated)
+
+def Regenerate(filename, commentPrefix, eolType, *lists):
+ """Regenerate the given file.
+
+ "eolType" indicates the type of EOLs to use in the generated
+ file. It should be one of following constants: LF, CRLF,
+ CR, or NATIVE.
+ """
+ Generate(filename, filename, commentPrefix, eolType, *lists)
+
+def FindModules(lexFile):
+ modules = []
+ f = open(lexFile)
+ for l in f.readlines():
+ if l.startswith("LexerModule"):
+ l = l.replace("(", " ")
+ modules.append(l.split()[1])
+ return modules
+
+knownIrregularProperties = [
+ "fold",
+ "styling.within.preprocessor",
+ "tab.timmy.whinge.level",
+ "asp.default.language",
+ "html.tags.case.sensitive",
+ "ps.level",
+ "ps.tokenize",
+ "sql.backslash.escapes",
+ "nsis.uservars",
+ "nsis.ignorecase"
+]
+
+def FindProperties(lexFile):
+ properties = {}
+ f = open(lexFile)
+ for l in f.readlines():
+ if "GetProperty" in l and '"' in l:
+ l = l.strip()
+ if not l.startswith("//"): # Drop comments
+ propertyName = l.split("\"")[1]
+ if propertyName.lower() == propertyName:
+ # Only allow lower case property names
+ if propertyName in knownIrregularProperties or \
+ propertyName.startswith("fold.") or \
+ propertyName.startswith("lexer."):
+ properties[propertyName] = 1
+ return properties
+
+def FindPropertyDocumentation(lexFile):
+ documents = {}
+ f = open(lexFile)
+ name = ""
+ for l in f.readlines():
+ l = l.strip()
+ if "// property " in l:
+ propertyName = l.split()[2]
+ if propertyName.lower() == propertyName:
+ # Only allow lower case property names
+ name = propertyName
+ documents[name] = ""
+ elif name:
+ if l.startswith("//"):
+ if documents[name]:
+ documents[name] += " "
+ documents[name] += l[2:].strip()
+ else:
+ name = ""
+ return documents
+
+def ciCompare(a,b):
+ return cmp(a.lower(), b.lower())
+
+def ciKey(a):
+ return a.lower()
+
+def sortListInsensitive(l):
+ try: # Try key function
+ l.sort(key=ciKey)
+ except TypeError: # Earlier version of Python, so use comparison function
+ l.sort(ciCompare)
+
+def RegenerateAll():
+ root="../../"
+
+ # Find all the lexer source code files
+ lexFilePaths = glob.glob(root + "scintilla/src/Lex*.cxx")
+ sortListInsensitive(lexFilePaths)
+ lexFiles = [os.path.basename(f)[:-4] for f in lexFilePaths]
+ print(lexFiles)
+ lexerModules = []
+ lexerProperties = {}
+ propertyDocuments = {}
+ for lexFile in lexFilePaths:
+ lexerModules.extend(FindModules(lexFile))
+ for k in FindProperties(lexFile).keys():
+ lexerProperties[k] = 1
+ documents = FindPropertyDocumentation(lexFile)
+ for k in documents.keys():
+ propertyDocuments[k] = documents[k]
+ sortListInsensitive(lexerModules)
+ del lexerProperties["fold.comment.python"]
+ lexerProperties = list(lexerProperties.keys())
+ sortListInsensitive(lexerProperties)
+
+ # Generate HTML to document each property
+ # This is done because tags can not be safely put inside comments in HTML
+ documentProperties = list(propertyDocuments.keys())
+ sortListInsensitive(documentProperties)
+ propertiesHTML = []
+ for k in documentProperties:
+ propertiesHTML.append("\t<tr>\n\t<td>%s</td>\n\t<td>%s</td>\n\t</tr>" %
+ (k, propertyDocuments[k]))
+
+ # Find all the SciTE properties files
+ otherProps = ["abbrev.properties", "Embedded.properties", "SciTEGlobal.properties", "SciTE.properties"]
+ if os.path.exists(root + "scite"):
+ propFilePaths = glob.glob(root + "scite/src/*.properties")
+ sortListInsensitive(propFilePaths)
+ propFiles = [os.path.basename(f) for f in propFilePaths if os.path.basename(f) not in otherProps]
+ sortListInsensitive(propFiles)
+ print(propFiles)
+
+ Regenerate(root + "scintilla/src/KeyWords.cxx", "//", NATIVE, lexerModules)
+ Regenerate(root + "scintilla/win32/makefile", "#", NATIVE, lexFiles)
+ Regenerate(root + "scintilla/win32/scintilla.mak", "#", NATIVE, lexFiles)
+ Regenerate(root + "scintilla/win32/scintilla_vc6.mak", "#", NATIVE, lexFiles)
+ # Use Unix EOLs for gtk Makefiles so they work for Linux users when
+ # extracted from the Scintilla source ZIP (typically created on
+ # Windows).
+ Regenerate(root + "scintilla/gtk/makefile", "#", LF, lexFiles)
+ Regenerate(root + "scintilla/macosx/makefile", "#", LF, lexFiles)
+ if os.path.exists(root + "scite"):
+ Regenerate(root + "scite/win32/makefile", "#", NATIVE, lexFiles, propFiles)
+ Regenerate(root + "scite/win32/scite.mak", "#", NATIVE, lexFiles, propFiles)
+ Regenerate(root + "scite/src/SciTEProps.cxx", "//", NATIVE, lexerProperties)
+ Regenerate(root + "scite/doc/SciTEDoc.html", "<!--", NATIVE, propertiesHTML)
+ Generate(root + "scite/boundscheck/vcproj.gen",
+ root + "scite/boundscheck/SciTE.vcproj", "#", NATIVE, lexFiles)
+
+RegenerateAll()
diff --git a/scintilla/src/LexGui4Cli.cxx b/scintilla/src/LexGui4Cli.cxx
new file mode 100644
index 0000000..a587aac
--- /dev/null
+++ b/scintilla/src/LexGui4Cli.cxx
@@ -0,0 +1,313 @@
+// Scintilla source code edit control
+// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+/*
+This is the Lexer for Gui4Cli, included in SciLexer.dll
+- by d. Keletsekis, 2/10/2003
+
+To add to SciLexer.dll:
+1. Add the values below to INCLUDE\Scintilla.iface
+2. Run the include/HFacer.py script
+3. Run the src/lexGen.py script
+
+val SCE_GC_DEFAULT=0
+val SCE_GC_COMMENTLINE=1
+val SCE_GC_COMMENTBLOCK=2
+val SCE_GC_GLOBAL=3
+val SCE_GC_EVENT=4
+val SCE_GC_ATTRIBUTE=5
+val SCE_GC_CONTROL=6
+val SCE_GC_COMMAND=7
+val SCE_GC_STRING=8
+val SCE_GC_OPERATOR=9
+*/
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define debug Platform::DebugPrintf
+
+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 == '.');
+}
+
+inline bool isGCOperator(int 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 == ':')
+ return true;
+ return false;
+}
+
+#define isSpace(x) ((x)==' ' || (x)=='\t')
+#define isNL(x) ((x)=='\n' || (x)=='\r')
+#define isSpaceOrNL(x) (isSpace(x) || isNL(x))
+#define BUFFSIZE 500
+#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
+
+static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
+ StyleContext *sc, char *buff, int length, int)
+{
+ int c = 0;
+ while (sc->More() && isSpaceOrNL(sc->ch))
+ { sc->Forward();
+ }
+ styler.ColourTo(sc->currentPos - 1, sc->state);
+
+ if (!IsAWordChar(sc->ch)) // comment, marker, etc..
+ return;
+
+ while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
+ { buff[c] = static_cast<char>(sc->ch);
+ ++c; sc->Forward();
+ }
+ buff[c] = '\0';
+ char *p = buff;
+ while (*p) // capitalize..
+ { if (islower(*p)) *p = static_cast<char>(toupper(*p));
+ ++p;
+ }
+
+ WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user
+ WordList &kEvent = *keywordlists[1];
+ WordList &kAttribute = *keywordlists[2];
+ WordList &kControl = *keywordlists[3];
+ WordList &kCommand = *keywordlists[4];
+
+ int state = 0;
+ // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
+ // debug ("line = %d, level = %d", line, level);
+
+ if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL;
+ else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE;
+ else if (kControl.InList(buff)) state = SCE_GC_CONTROL;
+ else if (kCommand.InList(buff)) state = SCE_GC_COMMAND;
+ else if (kEvent.InList(buff)) state = SCE_GC_EVENT;
+
+ if (state)
+ { sc->ChangeState(state);
+ styler.ColourTo(sc->currentPos - 1, sc->state);
+ sc->ChangeState(SCE_GC_DEFAULT);
+ }
+ else
+ { sc->ChangeState(SCE_GC_DEFAULT);
+ styler.ColourTo(sc->currentPos - 1, sc->state);
+ }
+}
+
+// Main colorizing function called by Scintilla
+static void
+ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler)
+{
+ styler.StartAt(startPos);
+
+ int quotestart = 0, oldstate, currentline = styler.GetLine(startPos);
+ styler.StartSegment(startPos);
+ bool noforward;
+ char buff[BUFFSIZE+1]; // buffer for command name
+
+ StyleContext sc(startPos, length, initStyle, styler);
+ buff[0] = '\0'; // cbuff = 0;
+
+ if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
+ colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
+
+ while (sc.More())
+ { noforward = 0;
+
+ switch (sc.ch)
+ {
+ case '/':
+ if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
+ break;
+ if (sc.chNext == '/') // line comment
+ { sc.SetState (SCE_GC_COMMENTLINE);
+ sc.Forward();
+ styler.ColourTo(sc.currentPos, sc.state);
+ }
+ else if (sc.chNext == '*') // block comment
+ { sc.SetState(SCE_GC_COMMENTBLOCK);
+ sc.Forward();
+ styler.ColourTo(sc.currentPos, sc.state);
+ }
+ else
+ styler.ColourTo(sc.currentPos, sc.state);
+ break;
+
+ case '*': // end of comment block, or operator..
+ if (sc.state == SCE_GC_STRING)
+ break;
+ if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
+ { sc.Forward();
+ styler.ColourTo(sc.currentPos, sc.state);
+ sc.ChangeState (SCE_GC_DEFAULT);
+ }
+ else
+ styler.ColourTo(sc.currentPos, sc.state);
+ break;
+
+ case '\'': case '\"': // strings..
+ if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
+ break;
+ if (sc.state == SCE_GC_STRING)
+ { if (sc.ch == quotestart) // match same quote char..
+ { styler.ColourTo(sc.currentPos, sc.state);
+ sc.ChangeState(SCE_GC_DEFAULT);
+ quotestart = 0;
+ } }
+ else
+ { styler.ColourTo(sc.currentPos - 1, sc.state);
+ sc.ChangeState(SCE_GC_STRING);
+ quotestart = sc.ch;
+ }
+ break;
+
+ case ';': // end of commandline character
+ if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
+ sc.state != SCE_GC_STRING)
+ {
+ styler.ColourTo(sc.currentPos - 1, sc.state);
+ styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
+ sc.ChangeState(SCE_GC_DEFAULT);
+ sc.Forward();
+ colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
+ noforward = 1; // don't move forward - already positioned at next char..
+ }
+ break;
+
+ case '+': case '-': case '=': case '!': // operators..
+ case '<': case '>': case '&': case '|': case '$':
+ if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
+ sc.state != SCE_GC_STRING)
+ {
+ styler.ColourTo(sc.currentPos - 1, sc.state);
+ styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
+ sc.ChangeState(SCE_GC_DEFAULT);
+ }
+ break;
+
+ case '\\': // escape - same as operator, but also mark in strings..
+ if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
+ {
+ oldstate = sc.state;
+ styler.ColourTo(sc.currentPos - 1, sc.state);
+ sc.Forward(); // mark also the next char..
+ styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
+ sc.ChangeState(oldstate);
+ }
+ break;
+
+ case '\n': case '\r':
+ ++currentline;
+ if (sc.state == SCE_GC_COMMENTLINE)
+ { styler.ColourTo(sc.currentPos, sc.state);
+ sc.ChangeState (SCE_GC_DEFAULT);
+ }
+ else if (sc.state != SCE_GC_COMMENTBLOCK)
+ { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
+ noforward = 1; // don't move forward - already positioned at next char..
+ }
+ break;
+
+// case ' ': case '\t':
+// default :
+ }
+
+ if (!noforward) sc.Forward();
+
+ }
+ sc.Complete();
+}
+
+// Main folding function called by Scintilla - (based on props (.ini) files function)
+static void FoldGui4Cli(unsigned int startPos, int length, int,
+ WordList *[], Accessor &styler)
+{
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ bool headerPoint = false;
+
+ for (unsigned int i = startPos; i < endPos; i++)
+ {
+ char ch = chNext;
+ chNext = styler[i+1];
+
+ int style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
+ { headerPoint = true; // fold at events and globals
+ }
+
+ if (atEOL)
+ { int lev = SC_FOLDLEVELBASE+1;
+
+ if (headerPoint)
+ lev = SC_FOLDLEVELBASE;
+
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+
+ if (headerPoint)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+
+ if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
+ { styler.SetLevel(lineCurrent, lev);
+ }
+
+ lineCurrent++; // re-initialize our flags
+ visibleChars = 0;
+ headerPoint = false;
+ }
+
+ if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
+ visibleChars++;
+ }
+
+ int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, lev | flagsNext);
+}
+
+// I have no idea what these are for.. probably accessible by some message.
+static const char * const gui4cliWordListDesc[] = {
+ "Globals", "Events", "Attributes", "Control", "Commands",
+ 0
+};
+
+// Declare language & pass our function pointers to Scintilla
+LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
+
+#undef debug
+
diff --git a/scintilla/src/LexHTML.cxx b/scintilla/src/LexHTML.cxx
new file mode 100644
index 0000000..3019552
--- /dev/null
+++ b/scintilla/src/LexHTML.cxx
@@ -0,0 +1,2131 @@
+// Scintilla source code edit control
+/** @file LexHTML.cxx
+ ** Lexer for HTML.
+ **/
+// 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 <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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
+#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
+#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
+
+enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment };
+enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc };
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+inline bool IsOperator(int ch) {
+ if (isascii(ch) && 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 == '>' || ch == ',' || ch == '/' ||
+ ch == '?' || ch == '!' || ch == '.' || ch == '~')
+ return true;
+ return false;
+}
+
+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 const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) {
+
+ size_t i = 0;
+ for (; i < sLen-1; i++) {
+ char ch = static_cast<char>(styler.SafeGetCharAt(start + i));
+ if ((i == 0) && !IsAWordStart(ch))
+ break;
+ if ((i > 0) && !IsAWordChar(ch))
+ break;
+ s[i] = ch;
+ }
+ s[i] = '\0';
+
+ return s;
+}
+
+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;
+ if (strstr(s, "vbs"))
+ return eScriptVBS;
+ if (strstr(s, "pyth"))
+ return eScriptPython;
+ if (strstr(s, "javas"))
+ return eScriptJS;
+ if (strstr(s, "jscr"))
+ return eScriptJS;
+ if (strstr(s, "php"))
+ return eScriptPHP;
+ if (strstr(s, "xml")) {
+ const char *xml = strstr(s, "xml");
+ for (const char *t=s; t<xml; t++) {
+ if (!IsASpace(*t)) {
+ return prevValue;
+ }
+ }
+ return eScriptXML;
+ }
+
+ return prevValue;
+}
+
+static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
+ int iResult = 0;
+ char s[100];
+ GetTextSegment(styler, start, end, s, sizeof(s));
+ if (0 == strncmp(s, "php", 3)) {
+ iResult = 3;
+ }
+
+ return iResult;
+}
+
+static script_type ScriptOfState(int state) {
+ if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
+ return eScriptPython;
+ } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
+ return eScriptVBS;
+ } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
+ return eScriptJS;
+ } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) {
+ return eScriptPHP;
+ } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) {
+ return eScriptSGML;
+ } else if (state == SCE_H_SGML_BLOCK_DEFAULT) {
+ return eScriptSGMLblock;
+ } else {
+ return eScriptNone;
+ }
+}
+
+static int statePrintForState(int state, script_mode inScriptType) {
+ int StateToPrint = state;
+
+ if (state >= SCE_HJ_START) {
+ if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
+ StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON);
+ } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
+ StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS);
+ } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
+ StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS);
+ }
+ }
+
+ return StateToPrint;
+}
+
+static int stateForPrintState(int StateToPrint) {
+ int state;
+
+ if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) {
+ state = StateToPrint - SCE_HA_PYTHON;
+ } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) {
+ state = StateToPrint - SCE_HA_VBS;
+ } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) {
+ state = StateToPrint - SCE_HA_JS;
+ } else {
+ state = StateToPrint;
+ }
+
+ return state;
+}
+
+static inline bool IsNumber(unsigned int start, Accessor &styler) {
+ return IsADigit(styler[start]) || (styler[start] == '.') ||
+ (styler[start] == '-') || (styler[start] == '#');
+}
+
+static inline bool isStringState(int state) {
+ bool bResult;
+
+ switch (state) {
+ case SCE_HJ_DOUBLESTRING:
+ case SCE_HJ_SINGLESTRING:
+ case SCE_HJA_DOUBLESTRING:
+ case SCE_HJA_SINGLESTRING:
+ case SCE_HB_STRING:
+ case SCE_HBA_STRING:
+ case SCE_HP_STRING:
+ case SCE_HP_CHARACTER:
+ case SCE_HP_TRIPLE:
+ case SCE_HP_TRIPLEDOUBLE:
+ case SCE_HPA_STRING:
+ case SCE_HPA_CHARACTER:
+ case SCE_HPA_TRIPLE:
+ case SCE_HPA_TRIPLEDOUBLE:
+ case SCE_HPHP_HSTRING:
+ case SCE_HPHP_SIMPLESTRING:
+ case SCE_HPHP_HSTRING_VARIABLE:
+ case SCE_HPHP_COMPLEX_VARIABLE:
+ bResult = true;
+ break;
+ default :
+ bResult = false;
+ break;
+ }
+ return bResult;
+}
+
+static inline bool stateAllowsTermination(int state) {
+ bool allowTermination = !isStringState(state);
+ if (allowTermination) {
+ switch (state) {
+ case SCE_HB_COMMENTLINE:
+ case SCE_HPHP_COMMENT:
+ case SCE_HP_COMMENTLINE:
+ case SCE_HPA_COMMENTLINE:
+ allowTermination = false;
+ }
+ }
+ return allowTermination;
+}
+
+// not really well done, since it's only comments that should lex the %> and <%
+static inline bool isCommentASPState(int state) {
+ bool bResult;
+
+ switch (state) {
+ case SCE_HJ_COMMENT:
+ case SCE_HJ_COMMENTLINE:
+ case SCE_HJ_COMMENTDOC:
+ case SCE_HB_COMMENTLINE:
+ case SCE_HP_COMMENTLINE:
+ case SCE_HPHP_COMMENT:
+ case SCE_HPHP_COMMENTLINE:
+ bResult = true;
+ break;
+ default :
+ bResult = false;
+ break;
+ }
+ return bResult;
+}
+
+static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+ bool wordIsNumber = IsNumber(start, styler);
+ char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
+ if (wordIsNumber) {
+ chAttr = SCE_H_NUMBER;
+ } else {
+ char s[100];
+ GetTextSegment(styler, start, end, s, sizeof(s));
+ if (keywords.InList(s))
+ chAttr = SCE_H_ATTRIBUTE;
+ }
+ if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords)
+ // No keywords -> all are known
+ chAttr = SCE_H_ATTRIBUTE;
+ styler.ColourTo(end, chAttr);
+}
+
+static int classifyTagHTML(unsigned int start, unsigned int end,
+ WordList &keywords, Accessor &styler, bool &tagDontFold,
+ bool caseSensitive, bool isXml, bool allowScripts) {
+ char s[30 + 2];
+ // Copy after the '<'
+ unsigned int i = 0;
+ for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
+ char ch = styler[cPos];
+ if ((ch != '<') && (ch != '/')) {
+ s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
+ }
+ }
+
+ //The following is only a quick hack, to see if this whole thing would work
+ //we first need the tagname with a trailing space...
+ s[i] = ' ';
+ s[i+1] = '\0';
+
+ // if the current language is XML, I can fold any tag
+ // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.)
+ //...to find it in the list of no-container-tags
+ tagDontFold = (!isXml) && (NULL != strstr("meta link img area br hr input ", s));
+
+ //now we can remove the trailing space
+ s[i] = '\0';
+
+ // No keywords -> all are known
+ char chAttr = SCE_H_TAGUNKNOWN;
+ if (s[0] == '!') {
+ chAttr = SCE_H_SGML_DEFAULT;
+ } else if (!keywords || keywords.InList(s)) {
+ chAttr = SCE_H_TAG;
+ }
+ styler.ColourTo(end, chAttr);
+ if (chAttr == SCE_H_TAG) {
+ if (allowScripts && 0 == strcmp(s, "script")) {
+ // check to see if this is a self-closing tag by sniffing ahead
+ bool isSelfClose = false;
+ for (unsigned int cPos = end; cPos <= end + 100; cPos++) {
+ char ch = styler.SafeGetCharAt(cPos, '\0');
+ if (ch == '\0' || ch == '>')
+ break;
+ else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') {
+ isSelfClose = true;
+ break;
+ }
+ }
+
+ // do not enter a script state if the tag self-closed
+ if (!isSelfClose)
+ chAttr = SCE_H_SCRIPT;
+ } else if (!isXml && 0 == strcmp(s, "comment")) {
+ chAttr = SCE_H_COMMENT;
+ }
+ }
+ return chAttr;
+}
+
+static void classifyWordHTJS(unsigned int start, unsigned int end,
+ WordList &keywords, Accessor &styler, script_mode inScriptType) {
+ char chAttr = SCE_HJ_WORD;
+ bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
+ if (wordIsNumber)
+ chAttr = SCE_HJ_NUMBER;
+ else {
+ char s[30 + 1];
+ unsigned int i = 0;
+ for (; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ }
+ s[i] = '\0';
+ if (keywords.InList(s))
+ chAttr = SCE_HJ_KEYWORD;
+ }
+ styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
+}
+
+static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) {
+ char chAttr = SCE_HB_IDENTIFIER;
+ bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
+ if (wordIsNumber)
+ chAttr = SCE_HB_NUMBER;
+ else {
+ char s[100];
+ GetTextSegment(styler, start, end, s, sizeof(s));
+ if (keywords.InList(s)) {
+ chAttr = SCE_HB_WORD;
+ if (strcmp(s, "rem") == 0)
+ chAttr = SCE_HB_COMMENTLINE;
+ }
+ }
+ styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
+ if (chAttr == SCE_HB_COMMENTLINE)
+ return SCE_HB_COMMENTLINE;
+ else
+ return SCE_HB_DEFAULT;
+}
+
+static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) {
+ bool wordIsNumber = IsADigit(styler[start]);
+ char s[30 + 1];
+ unsigned int i = 0;
+ for (; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ }
+ s[i] = '\0';
+ char chAttr = SCE_HP_IDENTIFIER;
+ if (0 == strcmp(prevWord, "class"))
+ chAttr = SCE_HP_CLASSNAME;
+ else if (0 == strcmp(prevWord, "def"))
+ chAttr = SCE_HP_DEFNAME;
+ else if (wordIsNumber)
+ chAttr = SCE_HP_NUMBER;
+ else if (keywords.InList(s))
+ chAttr = SCE_HP_WORD;
+ styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
+ strcpy(prevWord, s);
+}
+
+// Update the word colour to default or keyword
+// Called when in a PHP word
+static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+ char chAttr = SCE_HPHP_DEFAULT;
+ bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1]));
+ if (wordIsNumber)
+ chAttr = SCE_HPHP_NUMBER;
+ else {
+ char s[100];
+ GetTextSegment(styler, start, end, s, sizeof(s));
+ if (keywords.InList(s))
+ chAttr = SCE_HPHP_WORD;
+ }
+ styler.ColourTo(end, chAttr);
+}
+
+static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+ char s[30 + 1];
+ unsigned int i = 0;
+ for (; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ }
+ s[i] = '\0';
+ return keywords.InList(s);
+}
+
+static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) {
+ char s[30 + 1];
+ unsigned int i = 0;
+ for (; i < end - start + 1 && i < 30; i++) {
+ s[i] = styler[start + i];
+ }
+ s[i] = '\0';
+ return (0 == strcmp(s, "[CDATA["));
+}
+
+// Return the first state to reach when entering a scripting language
+static int StateForScript(script_type scriptLanguage) {
+ int Result;
+ switch (scriptLanguage) {
+ case eScriptVBS:
+ Result = SCE_HB_START;
+ break;
+ case eScriptPython:
+ Result = SCE_HP_START;
+ break;
+ case eScriptPHP:
+ Result = SCE_HPHP_DEFAULT;
+ break;
+ case eScriptXML:
+ Result = SCE_H_TAGUNKNOWN;
+ break;
+ case eScriptSGML:
+ Result = SCE_H_SGML_DEFAULT;
+ break;
+ case eScriptComment:
+ Result = SCE_H_COMMENT;
+ break;
+ default :
+ Result = SCE_HJ_START;
+ break;
+ }
+ return Result;
+}
+
+static inline bool ishtmlwordchar(int ch) {
+ return !isascii(ch) ||
+ (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#');
+}
+
+static inline bool issgmlwordchar(int ch) {
+ return !isascii(ch) ||
+ (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
+}
+
+static inline bool IsPhpWordStart(int ch) {
+ return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f);
+}
+
+static inline bool IsPhpWordChar(int ch) {
+ return IsADigit(ch) || IsPhpWordStart(ch);
+}
+
+static bool InTagState(int state) {
+ return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
+ state == SCE_H_SCRIPT ||
+ state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
+ state == SCE_H_NUMBER || state == SCE_H_OTHER ||
+ state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
+}
+
+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(int ch) {
+ return ch == '\r' || ch == '\n';
+}
+
+static bool isOKBeforeRE(int ch) {
+ return (ch == '(') || (ch == '=') || (ch == ',');
+}
+
+static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) {
+ if (strlen(blockType) == 0) {
+ return ((ch == '%') && (chNext == '>'));
+ } else if ((0 == strcmp(blockType, "inherit")) ||
+ (0 == strcmp(blockType, "namespace")) ||
+ (0 == strcmp(blockType, "include")) ||
+ (0 == strcmp(blockType, "page"))) {
+ return ((ch == '/') && (chNext == '>'));
+ } else if (0 == strcmp(blockType, "%")) {
+ return isLineEnd(ch);
+ } else if (0 == strcmp(blockType, "{")) {
+ return ch == '}';
+ } else {
+ return (ch == '>');
+ }
+}
+
+static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) {
+ if (strlen(blockType) == 0) {
+ return 0;
+ } else if (0 == strcmp(blockType, "%")) {
+ return ((ch == '%') && (chNext == '}'));
+ } else if (0 == strcmp(blockType, "{")) {
+ return ((ch == '}') && (chNext == '}'));
+ } else {
+ return 0;
+ }
+}
+
+static bool isPHPStringState(int state) {
+ return
+ (state == SCE_HPHP_HSTRING) ||
+ (state == SCE_HPHP_SIMPLESTRING) ||
+ (state == SCE_HPHP_HSTRING_VARIABLE) ||
+ (state == SCE_HPHP_COMPLEX_VARIABLE);
+}
+
+static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) {
+ int j;
+ const int beginning = i - 1;
+ bool isValidSimpleString = false;
+
+ while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
+ i++;
+
+ char ch = styler.SafeGetCharAt(i);
+ const char chNext = styler.SafeGetCharAt(i + 1);
+ if (!IsPhpWordStart(ch)) {
+ if (ch == '\'' && IsPhpWordStart(chNext)) {
+ i++;
+ ch = chNext;
+ isSimpleString = true;
+ } else {
+ phpStringDelimiter[0] = '\0';
+ return beginning;
+ }
+ }
+ phpStringDelimiter[0] = ch;
+ i++;
+
+ for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) {
+ if (!IsPhpWordChar(styler[j])) {
+ if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) {
+ isValidSimpleString = true;
+ j++;
+ break;
+ } else {
+ phpStringDelimiter[0] = '\0';
+ return beginning;
+ }
+ }
+ if (j - i < phpStringDelimiterSize - 2)
+ phpStringDelimiter[j-i+1] = styler[j];
+ else
+ i++;
+ }
+ if (isSimpleString && !isValidSimpleString) {
+ phpStringDelimiter[0] = '\0';
+ return beginning;
+ }
+ phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0';
+ return j - 1;
+}
+
+static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler, bool isXml) {
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+ WordList &keywords5 = *keywordlists[4];
+ WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords
+
+ // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
+ styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
+ char prevWord[200];
+ prevWord[0] = '\0';
+ char phpStringDelimiter[200]; // PHP is not limited in length, we are
+ phpStringDelimiter[0] = '\0';
+ int StateToPrint = initStyle;
+ int state = stateForPrintState(StateToPrint);
+ char makoBlockType[200];
+ makoBlockType[0] = '\0';
+ char djangoBlockType[2];
+ djangoBlockType[0] = '\0';
+
+ // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
+ if (InTagState(state)) {
+ while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) {
+ startPos--;
+ length++;
+ }
+ state = SCE_H_DEFAULT;
+ }
+ // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState
+ if (isPHPStringState(state)) {
+ while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) {
+ startPos--;
+ length++;
+ state = styler.StyleAt(startPos);
+ }
+ if (startPos == 0)
+ state = SCE_H_DEFAULT;
+ }
+ styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
+
+ int lineCurrent = styler.GetLine(startPos);
+ int lineState;
+ if (lineCurrent > 0) {
+ lineState = styler.GetLineState(lineCurrent);
+ } else {
+ // Default client and ASP scripting language is JavaScript
+ lineState = eScriptJS << 8;
+
+ // property asp.default.language
+ // Script in ASP code is initially assumed to be in JavaScript.
+ // To change this to VBScript set asp.default.language to 2. Python is 3.
+ lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4;
+ }
+ script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode
+ bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag
+ bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag
+ bool tagDontFold = false; //some HTML tags should not be folded
+ script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name
+ script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name
+ int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state
+
+ script_type scriptLanguage = ScriptOfState(state);
+ // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment
+ if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) {
+ scriptLanguage = eScriptComment;
+ }
+ script_type beforeLanguage = ScriptOfState(beforePreProc);
+
+ // property fold.html
+ // Folding is turned on or off for HTML and XML files with this option.
+ // The fold option must also be on for folding to occur.
+ const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;
+
+ const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);
+
+ // property fold.html.preprocessor
+ // Folding is turned on or off for scripts embedded in HTML files with this option.
+ // The default is on.
+ const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);
+
+ const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+
+ // property fold.hypertext.comment
+ // Allow folding for comments in scripts embedded in HTML.
+ // The default is off.
+ const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0;
+
+ // property fold.hypertext.heredoc
+ // Allow folding for heredocs in scripts embedded in HTML.
+ // The default is off.
+ const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;
+
+ // property html.tags.case.sensitive
+ // For XML and HTML, setting this property to 1 will make tags match in a case
+ // sensitive way which is the expected behaviour for XML and XHTML.
+ const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
+
+ // property lexer.xml.allow.scripts
+ // Set to 0 to disable scripts in XML.
+ const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;
+
+ // property lexer.html.mako
+ // Set to 1 to enable the mako template language.
+ const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0;
+
+ // property lexer.html.django
+ // Set to 1 to enable the django template language.
+ const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0;
+
+ const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
+ const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
+ const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
+
+ int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+ int visibleChars = 0;
+ int lineStartVisibleChars = 0;
+
+ int chPrev = ' ';
+ int ch = ' ';
+ int 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 = static_cast<unsigned char>(styler.SafeGetCharAt(back));
+ }
+ }
+
+ styler.StartSegment(startPos);
+ const int lengthDoc = startPos + length;
+ for (int i = startPos; i < lengthDoc; i++) {
+ const int chPrev2 = chPrev;
+ chPrev = ch;
+ if (!IsASpace(ch) && state != SCE_HJ_COMMENT &&
+ state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
+ chPrevNonWhite = ch;
+ ch = static_cast<unsigned char>(styler[i]);
+ int chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ const int chNext2 = static_cast<unsigned char>(styler.SafeGetCharAt(i + 2));
+
+ // Handle DBCS codepages
+ if (styler.IsLeadByte(static_cast<char>(ch))) {
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if ((!IsASpace(ch) || !foldCompact) && fold)
+ visibleChars++;
+ if (!IsASpace(ch))
+ lineStartVisibleChars++;
+
+ // decide what is the current state to print (depending of the script tag)
+ StateToPrint = statePrintForState(state, inScriptType);
+
+ // handle script folding
+ if (fold) {
+ switch (scriptLanguage) {
+ case eScriptJS:
+ case eScriptPHP:
+ //not currently supported case eScriptVBS:
+
+ if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) {
+ //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
+ //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
+ if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) {
+ levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1;
+ }
+ } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) {
+ levelCurrent--;
+ }
+ break;
+ case eScriptPython:
+ if (state != SCE_HP_COMMENTLINE) {
+ if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) {
+ levelCurrent++;
+ } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) {
+ // check if the number of tabs is lower than the level
+ int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8;
+ for (int j = 0; Findlevel > 0; j++) {
+ char chTmp = styler.SafeGetCharAt(i + j + 1);
+ if (chTmp == '\t') {
+ Findlevel -= 8;
+ } else if (chTmp == ' ') {
+ Findlevel--;
+ } else {
+ break;
+ }
+ }
+
+ if (Findlevel > 0) {
+ levelCurrent -= Findlevel / 8;
+ if (Findlevel % 8)
+ levelCurrent--;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
+ // Avoid triggering two times on Dos/Win
+ // New line -> record any line state onto /next/ line
+ if (fold) {
+ int lev = levelPrev;
+ if (visibleChars == 0)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((levelCurrent > levelPrev) && (visibleChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+
+ styler.SetLevel(lineCurrent, lev);
+ visibleChars = 0;
+ levelPrev = levelCurrent;
+ }
+ lineCurrent++;
+ lineStartVisibleChars = 0;
+ styler.SetLineState(lineCurrent,
+ ((inScriptType & 0x03) << 0) |
+ ((tagOpened & 0x01) << 2) |
+ ((tagClosing & 0x01) << 3) |
+ ((aspScript & 0x0F) << 4) |
+ ((clientScript & 0x0F) << 8) |
+ ((beforePreProc & 0xFF) << 12));
+ }
+
+ // Allow falling through to mako handling code if newline is going to end a block
+ if (((ch == '\r' && chNext != '\n') || (ch == '\n')) &&
+ (!isMako || (0 != strcmp(makoBlockType, "%")))) {
+ }
+
+ // generic end of script processing
+ else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) {
+ // Check if it's the end of the script tag (or any other HTML tag)
+ switch (state) {
+ // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
+ case SCE_H_DOUBLESTRING:
+ case SCE_H_SINGLESTRING:
+ case SCE_HJ_COMMENT:
+ case SCE_HJ_COMMENTDOC:
+ //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_HB_COMMENTLINE:
+ case SCE_HBA_COMMENTLINE:
+ case SCE_HJ_DOUBLESTRING:
+ case SCE_HJ_SINGLESTRING:
+ case SCE_HJ_REGEX:
+ case SCE_HB_STRING:
+ case SCE_HBA_STRING:
+ case SCE_HP_STRING:
+ case SCE_HP_TRIPLE:
+ case SCE_HP_TRIPLEDOUBLE:
+ case SCE_HPHP_HSTRING:
+ case SCE_HPHP_SIMPLESTRING:
+ case SCE_HPHP_COMMENT:
+ case SCE_HPHP_COMMENTLINE:
+ break;
+ default :
+ // check if the closing tag is a script tag
+ if (const char *tag =
+ state == SCE_HJ_COMMENTLINE || isXml ? "script" :
+ state == SCE_H_COMMENT ? "comment" : 0) {
+ int j = i + 2;
+ int chr;
+ do {
+ chr = static_cast<int>(*tag++);
+ } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++)));
+ if (chr != 0) break;
+ }
+ // closing tag of the script (it's a closing HTML tag anyway)
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_TAGUNKNOWN;
+ inScriptType = eHtml;
+ scriptLanguage = eScriptNone;
+ clientScript = eScriptJS;
+ i += 2;
+ visibleChars += 2;
+ tagClosing = true;
+ continue;
+ }
+ }
+
+ /////////////////////////////////////
+ // handle the start of PHP pre-processor = Non-HTML
+ else if ((state != SCE_H_ASPAT) &&
+ !isPHPStringState(state) &&
+ (state != SCE_HPHP_COMMENT) &&
+ (ch == '<') &&
+ (chNext == '?') &&
+ !IsScriptCommentState(state) ) {
+ scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP);
+ if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
+ styler.ColourTo(i - 1, StateToPrint);
+ beforePreProc = state;
+ i++;
+ visibleChars++;
+ i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6);
+ if (scriptLanguage == eScriptXML)
+ styler.ColourTo(i, SCE_H_XMLSTART);
+ else
+ styler.ColourTo(i, SCE_H_QUESTION);
+ state = StateForScript(scriptLanguage);
+ if (inScriptType == eNonHtmlScript)
+ inScriptType = eNonHtmlScriptPreProc;
+ else
+ inScriptType = eNonHtmlPreProc;
+ // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
+ if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
+ levelCurrent++;
+ }
+ // should be better
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ continue;
+ }
+
+ // handle the start Mako template Python code
+ else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') ||
+ (lineStartVisibleChars == 1 && ch == '%') ||
+ (ch == '$' && chNext == '{') ||
+ (ch == '<' && chNext == '/' && chNext2 == '%'))) {
+ if (ch == '%')
+ strcpy(makoBlockType, "%");
+ else if (ch == '$')
+ strcpy(makoBlockType, "{");
+ else if (chNext == '/')
+ GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType));
+ else
+ GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType));
+ styler.ColourTo(i - 1, StateToPrint);
+ beforePreProc = state;
+ if (inScriptType == eNonHtmlScript)
+ inScriptType = eNonHtmlScriptPreProc;
+ else
+ inScriptType = eNonHtmlPreProc;
+
+ if (chNext == '/') {
+ i += 2;
+ visibleChars += 2;
+ } else if (ch != '%') {
+ i++;
+ visibleChars++;
+ }
+ state = SCE_HP_START;
+ scriptLanguage = eScriptPython;
+ styler.ColourTo(i, SCE_H_ASP);
+ if (foldHTMLPreprocessor && ch == '<')
+ levelCurrent++;
+
+ if (ch != '%' && ch != '$') {
+ i += strlen(makoBlockType);
+ visibleChars += strlen(makoBlockType);
+ if (keywords4.InList(makoBlockType))
+ styler.ColourTo(i, SCE_HP_WORD);
+ else
+ styler.ColourTo(i, SCE_H_TAGUNKNOWN);
+ }
+
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ continue;
+ }
+
+ // handle the start Django template code
+ else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) {
+ if (chNext == '%')
+ strcpy(djangoBlockType, "%");
+ else
+ strcpy(djangoBlockType, "{");
+ styler.ColourTo(i - 1, StateToPrint);
+ beforePreProc = state;
+ if (inScriptType == eNonHtmlScript)
+ inScriptType = eNonHtmlScriptPreProc;
+ else
+ inScriptType = eNonHtmlPreProc;
+
+ i += 1;
+ visibleChars += 1;
+ state = SCE_HP_START;
+ beforeLanguage = scriptLanguage;
+ scriptLanguage = eScriptPython;
+ styler.ColourTo(i, SCE_H_ASP);
+ if (foldHTMLPreprocessor && chNext == '%')
+ levelCurrent++;
+
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ continue;
+ }
+
+ // handle the start of ASP pre-processor = Non-HTML
+ else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ beforePreProc = state;
+ if (inScriptType == eNonHtmlScript)
+ inScriptType = eNonHtmlScriptPreProc;
+ else
+ inScriptType = eNonHtmlPreProc;
+
+ if (chNext2 == '@') {
+ i += 2; // place as if it was the second next char treated
+ visibleChars += 2;
+ state = SCE_H_ASPAT;
+ } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) {
+ styler.ColourTo(i + 3, SCE_H_ASP);
+ state = SCE_H_XCCOMMENT;
+ scriptLanguage = eScriptVBS;
+ continue;
+ } else {
+ if (chNext2 == '=') {
+ i += 2; // place as if it was the second next char treated
+ visibleChars += 2;
+ } else {
+ i++; // place as if it was the next char treated
+ visibleChars++;
+ }
+
+ state = StateForScript(aspScript);
+ }
+ scriptLanguage = eScriptVBS;
+ styler.ColourTo(i, SCE_H_ASP);
+ // fold whole script
+ if (foldHTMLPreprocessor)
+ levelCurrent++;
+ // should be better
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ continue;
+ }
+
+ /////////////////////////////////////
+ // handle the start of SGML language (DTD)
+ else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
+ (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
+ 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
+ scriptLanguage = eScriptSGML;
+ state = SCE_H_SGML_COMMAND; // wait for a pending command
+ }
+ // fold whole tag (-- when closing the tag)
+ if (foldHTMLPreprocessor || (state == SCE_H_COMMENT))
+ levelCurrent++;
+ continue;
+ }
+
+ // handle the end of Mako Python code
+ else if (isMako &&
+ ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
+ (scriptLanguage != eScriptNone) && stateAllowsTermination(state) &&
+ isMakoBlockEnd(ch, chNext, makoBlockType)) {
+ if (state == SCE_H_ASPAT) {
+ aspScript = segIsScriptingIndicator(styler,
+ styler.GetStartSegment(), i - 1, aspScript);
+ }
+ if (state == SCE_HP_WORD) {
+ classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
+ } else {
+ styler.ColourTo(i - 1, StateToPrint);
+ }
+ if (0 != strcmp(makoBlockType, "%") && (0 != strcmp(makoBlockType, "{")) && ch != '>') {
+ i++;
+ visibleChars++;
+ }
+ if (0 != strcmp(makoBlockType, "%")) {
+ styler.ColourTo(i, SCE_H_ASP);
+ }
+ state = beforePreProc;
+ if (inScriptType == eNonHtmlScriptPreProc)
+ inScriptType = eNonHtmlScript;
+ else
+ inScriptType = eHtml;
+ if (foldHTMLPreprocessor && ch != '\n' && ch != '\r') {
+ levelCurrent--;
+ }
+ scriptLanguage = eScriptNone;
+ continue;
+ }
+
+ // handle the end of Django template code
+ else if (isDjango &&
+ ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
+ (scriptLanguage != eScriptNone) && stateAllowsTermination(state) &&
+ isDjangoBlockEnd(ch, chNext, djangoBlockType)) {
+ if (state == SCE_H_ASPAT) {
+ aspScript = segIsScriptingIndicator(styler,
+ styler.GetStartSegment(), i - 1, aspScript);
+ }
+ if (state == SCE_HP_WORD) {
+ classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
+ } else {
+ styler.ColourTo(i - 1, StateToPrint);
+ }
+ i += 1;
+ visibleChars += 1;
+ styler.ColourTo(i, SCE_H_ASP);
+ state = beforePreProc;
+ if (inScriptType == eNonHtmlScriptPreProc)
+ inScriptType = eNonHtmlScript;
+ else
+ inScriptType = eHtml;
+ if (foldHTMLPreprocessor) {
+ levelCurrent--;
+ }
+ scriptLanguage = beforeLanguage;
+ continue;
+ }
+
+ // handle the end of a pre-processor = Non-HTML
+ else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
+ (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) &&
+ (((ch == '%') || (ch == '?')) && (chNext == '>'))) ||
+ ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
+ if (state == SCE_H_ASPAT) {
+ aspScript = segIsScriptingIndicator(styler,
+ styler.GetStartSegment(), i - 1, aspScript);
+ }
+ // Bounce out of any ASP mode
+ switch (state) {
+ case SCE_HJ_WORD:
+ classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
+ break;
+ case SCE_HB_WORD:
+ classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
+ break;
+ case SCE_HP_WORD:
+ classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
+ break;
+ case SCE_HPHP_WORD:
+ classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
+ break;
+ case SCE_H_XCCOMMENT:
+ styler.ColourTo(i - 1, state);
+ break;
+ default :
+ styler.ColourTo(i - 1, StateToPrint);
+ break;
+ }
+ if (scriptLanguage != eScriptSGML) {
+ i++;
+ visibleChars++;
+ }
+ if (ch == '%')
+ styler.ColourTo(i, SCE_H_ASP);
+ else if (scriptLanguage == eScriptXML)
+ styler.ColourTo(i, SCE_H_XMLEND);
+ else if (scriptLanguage == eScriptSGML)
+ styler.ColourTo(i, SCE_H_SGML_DEFAULT);
+ else
+ styler.ColourTo(i, SCE_H_QUESTION);
+ state = beforePreProc;
+ if (inScriptType == eNonHtmlScriptPreProc)
+ inScriptType = eNonHtmlScript;
+ else
+ inScriptType = eHtml;
+ // Unfold all scripting languages, except for XML tag
+ if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
+ levelCurrent--;
+ }
+ scriptLanguage = eScriptNone;
+ continue;
+ }
+ /////////////////////////////////////
+
+ switch (state) {
+ case SCE_H_DEFAULT:
+ if (ch == '<') {
+ // in HTML, fold on tag open and unfold on tag close
+ tagOpened = true;
+ tagClosing = (chNext == '/');
+ styler.ColourTo(i - 1, StateToPrint);
+ if (chNext != '!')
+ state = SCE_H_TAGUNKNOWN;
+ } else if (ch == '&') {
+ styler.ColourTo(i - 1, SCE_H_DEFAULT);
+ state = SCE_H_ENTITY;
+ }
+ break;
+ case SCE_H_SGML_DEFAULT:
+ case SCE_H_SGML_BLOCK_DEFAULT:
+// if (scriptLanguage == eScriptSGMLblock)
+// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
+
+ if (ch == '\"') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_SGML_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_SGML_SIMPLESTRING;
+ } else if ((ch == '-') && (chPrev == '-')) {
+ if (static_cast<int>(styler.GetStartSegment()) <= (i - 2)) {
+ styler.ColourTo(i - 2, StateToPrint);
+ }
+ state = SCE_H_SGML_COMMENT;
+ } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) {
+ styler.ColourTo(i - 2, StateToPrint);
+ state = SCE_H_SGML_ENTITY;
+ } else if (ch == '#') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_SGML_SPECIAL;
+ } else if (ch == '[') {
+ styler.ColourTo(i - 1, StateToPrint);
+ scriptLanguage = eScriptSGMLblock;
+ state = SCE_H_SGML_BLOCK_DEFAULT;
+ } else if (ch == ']') {
+ if (scriptLanguage == eScriptSGMLblock) {
+ styler.ColourTo(i, StateToPrint);
+ scriptLanguage = eScriptSGML;
+ } else {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, SCE_H_SGML_ERROR);
+ }
+ state = SCE_H_SGML_DEFAULT;
+ } else if (scriptLanguage == eScriptSGMLblock) {
+ if ((ch == '!') && (chPrev == '<')) {
+ styler.ColourTo(i - 2, StateToPrint);
+ styler.ColourTo(i, SCE_H_SGML_DEFAULT);
+ state = SCE_H_SGML_COMMAND;
+ } else if (ch == '>') {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, SCE_H_SGML_DEFAULT);
+ }
+ }
+ break;
+ case SCE_H_SGML_COMMAND:
+ if ((ch == '-') && (chPrev == '-')) {
+ styler.ColourTo(i - 2, StateToPrint);
+ state = SCE_H_SGML_COMMENT;
+ } else if (!issgmlwordchar(ch)) {
+ if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_SGML_1ST_PARAM;
+ } else {
+ state = SCE_H_SGML_ERROR;
+ }
+ }
+ break;
+ case SCE_H_SGML_1ST_PARAM:
+ // wait for the beginning of the word
+ if ((ch == '-') && (chPrev == '-')) {
+ if (scriptLanguage == eScriptSGMLblock) {
+ styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT);
+ } else {
+ styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT);
+ }
+ state = SCE_H_SGML_1ST_PARAM_COMMENT;
+ } else if (issgmlwordchar(ch)) {
+ if (scriptLanguage == eScriptSGMLblock) {
+ styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT);
+ } else {
+ styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT);
+ }
+ // find the length of the word
+ int size = 1;
+ while (setHTMLWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(i + size))))
+ size++;
+ styler.ColourTo(i + size - 1, StateToPrint);
+ i += size - 1;
+ visibleChars += size - 1;
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ if (scriptLanguage == eScriptSGMLblock) {
+ state = SCE_H_SGML_BLOCK_DEFAULT;
+ } else {
+ state = SCE_H_SGML_DEFAULT;
+ }
+ continue;
+ }
+ break;
+ case SCE_H_SGML_ERROR:
+ if ((ch == '-') && (chPrev == '-')) {
+ styler.ColourTo(i - 2, StateToPrint);
+ state = SCE_H_SGML_COMMENT;
+ }
+ case SCE_H_SGML_DOUBLESTRING:
+ if (ch == '\"') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_SGML_DEFAULT;
+ }
+ break;
+ case SCE_H_SGML_SIMPLESTRING:
+ if (ch == '\'') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_SGML_DEFAULT;
+ }
+ break;
+ case SCE_H_SGML_COMMENT:
+ if ((ch == '-') && (chPrev == '-')) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_SGML_DEFAULT;
+ }
+ break;
+ case SCE_H_CDATA:
+ if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_DEFAULT;
+ levelCurrent--;
+ }
+ break;
+ case SCE_H_COMMENT:
+ if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_DEFAULT;
+ levelCurrent--;
+ }
+ break;
+ case SCE_H_SGML_1ST_PARAM_COMMENT:
+ if ((ch == '-') && (chPrev == '-')) {
+ styler.ColourTo(i, SCE_H_SGML_COMMENT);
+ state = SCE_H_SGML_1ST_PARAM;
+ }
+ break;
+ case SCE_H_SGML_SPECIAL:
+ if (!(isascii(ch) && isupper(ch))) {
+ styler.ColourTo(i - 1, StateToPrint);
+ if (isalnum(ch)) {
+ state = SCE_H_SGML_ERROR;
+ } else {
+ state = SCE_H_SGML_DEFAULT;
+ }
+ }
+ break;
+ case SCE_H_SGML_ENTITY:
+ if (ch == ';') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_SGML_DEFAULT;
+ } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') {
+ styler.ColourTo(i, SCE_H_SGML_ERROR);
+ state = SCE_H_SGML_DEFAULT;
+ }
+ break;
+ case SCE_H_ENTITY:
+ if (ch == ';') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_DEFAULT;
+ }
+ if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway...
+ && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML
+ if (!isascii(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style
+ styler.ColourTo(i-1, SCE_H_TAGUNKNOWN);
+ else
+ styler.ColourTo(i, SCE_H_TAGUNKNOWN);
+ state = SCE_H_DEFAULT;
+ }
+ break;
+ case SCE_H_TAGUNKNOWN:
+ if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) {
+ int eClass = classifyTagHTML(styler.GetStartSegment(),
+ i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts);
+ if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) {
+ if (!tagClosing) {
+ inScriptType = eNonHtmlScript;
+ scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment;
+ } else {
+ scriptLanguage = eScriptNone;
+ }
+ eClass = SCE_H_TAG;
+ }
+ if (ch == '>') {
+ styler.ColourTo(i, eClass);
+ if (inScriptType == eNonHtmlScript) {
+ state = StateForScript(scriptLanguage);
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ tagOpened = false;
+ if (!tagDontFold) {
+ if (tagClosing) {
+ levelCurrent--;
+ } else {
+ levelCurrent++;
+ }
+ }
+ tagClosing = false;
+ } else if (ch == '/' && chNext == '>') {
+ if (eClass == SCE_H_TAGUNKNOWN) {
+ styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN);
+ } else {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ }
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ tagOpened = false;
+ } else {
+ if (eClass != SCE_H_TAGUNKNOWN) {
+ if (eClass == SCE_H_SGML_DEFAULT) {
+ state = SCE_H_SGML_DEFAULT;
+ } else {
+ state = SCE_H_OTHER;
+ }
+ }
+ }
+ }
+ break;
+ case SCE_H_ATTRIBUTE:
+ if (!setAttributeContinue.Contains(ch)) {
+ if (inScriptType == eNonHtmlScript) {
+ int scriptLanguagePrev = scriptLanguage;
+ clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage);
+ scriptLanguage = clientScript;
+ if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone))
+ inScriptType = eHtml;
+ }
+ classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+ if (ch == '>') {
+ styler.ColourTo(i, SCE_H_TAG);
+ if (inScriptType == eNonHtmlScript) {
+ state = StateForScript(scriptLanguage);
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ tagOpened = false;
+ if (!tagDontFold) {
+ if (tagClosing) {
+ levelCurrent--;
+ } else {
+ levelCurrent++;
+ }
+ }
+ tagClosing = false;
+ } else if (ch == '=') {
+ styler.ColourTo(i, SCE_H_OTHER);
+ state = SCE_H_VALUE;
+ } else {
+ state = SCE_H_OTHER;
+ }
+ }
+ break;
+ case SCE_H_OTHER:
+ if (ch == '>') {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, SCE_H_TAG);
+ if (inScriptType == eNonHtmlScript) {
+ state = StateForScript(scriptLanguage);
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ tagOpened = false;
+ if (!tagDontFold) {
+ if (tagClosing) {
+ levelCurrent--;
+ } else {
+ levelCurrent++;
+ }
+ }
+ tagClosing = false;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_SINGLESTRING;
+ } else if (ch == '=') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_H_VALUE;
+ } else if (ch == '/' && chNext == '>') {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i + 1, SCE_H_TAGEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ tagOpened = false;
+ } else if (ch == '?' && chNext == '>') {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i + 1, SCE_H_XMLEND);
+ i++;
+ ch = chNext;
+ state = SCE_H_DEFAULT;
+ } else if (setHTMLWord.Contains(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_H_ATTRIBUTE;
+ }
+ break;
+ case SCE_H_DOUBLESTRING:
+ if (ch == '\"') {
+ if (inScriptType == eNonHtmlScript) {
+ scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+ }
+ styler.ColourTo(i, SCE_H_DOUBLESTRING);
+ state = SCE_H_OTHER;
+ }
+ break;
+ case SCE_H_SINGLESTRING:
+ if (ch == '\'') {
+ if (inScriptType == eNonHtmlScript) {
+ scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+ }
+ styler.ColourTo(i, SCE_H_SINGLESTRING);
+ state = SCE_H_OTHER;
+ }
+ break;
+ case SCE_H_VALUE:
+ if (!setHTMLWord.Contains(ch)) {
+ if (ch == '\"' && chPrev == '=') {
+ // Should really test for being first character
+ state = SCE_H_DOUBLESTRING;
+ } else if (ch == '\'' && chPrev == '=') {
+ state = SCE_H_SINGLESTRING;
+ } else {
+ if (IsNumber(styler.GetStartSegment(), styler)) {
+ styler.ColourTo(i - 1, SCE_H_NUMBER);
+ } else {
+ styler.ColourTo(i - 1, StateToPrint);
+ }
+ if (ch == '>') {
+ styler.ColourTo(i, SCE_H_TAG);
+ if (inScriptType == eNonHtmlScript) {
+ state = StateForScript(scriptLanguage);
+ } else {
+ state = SCE_H_DEFAULT;
+ }
+ tagOpened = false;
+ if (!tagDontFold) {
+ if (tagClosing) {
+ levelCurrent--;
+ } else {
+ levelCurrent++;
+ }
+ }
+ tagClosing = false;
+ } else {
+ state = SCE_H_OTHER;
+ }
+ }
+ }
+ break;
+ case SCE_HJ_DEFAULT:
+ case SCE_HJ_START:
+ case SCE_HJ_SYMBOLS:
+ if (IsAWordStart(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_WORD;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourTo(i - 1, StateToPrint);
+ if (chNext2 == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_REGEX;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_DOUBLESTRING;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_SINGLESTRING;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ i += 2;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
+ state = SCE_HJ_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HJ_START) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_DEFAULT;
+ }
+ }
+ break;
+ case SCE_HJ_WORD:
+ if (!IsAWordChar(ch)) {
+ classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
+ //styler.ColourTo(i - 1, eHTJSKeyword);
+ state = SCE_HJ_DEFAULT;
+ if (ch == '/' && chNext == '*') {
+ if (chNext2 == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJ_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HJ_DOUBLESTRING;
+ } else if (ch == '\'') {
+ state = SCE_HJ_SINGLESTRING;
+ } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ i += 2;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
+ state = SCE_HJ_DEFAULT;
+ }
+ }
+ break;
+ case SCE_HJ_COMMENT:
+ case SCE_HJ_COMMENTDOC:
+ 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:
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType));
+ state = SCE_HJ_DEFAULT;
+ } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ i += 2;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_STRINGEOL;
+ }
+ break;
+ case SCE_HJ_SINGLESTRING:
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType));
+ state = SCE_HJ_DEFAULT;
+ } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_COMMENTLINE;
+ i += 2;
+ } else if (isLineEnd(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_STRINGEOL;
+ }
+ break;
+ case SCE_HJ_STRINGEOL:
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HJ_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HJ_DEFAULT;
+ }
+ 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 = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ }
+ }
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HJ_DEFAULT;
+ } else if (ch == '\\') {
+ // Gobble up the quoted character
+ if (chNext == '\\' || chNext == '/') {
+ i++;
+ ch = chNext;
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ }
+ }
+ break;
+ case SCE_HB_DEFAULT:
+ case SCE_HB_START:
+ if (IsAWordStart(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_WORD;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_STRING;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_COMMENTLINE;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
+ state = SCE_HB_DEFAULT;
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HB_START) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_DEFAULT;
+ }
+ }
+ break;
+ case SCE_HB_WORD:
+ if (!IsAWordChar(ch)) {
+ state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
+ if (state == SCE_HB_DEFAULT) {
+ if (ch == '\"') {
+ state = SCE_HB_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HB_COMMENTLINE;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
+ state = SCE_HB_DEFAULT;
+ }
+ }
+ }
+ break;
+ case SCE_HB_STRING:
+ if (ch == '\"') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HB_DEFAULT;
+ } else if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_STRINGEOL;
+ }
+ break;
+ case SCE_HB_COMMENTLINE:
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_DEFAULT;
+ }
+ break;
+ case SCE_HB_STRINGEOL:
+ if (!isLineEnd(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HB_DEFAULT;
+ } else if (!isLineEnd(chNext)) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HB_DEFAULT;
+ }
+ break;
+ case SCE_HP_DEFAULT:
+ case SCE_HP_START:
+ if (IsAWordStart(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HP_WORD;
+ } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+ styler.SafeGetCharAt(i + 3) == '-') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '#') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '\"') {
+ styler.ColourTo(i - 1, StateToPrint);
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HP_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ } else {
+ // state = statePrintForState(SCE_HP_STRING,inScriptType);
+ state = SCE_HP_STRING;
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, StateToPrint);
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HP_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ } else {
+ state = SCE_HP_CHARACTER;
+ }
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
+ } else if ((ch == ' ') || (ch == '\t')) {
+ if (state == SCE_HP_START) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ }
+ break;
+ case SCE_HP_WORD:
+ if (!IsAWordChar(ch)) {
+ classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
+ state = SCE_HP_DEFAULT;
+ if (ch == '#') {
+ state = SCE_HP_COMMENTLINE;
+ } else if (ch == '\"') {
+ if (chNext == '\"' && chNext2 == '\"') {
+ i += 2;
+ state = SCE_HP_TRIPLEDOUBLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ } else {
+ state = SCE_HP_STRING;
+ }
+ } else if (ch == '\'') {
+ if (chNext == '\'' && chNext2 == '\'') {
+ i += 2;
+ state = SCE_HP_TRIPLE;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ } else {
+ state = SCE_HP_CHARACTER;
+ }
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
+ }
+ }
+ break;
+ case SCE_HP_COMMENTLINE:
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ break;
+ case SCE_HP_STRING:
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ break;
+ case SCE_HP_CHARACTER:
+ if (ch == '\\') {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+ i++;
+ ch = chNext;
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
+ }
+ } else if (ch == '\'') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ break;
+ case SCE_HP_TRIPLE:
+ if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ break;
+ case SCE_HP_TRIPLEDOUBLE:
+ if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HP_DEFAULT;
+ }
+ break;
+ ///////////// start - PHP state handling
+ case SCE_HPHP_WORD:
+ if (!IsAWordChar(ch)) {
+ classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
+ if (ch == '/' && chNext == '*') {
+ i++;
+ state = SCE_HPHP_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ i++;
+ state = SCE_HPHP_COMMENTLINE;
+ } else if (ch == '#') {
+ state = SCE_HPHP_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HPHP_HSTRING;
+ strcpy(phpStringDelimiter, "\"");
+ } else if (styler.Match(i, "<<<")) {
+ bool isSimpleString = false;
+ i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
+ if (strlen(phpStringDelimiter)) {
+ state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
+ if (foldHeredoc) levelCurrent++;
+ }
+ } else if (ch == '\'') {
+ state = SCE_HPHP_SIMPLESTRING;
+ strcpy(phpStringDelimiter, "\'");
+ } else if (ch == '$' && IsPhpWordStart(chNext)) {
+ state = SCE_HPHP_VARIABLE;
+ } else if (IsOperator(ch)) {
+ state = SCE_HPHP_OPERATOR;
+ } else {
+ state = SCE_HPHP_DEFAULT;
+ }
+ }
+ break;
+ case SCE_HPHP_NUMBER:
+ // 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;
+ else
+ state = SCE_HPHP_DEFAULT;
+ }
+ break;
+ case SCE_HPHP_VARIABLE:
+ if (!IsPhpWordChar(chNext)) {
+ styler.ColourTo(i, SCE_HPHP_VARIABLE);
+ state = SCE_HPHP_DEFAULT;
+ }
+ break;
+ case SCE_HPHP_COMMENT:
+ if (ch == '/' && chPrev == '*') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ }
+ break;
+ case SCE_HPHP_COMMENTLINE:
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ }
+ break;
+ case SCE_HPHP_HSTRING:
+ if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) {
+ // skip the next char
+ i++;
+ } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{'))
+ && IsPhpWordStart(chNext2)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HPHP_COMPLEX_VARIABLE;
+ } else if (ch == '$' && IsPhpWordStart(chNext)) {
+ styler.ColourTo(i - 1, StateToPrint);
+ state = SCE_HPHP_HSTRING_VARIABLE;
+ } else if (styler.Match(i, phpStringDelimiter)) {
+ if (phpStringDelimiter[0] == '\"') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ } else if (isLineEnd(chPrev)) {
+ const int psdLength = strlen(phpStringDelimiter);
+ const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
+ const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
+ if (isLineEnd(chAfterPsd) ||
+ (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
+ i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ if (foldHeredoc) levelCurrent--;
+ }
+ }
+ }
+ break;
+ case SCE_HPHP_SIMPLESTRING:
+ if (phpStringDelimiter[0] == '\'') {
+ if (ch == '\\') {
+ // skip the next char
+ i++;
+ } else if (ch == '\'') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ }
+ } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) {
+ const int psdLength = strlen(phpStringDelimiter);
+ const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
+ const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
+ if (isLineEnd(chAfterPsd) ||
+ (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
+ i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_DEFAULT;
+ if (foldHeredoc) levelCurrent--;
+ }
+ }
+ break;
+ case SCE_HPHP_HSTRING_VARIABLE:
+ if (!IsPhpWordChar(chNext)) {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_HSTRING;
+ }
+ break;
+ case SCE_HPHP_COMPLEX_VARIABLE:
+ if (ch == '}') {
+ styler.ColourTo(i, StateToPrint);
+ state = SCE_HPHP_HSTRING;
+ }
+ break;
+ case SCE_HPHP_OPERATOR:
+ case SCE_HPHP_DEFAULT:
+ styler.ColourTo(i - 1, StateToPrint);
+ if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
+ state = SCE_HPHP_NUMBER;
+ } else if (IsAWordStart(ch)) {
+ state = SCE_HPHP_WORD;
+ } else if (ch == '/' && chNext == '*') {
+ i++;
+ state = SCE_HPHP_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ i++;
+ state = SCE_HPHP_COMMENTLINE;
+ } else if (ch == '#') {
+ state = SCE_HPHP_COMMENTLINE;
+ } else if (ch == '\"') {
+ state = SCE_HPHP_HSTRING;
+ strcpy(phpStringDelimiter, "\"");
+ } else if (styler.Match(i, "<<<")) {
+ bool isSimpleString = false;
+ i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
+ if (strlen(phpStringDelimiter)) {
+ state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
+ if (foldHeredoc) levelCurrent++;
+ }
+ } else if (ch == '\'') {
+ state = SCE_HPHP_SIMPLESTRING;
+ strcpy(phpStringDelimiter, "\'");
+ } else if (ch == '$' && IsPhpWordStart(chNext)) {
+ state = SCE_HPHP_VARIABLE;
+ } else if (IsOperator(ch)) {
+ state = SCE_HPHP_OPERATOR;
+ } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) {
+ state = SCE_HPHP_DEFAULT;
+ }
+ break;
+ ///////////// end - PHP state handling
+ }
+
+ // Some of the above terminated their lexeme but since the same character starts
+ // the same class again, only reenter if non empty segment.
+
+ bool nonEmptySegment = i >= static_cast<int>(styler.GetStartSegment());
+ if (state == SCE_HB_DEFAULT) { // One of the above succeeded
+ if ((ch == '\"') && (nonEmptySegment)) {
+ state = SCE_HB_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HB_COMMENTLINE;
+ } else if (IsAWordStart(ch)) {
+ state = SCE_HB_WORD;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, SCE_HB_DEFAULT);
+ }
+ } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded
+ if ((ch == '\"') && (nonEmptySegment)) {
+ state = SCE_HBA_STRING;
+ } else if (ch == '\'') {
+ state = SCE_HBA_COMMENTLINE;
+ } else if (IsAWordStart(ch)) {
+ state = SCE_HBA_WORD;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, SCE_HBA_DEFAULT);
+ }
+ } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded
+ if (ch == '/' && chNext == '*') {
+ if (styler.SafeGetCharAt(i + 2) == '*')
+ state = SCE_HJ_COMMENTDOC;
+ else
+ state = SCE_HJ_COMMENT;
+ } else if (ch == '/' && chNext == '/') {
+ state = SCE_HJ_COMMENTLINE;
+ } else if ((ch == '\"') && (nonEmptySegment)) {
+ state = SCE_HJ_DOUBLESTRING;
+ } else if ((ch == '\'') && (nonEmptySegment)) {
+ state = SCE_HJ_SINGLESTRING;
+ } else if (IsAWordStart(ch)) {
+ state = SCE_HJ_WORD;
+ } else if (IsOperator(ch)) {
+ styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
+ }
+ }
+ }
+
+ switch (state) {
+ case SCE_HJ_WORD:
+ classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType);
+ break;
+ case SCE_HB_WORD:
+ classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType);
+ break;
+ case SCE_HP_WORD:
+ classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType);
+ break;
+ case SCE_HPHP_WORD:
+ classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler);
+ break;
+ default:
+ StateToPrint = statePrintForState(state, inScriptType);
+ styler.ColourTo(lengthDoc - 1, StateToPrint);
+ break;
+ }
+
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ if (fold) {
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+ }
+}
+
+static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ // Passing in true because we're lexing XML
+ ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+
+static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ // Passing in false because we're notlexing XML
+ ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false);
+}
+
+static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ if (startPos == 0)
+ initStyle = SCE_HPHP_DEFAULT;
+ ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler);
+}
+
+static const char * const htmlWordListDesc[] = {
+ "HTML elements and attributes",
+ "JavaScript keywords",
+ "VBScript keywords",
+ "Python keywords",
+ "PHP keywords",
+ "SGML and DTD keywords",
+ 0,
+};
+
+static const char * const phpscriptWordListDesc[] = {
+ "", //Unused
+ "", //Unused
+ "", //Unused
+ "", //Unused
+ "PHP keywords",
+ "", //Unused
+ 0,
+};
+
+LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8);
+LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8);
+LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8);
diff --git a/scintilla/src/LexHaskell.cxx b/scintilla/src/LexHaskell.cxx
new file mode 100644
index 0000000..f2d5432
--- /dev/null
+++ b/scintilla/src/LexHaskell.cxx
@@ -0,0 +1,275 @@
+/******************************************************************
+ * 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 "PropSetSimple.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#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);
+ } else if (sc.ch == '\\') {
+ sc.Forward();
+ }
+ }
+ // Char
+ else if (sc.state == SCE_HA_CHARACTER) {
+ if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_HA_DEFAULT);
+ } else if (sc.ch == '\\') {
+ sc.Forward();
+ }
+ }
+ // 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);
+ if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too
+ sc.Forward(1);
+ }
+ }
+ // 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('\'')) {
+ 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)
+{
+ PropSetSimple 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");
+
diff --git a/scintilla/src/LexInno.cxx b/scintilla/src/LexInno.cxx
new file mode 100644
index 0000000..e563bd9
--- /dev/null
+++ b/scintilla/src/LexInno.cxx
@@ -0,0 +1,279 @@
+// Scintilla source code edit control
+/** @file LexInno.cxx
+ ** Lexer for Inno Setup scripts.
+ **/
+// Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx.
+// 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 "CharClassify.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
+ int state = SCE_INNO_DEFAULT;
+ char chPrev;
+ char ch = 0;
+ char chNext = styler[startPos];
+ int lengthDoc = startPos + length;
+ char *buffer = new char[length];
+ int bufferCount = 0;
+ bool isBOL, isEOL, isWS, isBOLWS = 0;
+ bool isCode = false;
+ bool isCStyleComment = false;
+
+ WordList &sectionKeywords = *keywordLists[0];
+ WordList &standardKeywords = *keywordLists[1];
+ WordList &parameterKeywords = *keywordLists[2];
+ WordList &preprocessorKeywords = *keywordLists[3];
+ WordList &pascalKeywords = *keywordLists[4];
+ WordList &userKeywords = *keywordLists[5];
+
+ // Go through all provided text segment
+ // using the hand-written state machine shown below
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ for (int i = startPos; i < lengthDoc; i++) {
+ chPrev = ch;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ i++;
+ continue;
+ }
+
+ isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
+ isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
+ isEOL = (ch == '\n' || ch == '\r');
+ isWS = (ch == ' ' || ch == '\t');
+
+ switch(state) {
+ case SCE_INNO_DEFAULT:
+ if (!isCode && ch == ';' && isBOLWS) {
+ // Start of a comment
+ state = SCE_INNO_COMMENT;
+ } else if (ch == '[' && isBOLWS) {
+ // Start of a section name
+ bufferCount = 0;
+ state = SCE_INNO_SECTION;
+ } else if (ch == '#' && isBOLWS) {
+ // Start of a preprocessor directive
+ state = SCE_INNO_PREPROC;
+ } else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') {
+ // Start of an inline expansion
+ state = SCE_INNO_INLINE_EXPANSION;
+ } else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) {
+ // Start of a Pascal comment
+ state = SCE_INNO_COMMENT_PASCAL;
+ isCStyleComment = false;
+ } else if (isCode && ch == '/' && chNext == '/') {
+ // Apparently, C-style comments are legal, too
+ state = SCE_INNO_COMMENT_PASCAL;
+ isCStyleComment = true;
+ } else if (ch == '"') {
+ // Start of a double-quote string
+ state = SCE_INNO_STRING_DOUBLE;
+ } else if (ch == '\'') {
+ // Start of a single-quote string
+ state = SCE_INNO_STRING_SINGLE;
+ } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
+ // Start of an identifier
+ bufferCount = 0;
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ state = SCE_INNO_IDENTIFIER;
+ } else {
+ // Style it the default style
+ styler.ColourTo(i,SCE_INNO_DEFAULT);
+ }
+ break;
+
+ case SCE_INNO_COMMENT:
+ if (isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_COMMENT);
+ }
+ break;
+
+ case SCE_INNO_IDENTIFIER:
+ if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ } else {
+ state = SCE_INNO_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // Check if the buffer contains a keyword
+ if (!isCode && standardKeywords.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_INNO_KEYWORD);
+ } else if (!isCode && parameterKeywords.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_INNO_PARAMETER);
+ } else if (isCode && pascalKeywords.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
+ } else if (!isCode && userKeywords.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
+ } else {
+ styler.ColourTo(i-1,SCE_INNO_DEFAULT);
+ }
+
+ // Push back the faulty character
+ chNext = styler[i--];
+ ch = chPrev;
+ }
+ break;
+
+ case SCE_INNO_SECTION:
+ if (ch == ']') {
+ state = SCE_INNO_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // Check if the buffer contains a section name
+ if (sectionKeywords.InList(buffer)) {
+ styler.ColourTo(i,SCE_INNO_SECTION);
+ isCode = !CompareCaseInsensitive(buffer, "code");
+ } else {
+ styler.ColourTo(i,SCE_INNO_DEFAULT);
+ }
+ } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ } else {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_DEFAULT);
+ }
+ break;
+
+ case SCE_INNO_PREPROC:
+ if (isWS || isEOL) {
+ if (isascii(chPrev) && isalpha(chPrev)) {
+ state = SCE_INNO_DEFAULT;
+ buffer[bufferCount] = '\0';
+
+ // Check if the buffer contains a preprocessor directive
+ if (preprocessorKeywords.InList(buffer)) {
+ styler.ColourTo(i-1,SCE_INNO_PREPROC);
+ } else {
+ styler.ColourTo(i-1,SCE_INNO_DEFAULT);
+ }
+
+ // Push back the faulty character
+ chNext = styler[i--];
+ ch = chPrev;
+ }
+ } else if (isascii(ch) && isalpha(ch)) {
+ if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
+ bufferCount = 0;
+ buffer[bufferCount++] = static_cast<char>(tolower(ch));
+ }
+ break;
+
+ case SCE_INNO_STRING_DOUBLE:
+ if (ch == '"' || isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
+ }
+ break;
+
+ case SCE_INNO_STRING_SINGLE:
+ if (ch == '\'' || isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
+ }
+ break;
+
+ case SCE_INNO_INLINE_EXPANSION:
+ if (ch == '}') {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
+ } else if (isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_DEFAULT);
+ }
+ break;
+
+ case SCE_INNO_COMMENT_PASCAL:
+ if (isCStyleComment) {
+ if (isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
+ }
+ } else {
+ if (ch == '}' || (ch == ')' && chPrev == '*')) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
+ } else if (isEOL) {
+ state = SCE_INNO_DEFAULT;
+ styler.ColourTo(i,SCE_INNO_DEFAULT);
+ }
+ }
+ break;
+
+ }
+ }
+ delete []buffer;
+}
+
+static const char * const innoWordListDesc[] = {
+ "Sections",
+ "Keywords",
+ "Parameters",
+ "Preprocessor directives",
+ "Pascal keywords",
+ "User defined keywords",
+ 0
+};
+
+static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ unsigned int endPos = startPos + length;
+ char chNext = styler[startPos];
+
+ int lineCurrent = styler.GetLine(startPos);
+
+ bool sectionFlag = false;
+ int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
+ int level;
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler[i+1];
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ int style = styler.StyleAt(i);
+
+ if (style == SCE_INNO_SECTION)
+ sectionFlag = true;
+
+ if (atEOL || i == endPos - 1) {
+ if (sectionFlag) {
+ level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ if (level == levelPrev)
+ styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
+ } else {
+ level = levelPrev & SC_FOLDLEVELNUMBERMASK;
+ if (levelPrev & SC_FOLDLEVELHEADERFLAG)
+ level++;
+ }
+
+ styler.SetLevel(lineCurrent, level);
+
+ levelPrev = level;
+ lineCurrent++;
+ sectionFlag = false;
+ }
+ }
+}
+
+LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);
diff --git a/scintilla/src/LexKix.cxx b/scintilla/src/LexKix.cxx
new file mode 100644
index 0000000..2752570
--- /dev/null
+++ b/scintilla/src/LexKix.cxx
@@ -0,0 +1,126 @@
+// Scintilla source code edit control
+/** @file LexKix.cxx
+ ** Lexer for KIX-Scripts.
+ **/
+// Copyright 2004 by Manfred Becker <manfred@becker-trdf.de>
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+ return ch >= 0x80 || isalnum(ch) || ch == '_';
+}
+
+static inline bool IsOperator(const int ch) {
+ return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '=');
+}
+
+static void ColouriseKixDoc(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];
+
+ styler.StartAt(startPos);
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_KIX_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_STRING1) {
+ // This is a doubles quotes string
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_STRING2) {
+ // This is a single quote string
+ if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_NUMBER) {
+ if (!IsADigit(sc.ch)) {
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_VAR) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_MACRO) {
+ if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+
+ if (!keywords3.InList(&s[1])) {
+ sc.ChangeState(SCE_KIX_DEFAULT);
+ }
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_OPERATOR) {
+ if (!IsOperator(sc.ch)) {
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ } else if (sc.state == SCE_KIX_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_KIX_KEYWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_KIX_FUNCTIONS);
+ }
+ sc.SetState(SCE_KIX_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_KIX_DEFAULT) {
+ if (sc.ch == ';') {
+ sc.SetState(SCE_KIX_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_KIX_STRING1);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_KIX_STRING2);
+ } else if (sc.ch == '$') {
+ sc.SetState(SCE_KIX_VAR);
+ } else if (sc.ch == '@') {
+ sc.SetState(SCE_KIX_MACRO);
+ } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_KIX_NUMBER);
+ } else if (IsOperator(sc.ch)) {
+ sc.SetState(SCE_KIX_OPERATOR);
+ } else if (IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_KIX_IDENTIFIER);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+
+LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix");
+
diff --git a/scintilla/src/LexLisp.cxx b/scintilla/src/LexLisp.cxx
new file mode 100644
index 0000000..bad298c
--- /dev/null
+++ b/scintilla/src/LexLisp.cxx
@@ -0,0 +1,282 @@
+// Scintilla source code edit control
+/** @file LexLisp.cxx
+ ** Lexer for Lisp.
+ ** Written by Alexey Yutkin.
+ **/
+// Copyright 1998-2001 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 "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "StyleContext.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#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 == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
+ return true;
+ return false;
+}
+
+static inline bool isLispwordstart(char ch) {
+ return isascii(ch) && ch != ';' && !isspacechar(ch) && !isLispoperator(ch) &&
+ ch != '\n' && ch != '\r' && ch != '\"';
+}
+
+
+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;
+ bool digit_flag = true;
+ for (i = 0; (i < end - start + 1) && (i < 99); i++) {
+ s[i] = styler[start + i];
+ s[i + 1] = '\0';
+ if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
+ }
+ char chAttr = SCE_LISP_IDENTIFIER;
+
+ if(digit_flag) chAttr = SCE_LISP_NUMBER;
+ 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);
+ return;
+}
+
+
+static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords_kw = *keywordlists[1];
+
+ styler.StartAt(startPos);
+
+ int state = initStyle, radix = -1;
+ char chNext = styler[startPos];
+ unsigned int lengthDoc = startPos + length;
+ styler.StartSegment(startPos);
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_LISP_DEFAULT) {
+ if (ch == '#') {
+ styler.ColourTo(i - 1, state);
+ radix = -1;
+ state = SCE_LISP_MACRO_DISPATCH;
+ } else if (ch == ':' && isLispwordstart(chNext)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_LISP_SYMBOL;
+ } else if (isLispwordstart(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_LISP_IDENTIFIER;
+ }
+ else if (ch == ';') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_LISP_COMMENT;
+ }
+ 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 || state == SCE_LISP_SYMBOL) {
+ if (!isLispwordstart(ch)) {
+ 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 (!(isascii(ch) && 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 == '\\') {
+ i++;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (ch == '\"') {
+ styler.ColourTo(i, state);
+ state = SCE_LISP_DEFAULT;
+ }
+ }
+ }
+
+ }
+ styler.ColourTo(lengthDoc - 1, state);
+}
+
+static void FoldLispDoc(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_LISP_OPERATOR) {
+ if (ch == '(' || ch == '[' || ch == '{') {
+ levelCurrent++;
+ } else if (ch == ')' || ch == ']' || 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 lispWordListDesc[] = {
+ "Functions and special operators",
+ "Keywords",
+ 0
+};
+
+LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);
diff --git a/scintilla/src/LexLout.cxx b/scintilla/src/LexLout.cxx
new file mode 100644
index 0000000..8ec3f39
--- /dev/null
+++ b/scintilla/src/LexLout.cxx
@@ -0,0 +1,212 @@
+// Scintilla source code edit control
+/** @file LexLout.cxx
+ ** Lexer for the Basser Lout (>= version 3) typesetting language
+ **/
+// Copyright 2003 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_');
+}
+
+static inline bool IsAnOther(const int ch) {
+ return (ch < 0x80) && (ch == '{' || ch == '}' ||
+ ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' ||
+ ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
+ ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' ||
+ ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' ||
+ ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~');
+}
+
+static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+
+ int visibleChars = 0;
+ int firstWordInLine = 0;
+ int leadingAtSign = 0;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) {
+ // Prevent SCE_LOUT_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_LOUT_STRING);
+ }
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_LOUT_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_LOUT_DEFAULT);
+ visibleChars = 0;
+ }
+ } else if (sc.state == SCE_LOUT_NUMBER) {
+ if (!IsADigit(sc.ch) && sc.ch != '.') {
+ sc.SetState(SCE_LOUT_DEFAULT);
+ }
+ } else if (sc.state == SCE_LOUT_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_LOUT_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_LOUT_STRINGEOL);
+ sc.ForwardSetState(SCE_LOUT_DEFAULT);
+ visibleChars = 0;
+ }
+ } else if (sc.state == SCE_LOUT_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+
+ if (leadingAtSign) {
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_LOUT_WORD);
+ } else {
+ sc.ChangeState(SCE_LOUT_WORD4);
+ }
+ } else if (firstWordInLine && keywords3.InList(s)) {
+ sc.ChangeState(SCE_LOUT_WORD3);
+ }
+ sc.SetState(SCE_LOUT_DEFAULT);
+ }
+ } else if (sc.state == SCE_LOUT_OPERATOR) {
+ if (!IsAnOther(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+
+ if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_LOUT_WORD2);
+ }
+ sc.SetState(SCE_LOUT_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_LOUT_DEFAULT) {
+ if (sc.ch == '#') {
+ sc.SetState(SCE_LOUT_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_LOUT_STRING);
+ } else if (IsADigit(sc.ch) ||
+ (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_LOUT_NUMBER);
+ } else if (IsAWordChar(sc.ch)) {
+ firstWordInLine = (visibleChars == 0);
+ leadingAtSign = (sc.ch == '@');
+ sc.SetState(SCE_LOUT_IDENTIFIER);
+ } else if (IsAnOther(sc.ch)) {
+ sc.SetState(SCE_LOUT_OPERATOR);
+ }
+ }
+
+ if (sc.atLineEnd) {
+ // Reset states to begining of colourise so no surprises
+ // if different sets of lines lexed.
+ visibleChars = 0;
+ }
+ if (!IsASpace(sc.ch)) {
+ visibleChars++;
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[],
+ Accessor &styler) {
+
+ 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 foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ int styleNext = styler.StyleAt(startPos);
+ char s[10];
+
+ 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 (style == SCE_LOUT_WORD) {
+ if (ch == '@') {
+ for (unsigned int j = 0; j < 8; j++) {
+ if (!IsAWordChar(styler[i + j])) {
+ break;
+ }
+ s[j] = styler[i + j];
+ s[j + 1] = '\0';
+ }
+ if (strcmp(s, "@Begin") == 0) {
+ levelCurrent++;
+ } else if (strcmp(s, "@End") == 0) {
+ levelCurrent--;
+ }
+ }
+ } else if (style == SCE_LOUT_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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 loutWordLists[] = {
+ "Predefined identifiers",
+ "Predefined delimiters",
+ "Predefined keywords",
+ 0,
+ };
+
+LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists);
diff --git a/scintilla/src/LexLua.cxx b/scintilla/src/LexLua.cxx
new file mode 100644
index 0000000..d64d3bb
--- /dev/null
+++ b/scintilla/src/LexLua.cxx
@@ -0,0 +1,358 @@
+// Scintilla source code edit control
+/** @file LexLua.cxx
+ ** Lexer for Lua language.
+ **
+ ** Written by Paul Winwood.
+ ** Folder by Alexey Yutkin.
+ ** Modified by Marcos E. Wurzius & Philippe Lhoste
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// 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,
+ 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];
+
+ // Accepts accented characters
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+ // Not exactly following number definition (several dots are seen as OK, etc.)
+ // but probably enough in most cases.
+ CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefABCDEF");
+ CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#");
+ CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\");
+
+ int currentLine = styler.GetLine(startPos);
+ // 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 || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
+ initStyle = SCE_LUA_DEFAULT;
+ }
+
+ StyleContext sc(startPos, length, initStyle, styler);
+ if (startPos == 0 && sc.ch == '#') {
+ // shbang line: # is a comment only if first char of the script
+ sc.SetState(SCE_LUA_COMMENTLINE);
+ }
+ for (; sc.More(); sc.Forward()) {
+ if (sc.atLineEnd) {
+ // Update the line state, so it can be seen by next line
+ currentLine = styler.GetLine(sc.currentPos);
+ switch (sc.state) {
+ case SCE_LUA_LITERALSTRING:
+ 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
+ styler.SetLineState(currentLine, 0);
+ break;
+ }
+ }
+ if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
+ // Prevent SCE_LUA_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_LUA_STRING);
+ }
+
+ // Handle string line continuation
+ if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
+ 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_LUA_OPERATOR) {
+ sc.SetState(SCE_LUA_DEFAULT);
+ } else if (sc.state == SCE_LUA_NUMBER) {
+ // We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
+ if (!setNumber.Contains(sc.ch)) {
+ sc.SetState(SCE_LUA_DEFAULT);
+ } else if (sc.ch == '-' || sc.ch == '+') {
+ if (sc.chPrev != 'E' && sc.chPrev != 'e')
+ sc.SetState(SCE_LUA_DEFAULT);
+ }
+ } else if (sc.state == SCE_LUA_IDENTIFIER) {
+ if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD4);
+ } else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD5);
+ } else if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD6);
+ } else if (keywords7.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD7);
+ } else if (keywords8.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD8);
+ }
+ sc.SetState(SCE_LUA_DEFAULT);
+ }
+ } else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
+ if (sc.atLineEnd) {
+ sc.ForwardSetState(SCE_LUA_DEFAULT);
+ }
+ } else if (sc.state == SCE_LUA_STRING) {
+ if (sc.ch == '\\') {
+ if (setEscapeSkip.Contains(sc.chNext)) {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_LUA_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_LUA_STRINGEOL);
+ sc.ForwardSetState(SCE_LUA_DEFAULT);
+ }
+ } else if (sc.state == SCE_LUA_CHARACTER) {
+ if (sc.ch == '\\') {
+ if (setEscapeSkip.Contains(sc.chNext)) {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_LUA_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_LUA_STRINGEOL);
+ 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.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);
+ }
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_LUA_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_LUA_NUMBER);
+ if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
+ sc.Forward();
+ }
+ } else if (setWordStart.Contains(sc.ch)) {
+ sc.SetState(SCE_LUA_IDENTIFIER);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_LUA_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_LUA_CHARACTER);
+ } 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);
+ 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 (setLuaOperator.Contains(sc.ch)) {
+ sc.SetState(SCE_LUA_OPERATOR);
+ }
+ }
+ }
+
+ if (setWord.Contains(sc.chPrev)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD4);
+ } else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD5);
+ } else if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD6);
+ } else if (keywords7.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD7);
+ } else if (keywords8.InList(s)) {
+ sc.ChangeState(SCE_LUA_WORD8);
+ }
+ }
+
+ sc.Complete();
+}
+
+static void FoldLuaDoc(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];
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ int styleNext = styler.StyleAt(startPos);
+ char s[10];
+
+ 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_LUA_WORD) {
+ 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;
+ }
+ s[j] = styler[i + j];
+ s[j + 1] = '\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) || (strcmp(s, "until") == 0)) {
+ levelCurrent--;
+ }
+ }
+ } else if (style == SCE_LUA_OPERATOR) {
+ if (ch == '{' || ch == '(') {
+ levelCurrent++;
+ } else if (ch == '}' || ch == ')') {
+ levelCurrent--;
+ }
+ } else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
+ if (ch == '[') {
+ levelCurrent++;
+ } else if (ch == ']') {
+ 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 luaWordListDesc[] = {
+ "Keywords",
+ "Basic functions",
+ "String, (table) & math functions",
+ "(coroutines), I/O & system facilities",
+ "user1",
+ "user2",
+ "user3",
+ "user4",
+ 0
+};
+
+LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
diff --git a/scintilla/src/LexMMIXAL.cxx b/scintilla/src/LexMMIXAL.cxx
new file mode 100644
index 0000000..4c80907
--- /dev/null
+++ b/scintilla/src/LexMMIXAL.cxx
@@ -0,0 +1,186 @@
+// Scintilla source code edit control
+/** @file LexMMIXAL.cxx
+ ** Lexer for MMIX Assembler Language.
+ ** Written by Christoph Hösler <christoph.hoesler@student.uni-tuebingen.de>
+ ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html
+ **/
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_');
+}
+
+inline bool isMMIXALOperator(char ch) {
+ if (isascii(ch) && isalnum(ch))
+ return false;
+ 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 ColouriseMMIXALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &opcodes = *keywordlists[0];
+ WordList &special_register = *keywordlists[1];
+ WordList &predef_symbols = *keywordlists[2];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+ // No EOL continuation
+ if (sc.atLineStart) {
+ if (sc.ch == '@' && sc.chNext == 'i') {
+ sc.SetState(SCE_MMIXAL_INCLUDE);
+ } else {
+ sc.SetState(SCE_MMIXAL_LEADWS);
+ }
+ }
+
+ // Check if first non whitespace character in line is alphanumeric
+ if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) { // LEADWS
+ if(!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_MMIXAL_COMMENT);
+ } else {
+ if(sc.atLineStart) {
+ sc.SetState(SCE_MMIXAL_LABEL);
+ } else {
+ sc.SetState(SCE_MMIXAL_OPCODE_PRE);
+ }
+ }
+ }
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_MMIXAL_OPERATOR) { // OPERATOR
+ sc.SetState(SCE_MMIXAL_OPERANDS);
+ } else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER
+ if (!isdigit(sc.ch)) {
+ if (IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ sc.ChangeState(SCE_MMIXAL_REF);
+ sc.SetState(SCE_MMIXAL_REF);
+ } else {
+ sc.SetState(SCE_MMIXAL_OPERANDS);
+ }
+ }
+ } else if (sc.state == SCE_MMIXAL_LABEL) { // LABEL
+ if (!IsAWordChar(sc.ch) ) {
+ sc.SetState(SCE_MMIXAL_OPCODE_PRE);
+ }
+ } else if (sc.state == SCE_MMIXAL_REF) { // REF
+ if (!IsAWordChar(sc.ch) ) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (*s == ':') { // ignore base prefix for match
+ for (size_t i = 0; i != sizeof(s); ++i) {
+ *(s+i) = *(s+i+1);
+ }
+ }
+ if (special_register.InList(s)) {
+ sc.ChangeState(SCE_MMIXAL_REGISTER);
+ } else if (predef_symbols.InList(s)) {
+ sc.ChangeState(SCE_MMIXAL_SYMBOL);
+ }
+ sc.SetState(SCE_MMIXAL_OPERANDS);
+ }
+ } else if (sc.state == SCE_MMIXAL_OPCODE_PRE) { // OPCODE_PRE
+ if (!isspace(sc.ch)) {
+ sc.SetState(SCE_MMIXAL_OPCODE);
+ }
+ } else if (sc.state == SCE_MMIXAL_OPCODE) { // OPCODE
+ if (!IsAWordChar(sc.ch) ) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (opcodes.InList(s)) {
+ sc.ChangeState(SCE_MMIXAL_OPCODE_VALID);
+ } else {
+ sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN);
+ }
+ sc.SetState(SCE_MMIXAL_OPCODE_POST);
+ }
+ } else if (sc.state == SCE_MMIXAL_STRING) { // STRING
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
+ } else if (sc.atLineEnd) {
+ sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
+ }
+ } else if (sc.state == SCE_MMIXAL_CHAR) { // CHAR
+ if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
+ } else if (sc.atLineEnd) {
+ sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
+ }
+ } else if (sc.state == SCE_MMIXAL_REGISTER) { // REGISTER
+ if (!isdigit(sc.ch)) {
+ sc.SetState(SCE_MMIXAL_OPERANDS);
+ }
+ } else if (sc.state == SCE_MMIXAL_HEX) { // HEX
+ if (!isxdigit(sc.ch)) {
+ sc.SetState(SCE_MMIXAL_OPERANDS);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST
+ sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS
+ if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) {
+ if (!sc.atLineEnd) {
+ sc.SetState(SCE_MMIXAL_COMMENT);
+ }
+ } else if (isdigit(sc.ch)) {
+ sc.SetState(SCE_MMIXAL_NUMBER);
+ } else if (IsAWordChar(sc.ch) || sc.Match('@')) {
+ sc.SetState(SCE_MMIXAL_REF);
+ } else if (sc.Match('\"')) {
+ sc.SetState(SCE_MMIXAL_STRING);
+ } else if (sc.Match('\'')) {
+ sc.SetState(SCE_MMIXAL_CHAR);
+ } else if (sc.Match('$')) {
+ sc.SetState(SCE_MMIXAL_REGISTER);
+ } else if (sc.Match('#')) {
+ sc.SetState(SCE_MMIXAL_HEX);
+ } else if (isMMIXALOperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_MMIXAL_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static const char * const MMIXALWordListDesc[] = {
+ "Operation Codes",
+ "Special Register",
+ "Predefined Symbols",
+ 0
+};
+
+LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc);
+
diff --git a/scintilla/src/LexMPT.cxx b/scintilla/src/LexMPT.cxx
new file mode 100644
index 0000000..9d971de
--- /dev/null
+++ b/scintilla/src/LexMPT.cxx
@@ -0,0 +1,188 @@
+// Scintilla source code edit control
+/** @file LexMPT.cxx
+ ** Lexer for MPT specific files. Based on LexOthers.cxx
+ ** LOT = the text log file created by the MPT application while running a test program
+ ** Other MPT specific files to be added later.
+ **/
+// Copyright 2003 by Marius Gheorghe <mgheorghe@cabletest.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static int GetLotLineState(std::string &line) {
+ if (line.length()) {
+ // Most of the time the first non-blank character in line determines that line's type
+ // Now finds the first non-blank character
+ unsigned i; // Declares counter here to make it persistent after the for loop
+ for (i = 0; i < line.length(); ++i) {
+ if (!(isascii(line[i]) && isspace(line[i])))
+ break;
+ }
+
+ // Checks if it was a blank line
+ if (i == line.length())
+ return SCE_LOT_DEFAULT;
+
+ switch (line[i]) {
+ case '*': // Fail measurement
+ return SCE_LOT_FAIL;
+
+ case '+': // Header
+ case '|': // Header
+ return SCE_LOT_HEADER;
+
+ case ':': // Set test limits
+ return SCE_LOT_SET;
+
+ case '-': // Section break
+ return SCE_LOT_BREAK;
+
+ default: // Any other line
+ // Checks for message at the end of lot file
+ if (line.find("PASSED") != std::string::npos) {
+ return SCE_LOT_PASS;
+ }
+ else if (line.find("FAILED") != std::string::npos) {
+ return SCE_LOT_FAIL;
+ }
+ else if (line.find("ABORTED") != std::string::npos) {
+ return SCE_LOT_ABORT;
+ }
+ else {
+ return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT;
+ }
+ }
+ }
+ else {
+ return SCE_LOT_DEFAULT;
+ }
+}
+
+static void ColourizeLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ bool atLineStart = true;// Arms the 'at line start' flag
+ char chNext = styler.SafeGetCharAt(startPos);
+ std::string line("");
+ line.reserve(256); // Lot lines are less than 256 chars long most of the time. This should avoid reallocations
+
+ // Styles LOT document
+ unsigned int i; // Declared here because it's used after the for loop
+ for (i = startPos; i < startPos + length; ++i) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ line += ch;
+ atLineStart = false;
+
+ // LOT files are only used on the Win32 platform, thus EOL == CR+LF
+ // Searches for the end of line
+ if (ch == '\r' && chNext == '\n') {
+ line += chNext; // Gets the '\n'
+ ++i; // Advances past the '\n'
+ chNext = styler.SafeGetCharAt(i + 1); // Gets character of next line
+ styler.ColourTo(i, GetLotLineState(line));
+ line = "";
+ atLineStart = true; // Arms flag for next line
+ }
+ }
+
+ // Last line may not have a line ending
+ if (!atLineStart) {
+ styler.ColourTo(i - 1, GetLotLineState(line));
+ }
+}
+
+// Folds an MPT LOT file: the blocks that can be folded are:
+// sections (headed by a set line)
+// passes (contiguous pass results within a section)
+// fails (contiguous fail results within a section)
+static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 0) != 0;
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+
+ char chNext = styler.SafeGetCharAt(startPos);
+ int style = SCE_LOT_DEFAULT;
+ int styleNext = styler.StyleAt(startPos);
+ int lev = SC_FOLDLEVELBASE;
+
+ // Gets style of previous line if not at the beginning of the document
+ if (startPos > 1)
+ style = styler.StyleAt(startPos - 2);
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (ch == '\r' && chNext == '\n') {
+ // TO DO:
+ // Should really get the state of the previous line from the styler
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 2);
+
+ switch (style) {
+/*
+ case SCE_LOT_SET:
+ lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ break;
+*/
+ case SCE_LOT_FAIL:
+/*
+ if (stylePrev != SCE_LOT_FAIL)
+ lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ else
+ lev = SC_FOLDLEVELBASE + 1;
+*/
+ lev = SC_FOLDLEVELBASE;
+ break;
+
+ default:
+ if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL)
+ lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ else
+ lev = SC_FOLDLEVELBASE + 1;
+
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ break;
+ }
+
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+
+ lineCurrent++;
+ visibleChars = 0;
+ }
+
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, lev | flagsNext);
+}
+
+static const char * const emptyWordListDesc[] = {
+ 0
+};
+
+LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot", FoldLotDoc, emptyWordListDesc);
diff --git a/scintilla/src/LexMSSQL.cxx b/scintilla/src/LexMSSQL.cxx
new file mode 100644
index 0000000..9f1dff6
--- /dev/null
+++ b/scintilla/src/LexMSSQL.cxx
@@ -0,0 +1,363 @@
+// Scintilla source code edit control
+/** @file LexMSSQL.cxx
+ ** Lexer for MSSQL.
+ **/
+// By Filip Yaghob <fyaghob@gmail.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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define KW_MSSQL_STATEMENTS 0
+#define KW_MSSQL_DATA_TYPES 1
+#define KW_MSSQL_SYSTEM_TABLES 2
+#define KW_MSSQL_GLOBAL_VARIABLES 3
+#define KW_MSSQL_FUNCTIONS 4
+#define KW_MSSQL_STORED_PROCEDURES 5
+#define KW_MSSQL_OPERATORS 6
+
+static bool isMSSQLOperator(char ch) {
+ if (isascii(ch) && 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 == ',')
+ return true;
+ return false;
+}
+
+static char classifyWordSQL(unsigned int start,
+ unsigned int end,
+ WordList *keywordlists[],
+ Accessor &styler,
+ unsigned int actualState,
+ unsigned int prevState) {
+ char s[256];
+ bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+
+ 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];
+ WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES];
+ WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS];
+
+ for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ s[i + 1] = '\0';
+ }
+ char chAttr = SCE_MSSQL_IDENTIFIER;
+
+ if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) {
+
+ if (kwGlobalVariables.InList(&s[2]))
+ chAttr = SCE_MSSQL_GLOBAL_VARIABLE;
+
+ } else if (wordIsNumber) {
+ chAttr = SCE_MSSQL_NUMBER;
+
+ } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
+ // Look first in datatypes
+ if (kwDataTypes.InList(s))
+ chAttr = SCE_MSSQL_DATATYPE;
+ else if (kwOperators.InList(s))
+ chAttr = SCE_MSSQL_OPERATOR;
+ else if (kwStatements.InList(s))
+ chAttr = SCE_MSSQL_STATEMENT;
+ else if (kwSystemTables.InList(s))
+ chAttr = SCE_MSSQL_SYSTABLE;
+ else if (kwFunctions.InList(s))
+ chAttr = SCE_MSSQL_FUNCTION;
+ else if (kwStoredProcedures.InList(s))
+ chAttr = SCE_MSSQL_STORED_PROCEDURE;
+
+ } else {
+ if (kwOperators.InList(s))
+ chAttr = SCE_MSSQL_OPERATOR;
+ else if (kwStatements.InList(s))
+ chAttr = SCE_MSSQL_STATEMENT;
+ else if (kwSystemTables.InList(s))
+ chAttr = SCE_MSSQL_SYSTABLE;
+ else if (kwFunctions.InList(s))
+ chAttr = SCE_MSSQL_FUNCTION;
+ else if (kwStoredProcedures.InList(s))
+ chAttr = SCE_MSSQL_STORED_PROCEDURE;
+ else if (kwDataTypes.InList(s))
+ chAttr = SCE_MSSQL_DATATYPE;
+ }
+
+ styler.ColourTo(end, chAttr);
+
+ return chAttr;
+}
+
+static void ColouriseMSSQLDoc(unsigned int startPos, int length,
+ int initStyle, WordList *keywordlists[], Accessor &styler) {
+
+
+ styler.StartAt(startPos);
+
+ bool fold = styler.GetPropertyInt("fold") != 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int spaceFlags = 0;
+
+ int state = initStyle;
+ int prevState = 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')) {
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
+ int lev = 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;
+ }
+ }
+ if (fold) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ }
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ // When the last char isn't part of the state (have to deal with it too)...
+ if ( (state == SCE_MSSQL_IDENTIFIER) ||
+ (state == SCE_MSSQL_STORED_PROCEDURE) ||
+ (state == SCE_MSSQL_DATATYPE) ||
+ //~ (state == SCE_MSSQL_COLUMN_NAME) ||
+ (state == SCE_MSSQL_FUNCTION) ||
+ //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) ||
+ (state == SCE_MSSQL_VARIABLE)) {
+ if (!iswordchar(ch)) {
+ int stateTmp;
+
+ if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) {
+ styler.ColourTo(i - 1, state);
+ stateTmp = state;
+ } else
+ stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
+
+ prevState = state;
+
+ if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE)
+ state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
+ else
+ state = SCE_MSSQL_DEFAULT;
+ }
+ } else if (state == SCE_MSSQL_LINE_COMMENT) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT;
+ }
+ } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) {
+ if ((ch != '@') && !iswordchar(ch)) {
+ classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT;
+ }
+ }
+
+ // If is the default or one of the above succeeded
+ if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
+ if (iswordstart(ch)) {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_IDENTIFIER;
+ } else if (ch == '/' && chNext == '*') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_COMMENT;
+ } else if (ch == '-' && chNext == '-') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_LINE_COMMENT;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_STRING;
+ } else if (ch == '"') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_COLUMN_NAME;
+ } else if (ch == '[') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ state = SCE_MSSQL_COLUMN_NAME_2;
+ } else if (isMSSQLOperator(ch)) {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ styler.ColourTo(i, SCE_MSSQL_OPERATOR);
+ //~ style = SCE_MSSQL_DEFAULT;
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT;
+ } else if (ch == '@') {
+ styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
+ prevState = state;
+ if (chNext == '@') {
+ state = SCE_MSSQL_GLOBAL_VARIABLE;
+// i += 2;
+ } else
+ state = SCE_MSSQL_VARIABLE;
+ }
+
+
+ // When the last char is part of the state...
+ } else if (state == SCE_MSSQL_COMMENT) {
+ if (ch == '/' && chPrev == '*') {
+ if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) &&
+ (styler.GetStartSegment() == startPos)))) {
+ styler.ColourTo(i, state);
+ //~ state = SCE_MSSQL_COMMENT;
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT;
+ }
+ }
+ } else if (state == SCE_MSSQL_STRING) {
+ if (ch == '\'') {
+ if ( chNext == '\'' ) {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ styler.ColourTo(i, state);
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT;
+ //i++;
+ }
+ //ch = chNext;
+ //chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (state == SCE_MSSQL_COLUMN_NAME) {
+ if (ch == '"') {
+ if (chNext == '"') {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ styler.ColourTo(i, state);
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
+ //i++;
+ }
+ }
+ } else if (state == SCE_MSSQL_COLUMN_NAME_2) {
+ if (ch == ']') {
+ styler.ColourTo(i, state);
+ prevState = state;
+ state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
+ //i++;
+ }
+ }
+
+ chPrev = ch;
+ }
+ 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 or case and end
+ if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') {
+ for (unsigned int j = 0; j < 5; j++) {
+ if (!iswordchar(styler[i + j])) {
+ break;
+ }
+ s[j] = static_cast<char>(tolower(styler[i + j]));
+ s[j + 1] = '\0';
+ }
+ if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 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",
+ "System tables",
+ "Global variables",
+ "Functions",
+ "System Stored Procedures",
+ "Operators",
+ 0,
+};
+
+LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);
diff --git a/scintilla/src/LexMagik.cxx b/scintilla/src/LexMagik.cxx
new file mode 100644
index 0000000..a70b0ed
--- /dev/null
+++ b/scintilla/src/LexMagik.cxx
@@ -0,0 +1,445 @@
+// Scintilla source code edit control
+/**
+ * @file LexMagik.cxx
+ * Lexer for GE(r) Smallworld(tm) MagikSF
+ */
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/**
+ * Is it a core character (C isalpha(), exclamation and question mark)
+ *
+ * \param ch The character
+ * \return True if ch is a character, False otherwise
+ */
+static inline bool IsAlphaCore(int ch) {
+ return (isalpha(ch) || ch == '!' || ch == '?');
+}
+
+/**
+ * Is it a character (IsAlphaCore() and underscore)
+ *
+ * \param ch The character
+ * \return True if ch is a character, False otherwise
+ */
+static inline bool IsAlpha(int ch) {
+ return (IsAlphaCore(ch) || ch == '_');
+}
+
+/**
+ * Is it a symbolic character (IsAlpha() and colon)
+ *
+ * \param ch The character
+ * \return True if ch is a character, False otherwise
+ */
+static inline bool IsAlphaSym(int ch) {
+ return (IsAlpha(ch) || ch == ':');
+}
+
+/**
+ * Is it a numerical character (IsAlpha() and 0 - 9)
+ *
+ * \param ch The character
+ * \return True if ch is a character, False otherwise
+ */
+static inline bool IsAlNum(int ch) {
+ return ((ch >= '0' && ch <= '9') || IsAlpha(ch));
+}
+
+/**
+ * Is it a symbolic numerical character (IsAlNum() and colon)
+ *
+ * \param ch The character
+ * \return True if ch is a character, False otherwise
+ */
+static inline bool IsAlNumSym(int ch) {
+ return (IsAlNum(ch) || ch == ':');
+}
+
+/**
+ * The lexer function
+ *
+ * \param startPos Where to start scanning
+ * \param length Where to scan to
+ * \param initStyle The style at the initial point, not used in this folder
+ * \param keywordslists The keywordslists, currently, number 5 is used
+ * \param styler The styler
+ */
+static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ styler.StartAt(startPos);
+
+ WordList &keywords = *keywordlists[0];
+ WordList &pragmatics = *keywordlists[1];
+ WordList &containers = *keywordlists[2];
+ WordList &flow = *keywordlists[3];
+ WordList &characters = *keywordlists[4];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+
+ for (; sc.More(); sc.Forward()) {
+
+ repeat:
+
+ if(sc.ch == '#') {
+ if (sc.chNext == '#') sc.SetState(SCE_MAGIK_HYPER_COMMENT);
+ else sc.SetState(SCE_MAGIK_COMMENT);
+ for(; sc.More() && !(sc.atLineEnd); sc.Forward());
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ if(sc.ch == '"') {
+ sc.SetState(SCE_MAGIK_STRING);
+
+ if(sc.More())
+ {
+ sc.Forward();
+ for(; sc.More() && sc.ch != '"'; sc.Forward());
+ }
+
+ sc.ForwardSetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ // The default state
+ if(sc.state == SCE_MAGIK_DEFAULT) {
+
+ // A certain keyword has been detected
+ if (sc.ch == '_' && (
+ sc.currentPos == 0 || !IsAlNum(sc.chPrev))) {
+ char keyword[50];
+ memset(keyword, '\0', 50);
+
+ for(
+ int scanPosition = 0;
+ scanPosition < 50;
+ scanPosition++) {
+ char keywordChar = static_cast<char>(
+ tolower(styler.SafeGetCharAt(
+ scanPosition +
+ static_cast<int>(sc.currentPos+1), ' ')));
+ if(IsAlpha(keywordChar)) {
+ keyword[scanPosition] = keywordChar;
+ } else {
+ break;
+ }
+ }
+
+ // It is a pragma
+ if(pragmatics.InList(keyword)) {
+ sc.SetState(SCE_MAGIK_PRAGMA);
+ }
+
+ // it is a normal keyword like _local, _self, etc.
+ else if(keywords.InList(keyword)) {
+ sc.SetState(SCE_MAGIK_KEYWORD);
+ }
+
+ // It is a container keyword, such as _method, _proc, etc.
+ else if(containers.InList(keyword)) {
+ sc.SetState(SCE_MAGIK_CONTAINER);
+ }
+
+ // It is a flow keyword, such as _for, _if, _try, etc.
+ else if(flow.InList(keyword)) {
+ sc.SetState(SCE_MAGIK_FLOW);
+ }
+
+ // Interpret as unknown keyword
+ else {
+ sc.SetState(SCE_MAGIK_UNKNOWN_KEYWORD);
+ }
+ }
+
+ // Symbolic expression
+ else if(sc.ch == ':' && !IsAlNum(sc.chPrev)) {
+ sc.SetState(SCE_MAGIK_SYMBOL);
+ bool firstTrip = true;
+ for(sc.Forward(); sc.More(); sc.Forward()) {
+ if(firstTrip && IsAlphaSym(sc.ch));
+ else if(!firstTrip && IsAlNumSym(sc.ch));
+ else if(sc.ch == '|') {
+ for(sc.Forward();
+ sc.More() && sc.ch != '|';
+ sc.Forward());
+ }
+ else break;
+
+ firstTrip = false;
+ }
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ // Identifier (label) expression
+ else if(sc.ch == '@') {
+ sc.SetState(SCE_MAGIK_IDENTIFIER);
+ bool firstTrip = true;
+ for(sc.Forward(); sc.More(); sc.Forward()) {
+ if(firstTrip && IsAlphaCore(sc.ch)) {
+ firstTrip = false;
+ }
+ else if(!firstTrip && IsAlpha(sc.ch));
+ else break;
+ }
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ // Start of a character
+ else if(sc.ch == '%') {
+ sc.SetState(SCE_MAGIK_CHARACTER);
+ sc.Forward();
+ char keyword[50];
+ memset(keyword, '\0', 50);
+
+ for(
+ int scanPosition = 0;
+ scanPosition < 50;
+ scanPosition++) {
+ char keywordChar = static_cast<char>(
+ tolower(styler.SafeGetCharAt(
+ scanPosition +
+ static_cast<int>(sc.currentPos), ' ')));
+ if(IsAlpha(keywordChar)) {
+ keyword[scanPosition] = keywordChar;
+ } else {
+ break;
+ }
+ }
+
+ if(characters.InList(keyword)) {
+ sc.Forward(strlen(keyword));
+ } else {
+ sc.Forward();
+ }
+
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ // Operators
+ else if(
+ sc.ch == '>' ||
+ sc.ch == '<' ||
+ sc.ch == '.' ||
+ sc.ch == ',' ||
+ sc.ch == '+' ||
+ sc.ch == '-' ||
+ sc.ch == '/' ||
+ sc.ch == '*' ||
+ sc.ch == '~' ||
+ sc.ch == '$' ||
+ sc.ch == '=') {
+ sc.SetState(SCE_MAGIK_OPERATOR);
+ }
+
+ // Braces
+ else if(sc.ch == '(' || sc.ch == ')') {
+ sc.SetState(SCE_MAGIK_BRACE_BLOCK);
+ }
+
+ // Brackets
+ else if(sc.ch == '{' || sc.ch == '}') {
+ sc.SetState(SCE_MAGIK_BRACKET_BLOCK);
+ }
+
+ // Square Brackets
+ else if(sc.ch == '[' || sc.ch == ']') {
+ sc.SetState(SCE_MAGIK_SQBRACKET_BLOCK);
+ }
+
+
+ }
+
+ // It is an operator
+ else if(
+ sc.state == SCE_MAGIK_OPERATOR ||
+ sc.state == SCE_MAGIK_BRACE_BLOCK ||
+ sc.state == SCE_MAGIK_BRACKET_BLOCK ||
+ sc.state == SCE_MAGIK_SQBRACKET_BLOCK) {
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+
+ // It is the pragma state
+ else if(sc.state == SCE_MAGIK_PRAGMA) {
+ if(!IsAlpha(sc.ch)) {
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+ }
+
+ // It is the keyword state
+ else if(
+ sc.state == SCE_MAGIK_KEYWORD ||
+ sc.state == SCE_MAGIK_CONTAINER ||
+ sc.state == SCE_MAGIK_FLOW ||
+ sc.state == SCE_MAGIK_UNKNOWN_KEYWORD) {
+ if(!IsAlpha(sc.ch)) {
+ sc.SetState(SCE_MAGIK_DEFAULT);
+ goto repeat;
+ }
+ }
+ }
+
+ sc.Complete();
+}
+
+/**
+ * The word list description
+ */
+static const char * const magikWordListDesc[] = {
+ "Accessors (local, global, self, super, thisthread)",
+ "Pragmatic (pragma, private)",
+ "Containers (method, block, proc)",
+ "Flow (if, then, elif, else)",
+ "Characters (space, tab, newline, return)",
+ "Fold Containers (method, proc, block, if, loop)",
+ 0};
+
+/**
+ * This function detects keywords which are able to have a body. Note that it
+ * uses the Fold Containers word description, not the containers description. It
+ * only works when the style at that particular position is set on Containers
+ * or Flow (number 3 or 4).
+ *
+ * \param keywordslist The list of keywords that are scanned, they should only
+ * contain the start keywords, not the end keywords
+ * \param The actual keyword
+ * \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword
+ * 0 otherwise
+ */
+static inline int IsFoldingContainer(WordList &keywordslist, char * keyword) {
+ if(
+ strlen(keyword) > 3 &&
+ keyword[0] == 'e' && keyword[1] == 'n' && keyword[2] == 'd') {
+ if (keywordslist.InList(keyword + 3)) {
+ return -1;
+ }
+
+ } else {
+ if(keywordslist.InList(keyword)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * The folding function
+ *
+ * \param startPos Where to start scanning
+ * \param length Where to scan to
+ * \param keywordslists The keywordslists, currently, number 5 is used
+ * \param styler The styler
+ */
+static void FoldMagikDoc(unsigned int startPos, int length, int,
+ WordList *keywordslists[], Accessor &styler) {
+
+ bool compact = styler.GetPropertyInt("fold.compact") != 0;
+
+ WordList &foldingElements = *keywordslists[5];
+ int endPos = startPos + length;
+ int line = styler.GetLine(startPos);
+ int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
+ int flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;
+
+ for(
+ int currentPos = startPos;
+ currentPos < endPos;
+ currentPos++) {
+ char currentState = styler.StyleAt(currentPos);
+ char c = styler.SafeGetCharAt(currentPos, ' ');
+ int prevLine = styler.GetLine(currentPos - 1);
+ line = styler.GetLine(currentPos);
+
+ // Default situation
+ if(prevLine < line) {
+ styler.SetLevel(line, (level|flags) & ~SC_FOLDLEVELHEADERFLAG);
+ flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;
+ }
+
+ if(
+ (
+ currentState == SCE_MAGIK_CONTAINER ||
+ currentState == SCE_MAGIK_FLOW
+ ) &&
+ c == '_') {
+
+ char keyword[50];
+ memset(keyword, '\0', 50);
+
+ for(
+ int scanPosition = 0;
+ scanPosition < 50;
+ scanPosition++) {
+ char keywordChar = static_cast<char>(
+ tolower(styler.SafeGetCharAt(
+ scanPosition +
+ currentPos + 1, ' ')));
+ if(IsAlpha(keywordChar)) {
+ keyword[scanPosition] = keywordChar;
+ } else {
+ break;
+ }
+ }
+
+ if(IsFoldingContainer(foldingElements, keyword) > 0) {
+ styler.SetLevel(
+ line,
+ styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
+ level++;
+ } else if(IsFoldingContainer(foldingElements, keyword) < 0) {
+ styler.SetLevel(line, styler.LevelAt(line));
+ level--;
+ }
+ }
+
+ if(
+ compact && (
+ currentState == SCE_MAGIK_BRACE_BLOCK ||
+ currentState == SCE_MAGIK_BRACKET_BLOCK ||
+ currentState == SCE_MAGIK_SQBRACKET_BLOCK)) {
+ if(c == '{' || c == '[' || c == '(') {
+ styler.SetLevel(
+ line,
+ styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
+ level++;
+ } else if(c == '}' || c == ']' || c == ')') {
+ styler.SetLevel(line, styler.LevelAt(line));
+ level--;
+ }
+ }
+ }
+
+}
+
+/**
+ * Injecting the module
+ */
+LexerModule lmMagikSF(
+ SCLEX_MAGIK, ColouriseMagikDoc, "magiksf", FoldMagikDoc, magikWordListDesc);
+
diff --git a/scintilla/src/LexMarkdown.cxx b/scintilla/src/LexMarkdown.cxx
new file mode 100644
index 0000000..9e69b31
--- /dev/null
+++ b/scintilla/src/LexMarkdown.cxx
@@ -0,0 +1,412 @@
+/******************************************************************
+ * LexMarkdown.cxx
+ *
+ * A simple Markdown lexer for scintilla.
+ *
+ * Includes highlighting for some extra features from the
+ * Pandoc implementation; strikeout, using '#.' as a default
+ * ordered list item marker, and delimited code blocks.
+ *
+ * Limitations:
+ *
+ * Standard indented code blocks are not highlighted at all,
+ * as it would conflict with other indentation schemes. Use
+ * delimited code blocks for blanket highlighting of an
+ * entire code block. Embedded HTML is not highlighted either.
+ * Blanket HTML highlighting has issues, because some Markdown
+ * implementations allow Markdown markup inside of the HTML. Also,
+ * there is a following blank line issue that can't be ignored,
+ * explained in the next paragraph. Embedded HTML and code
+ * blocks would be better supported with language specific
+ * highlighting.
+ *
+ * The highlighting aims to accurately reflect correct syntax,
+ * but a few restrictions are relaxed. Delimited code blocks are
+ * highlighted, even if the line following the code block is not blank.
+ * Requiring a blank line after a block, breaks the highlighting
+ * in certain cases, because of the way Scintilla ends up calling
+ * the lexer.
+ *
+ * Written by Jon Strait - jstrait@moonloop.net
+ *
+ * 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsNewline(const int ch) {
+ return (ch == '\n' || ch == '\r');
+}
+
+// True if can follow ch down to the end with possibly trailing whitespace
+static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) {
+ unsigned int i = 0;
+ while (sc.GetRelative(++i) == ch)
+ ;
+ // Skip over whitespace
+ while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
+ ++i;
+ if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
+ sc.Forward(i);
+ sc.ChangeState(state);
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ return true;
+ }
+ else return false;
+}
+
+// Set the state on text section from current to length characters,
+// then set the rest until the newline to default, except for any characters matching token
+static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) {
+ sc.SetState(state);
+ sc.Forward(length);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ sc.Forward();
+ bool started = false;
+ while (sc.More() && !IsNewline(sc.ch)) {
+ if (sc.ch == token && !started) {
+ sc.SetState(state);
+ started = true;
+ }
+ else if (sc.ch != token) {
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ started = false;
+ }
+ sc.Forward();
+ }
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+}
+
+// Does the previous line have more than spaces and tabs?
+static bool HasPrevLineContent(StyleContext &sc) {
+ int i = 0;
+ // Go back to the previous newline
+ while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i)))
+ ;
+ while (--i + sc.currentPos) {
+ if (IsNewline(sc.GetRelative(i)))
+ break;
+ if (!IsASpaceOrTab(sc.GetRelative(i)))
+ return true;
+ }
+ return false;
+}
+
+static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) {
+ int c, count = 1;
+ unsigned int i = 0;
+ while (++i) {
+ c = sc.GetRelative(i);
+ if (c == sc.ch)
+ ++count;
+ // hit a terminating character
+ else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) {
+ // Are we a valid HRULE
+ if ((IsNewline(c) || sc.currentPos + i == endPos) &&
+ count >= 3 && !HasPrevLineContent(sc)) {
+ sc.SetState(SCE_MARKDOWN_HRULE);
+ sc.Forward(i);
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ return true;
+ }
+ else {
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle,
+ WordList **, Accessor &styler) {
+ unsigned int endPos = startPos + length;
+ int precharCount = 0;
+ // Don't advance on a new loop iteration and retry at the same position.
+ // Useful in the corner case of having to start at the beginning file position
+ // in the default state.
+ bool freezeCursor = false;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ while (sc.More()) {
+ // Skip past escaped characters
+ if (sc.ch == '\\') {
+ sc.Forward();
+ continue;
+ }
+
+ // A blockquotes resets the line semantics
+ if (sc.state == SCE_MARKDOWN_BLOCKQUOTE)
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+
+ // Conditional state-based actions
+ if (sc.state == SCE_MARKDOWN_CODE2) {
+ if (sc.Match("``") && sc.GetRelative(-2) != ' ') {
+ sc.Forward(2);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_MARKDOWN_CODE) {
+ if (sc.ch == '`' && sc.chPrev != ' ')
+ sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
+ }
+ /* De-activated because it gets in the way of other valid indentation
+ * schemes, for example multiple paragraphs inside a list item.
+ // Code block
+ else if (sc.state == SCE_MARKDOWN_CODEBK) {
+ bool d = true;
+ if (IsNewline(sc.ch)) {
+ if (sc.chNext != '\t') {
+ for (int c = 1; c < 5; ++c) {
+ if (sc.GetRelative(c) != ' ')
+ d = false;
+ }
+ }
+ }
+ else if (sc.atLineStart) {
+ if (sc.ch != '\t' ) {
+ for (int i = 0; i < 4; ++i) {
+ if (sc.GetRelative(i) != ' ')
+ d = false;
+ }
+ }
+ }
+ if (!d)
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ }
+ */
+ // Strong
+ else if (sc.state == SCE_MARKDOWN_STRONG1) {
+ if (sc.Match("**") && sc.chPrev != ' ') {
+ sc.Forward(2);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_MARKDOWN_STRONG2) {
+ if (sc.Match("__") && sc.chPrev != ' ') {
+ sc.Forward(2);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ // Emphasis
+ else if (sc.state == SCE_MARKDOWN_EM1) {
+ if (sc.ch == '*' && sc.chPrev != ' ')
+ sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
+ }
+ else if (sc.state == SCE_MARKDOWN_EM2) {
+ if (sc.ch == '_' && sc.chPrev != ' ')
+ sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
+ }
+ else if (sc.state == SCE_MARKDOWN_CODEBK) {
+ if (sc.atLineStart && sc.Match("~~~")) {
+ int i = 1;
+ while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos)
+ i++;
+ sc.Forward(i);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_MARKDOWN_STRIKEOUT) {
+ if (sc.Match("~~") && sc.chPrev != ' ') {
+ sc.Forward(2);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) {
+ // Header
+ if (sc.Match("######"))
+ SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc);
+ else if (sc.Match("#####"))
+ SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc);
+ else if (sc.Match("####"))
+ SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc);
+ else if (sc.Match("###"))
+ SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc);
+ else if (sc.Match("##"))
+ SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc);
+ else if (sc.Match("#")) {
+ // Catch the special case of an unordered list
+ if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
+ precharCount = 0;
+ sc.SetState(SCE_MARKDOWN_PRECHAR);
+ }
+ else
+ SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc);
+ }
+ // Code block
+ else if (sc.Match("~~~")) {
+ if (!HasPrevLineContent(sc))
+ sc.SetState(SCE_MARKDOWN_CODEBK);
+ else
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ else if (sc.ch == '=') {
+ if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc))
+ ;
+ else
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ else if (sc.ch == '-') {
+ if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc))
+ ;
+ else {
+ precharCount = 0;
+ sc.SetState(SCE_MARKDOWN_PRECHAR);
+ }
+ }
+ else if (IsNewline(sc.ch))
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ else {
+ precharCount = 0;
+ sc.SetState(SCE_MARKDOWN_PRECHAR);
+ }
+ }
+
+ // The header lasts until the newline
+ else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 ||
+ sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 ||
+ sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) {
+ if (IsNewline(sc.ch))
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ }
+
+ // New state only within the initial whitespace
+ if (sc.state == SCE_MARKDOWN_PRECHAR) {
+ // Blockquote
+ if (sc.ch == '>' && precharCount < 5)
+ sc.SetState(SCE_MARKDOWN_BLOCKQUOTE);
+ /*
+ // Begin of code block
+ else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4))
+ sc.SetState(SCE_MARKDOWN_CODEBK);
+ */
+ // HRule - Total of three or more hyphens, asterisks, or underscores
+ // on a line by themselves
+ else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc))
+ ;
+ // Unordered list
+ else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '+') && IsASpaceOrTab(sc.chNext)) {
+ sc.SetState(SCE_MARKDOWN_ULIST_ITEM);
+ sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
+ }
+ // Ordered list
+ else if (IsADigit(sc.ch)) {
+ int digitCount = 0;
+ while (IsADigit(sc.GetRelative(++digitCount)))
+ ;
+ if (sc.GetRelative(digitCount) == '.' &&
+ IsASpaceOrTab(sc.GetRelative(digitCount + 1))) {
+ sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
+ sc.Forward(digitCount + 1);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ // Alternate Ordered list
+ else if (sc.ch == '#' && sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
+ sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
+ sc.Forward(2);
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ }
+ else if (sc.ch != ' ' || precharCount > 2)
+ sc.SetState(SCE_MARKDOWN_DEFAULT);
+ else
+ ++precharCount;
+ }
+
+ // New state anywhere in doc
+ if (sc.state == SCE_MARKDOWN_DEFAULT) {
+ if (sc.atLineStart && sc.ch == '#') {
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ freezeCursor = true;
+ }
+ // Links and Images
+ if (sc.Match("![") || sc.ch == '[') {
+ int i = 0, j = 0, k = 0;
+ int len = endPos - sc.currentPos;
+ while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
+ ;
+ if (sc.GetRelative(i) == ']') {
+ j = i;
+ if (sc.GetRelative(++i) == '(') {
+ while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\'))
+ ;
+ if (sc.GetRelative(i) == ')')
+ k = i;
+ }
+ else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') {
+ while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
+ ;
+ if (sc.GetRelative(i) == ']')
+ k = i;
+ }
+ }
+ // At least a link text
+ if (j) {
+ sc.SetState(SCE_MARKDOWN_LINK);
+ sc.Forward(j);
+ // Also has a URL or reference portion
+ if (k)
+ sc.Forward(k - j);
+ sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
+ }
+ }
+ // Code - also a special case for alternate inside spacing
+ if (sc.Match("``") && sc.GetRelative(3) != ' ') {
+ sc.SetState(SCE_MARKDOWN_CODE2);
+ sc.Forward();
+ }
+ else if (sc.ch == '`' && sc.chNext != ' ') {
+ sc.SetState(SCE_MARKDOWN_CODE);
+ }
+ // Strong
+ else if (sc.Match("**") && sc.GetRelative(2) != ' ') {
+ sc.SetState(SCE_MARKDOWN_STRONG1);
+ sc.Forward();
+ }
+ else if (sc.Match("__") && sc.GetRelative(2) != ' ') {
+ sc.SetState(SCE_MARKDOWN_STRONG2);
+ sc.Forward();
+ }
+ // Emphasis
+ else if (sc.ch == '*' && sc.chNext != ' ')
+ sc.SetState(SCE_MARKDOWN_EM1);
+ else if (sc.ch == '_' && sc.chNext != ' ')
+ sc.SetState(SCE_MARKDOWN_EM2);
+ // Strikeout
+ else if (sc.Match("~~") && sc.GetRelative(2) != ' ') {
+ sc.SetState(SCE_MARKDOWN_STRIKEOUT);
+ sc.Forward();
+ }
+ // Beginning of line
+ else if (IsNewline(sc.ch))
+ sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
+ }
+ // Advance if not holding back the cursor for this iteration.
+ if (!freezeCursor)
+ sc.Forward();
+ freezeCursor = false;
+ }
+ sc.Complete();
+}
+
+LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown");
diff --git a/scintilla/src/LexMatlab.cxx b/scintilla/src/LexMatlab.cxx
new file mode 100644
index 0000000..73e093e
--- /dev/null
+++ b/scintilla/src/LexMatlab.cxx
@@ -0,0 +1,236 @@
+// Scintilla source code edit control
+/** @file LexMatlab.cxx
+ ** Lexer for Matlab.
+ ** Written by José Fonseca
+ **
+ ** Changes by Christoph Dalitz 2003/12/04:
+ ** - added support for Octave
+ ** - Strings can now be included both in single or double quotes
+ **/
+// Copyright 1998-2001 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static bool IsMatlabCommentChar(int c) {
+ return (c == '%') ;
+}
+
+static bool IsOctaveCommentChar(int c) {
+ return (c == '%' || c == '#') ;
+}
+
+static bool IsMatlabComment(Accessor &styler, int pos, int len) {
+ return len > 0 && IsMatlabCommentChar(styler[pos]) ;
+}
+
+static bool IsOctaveComment(Accessor &styler, int pos, int len) {
+ return len > 0 && IsOctaveCommentChar(styler[pos]) ;
+}
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static void ColouriseMatlabOctaveDoc(
+ unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler,
+ bool (*IsCommentChar)(int)) {
+
+ WordList &keywords = *keywordlists[0];
+
+ styler.StartAt(startPos);
+
+ bool transpose = false;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_MATLAB_OPERATOR) {
+ if (sc.chPrev == '.') {
+ if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
+ sc.ForwardSetState(SCE_MATLAB_DEFAULT);
+ transpose = false;
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_MATLAB_DEFAULT);
+ transpose = true;
+ } else {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ }
+ } else {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ }
+ } else if (sc.state == SCE_MATLAB_KEYWORD) {
+ if (!isalnum(sc.ch) && sc.ch != '_') {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ transpose = false;
+ } else {
+ sc.ChangeState(SCE_MATLAB_IDENTIFIER);
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ transpose = true;
+ }
+ }
+ } else if (sc.state == SCE_MATLAB_NUMBER) {
+ if (!isdigit(sc.ch) && sc.ch != '.'
+ && !(sc.ch == 'e' || sc.ch == 'E')
+ && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ transpose = true;
+ }
+ } else if (sc.state == SCE_MATLAB_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_MATLAB_DEFAULT);
+ }
+ } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_MATLAB_DEFAULT);
+ }
+ } else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ transpose = false;
+ }
+ }
+
+ if (sc.state == SCE_MATLAB_DEFAULT) {
+ if (IsCommentChar(sc.ch)) {
+ sc.SetState(SCE_MATLAB_COMMENT);
+ } else if (sc.ch == '!' && sc.chNext != '=' ) {
+ sc.SetState(SCE_MATLAB_COMMAND);
+ } else if (sc.ch == '\'') {
+ if (transpose) {
+ sc.SetState(SCE_MATLAB_OPERATOR);
+ } else {
+ sc.SetState(SCE_MATLAB_STRING);
+ }
+ } else if (sc.ch == '"') {
+ sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING);
+ } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
+ sc.SetState(SCE_MATLAB_NUMBER);
+ } else if (isalpha(sc.ch)) {
+ sc.SetState(SCE_MATLAB_KEYWORD);
+ } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
+ if (sc.ch == ')' || sc.ch == ']') {
+ transpose = true;
+ } else {
+ transpose = false;
+ }
+ sc.SetState(SCE_MATLAB_OPERATOR);
+ } else {
+ transpose = false;
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar);
+}
+
+static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar);
+}
+
+static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int,
+ WordList *[], Accessor &styler,
+ bool (*IsComment)(Accessor&, int, int)) {
+
+ 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, IsComment);
+ 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, IsComment);
+ 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, IsComment);
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ }
+ indentCurrent = indentNext;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ }
+ }
+}
+
+static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment);
+}
+
+static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment);
+}
+
+static const char * const matlabWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+static const char * const octaveWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc);
+
+LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc);
diff --git a/scintilla/src/LexMetapost.cxx b/scintilla/src/LexMetapost.cxx
new file mode 100644
index 0000000..ba39125
--- /dev/null
+++ b/scintilla/src/LexMetapost.cxx
@@ -0,0 +1,399 @@
+// Scintilla source code edit control
+
+// File: LexMetapost.cxx - general context conformant metapost coloring scheme
+// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
+// Version: September 28, 2003
+// Modified by instanton: July 10, 2007
+// Folding based on keywordlists[]
+
+// Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// This lexer is derived from the one written for the texwork environment (1999++) which in
+// turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// val SCE_METAPOST_DEFAULT = 0
+// val SCE_METAPOST_SPECIAL = 1
+// val SCE_METAPOST_GROUP = 2
+// val SCE_METAPOST_SYMBOL = 3
+// val SCE_METAPOST_COMMAND = 4
+// val SCE_METAPOST_TEXT = 5
+
+// Definitions in SciTEGlobal.properties:
+//
+// Metapost Highlighting
+//
+// # Default
+// style.metapost.0=fore:#7F7F00
+// # Special
+// style.metapost.1=fore:#007F7F
+// # Group
+// style.metapost.2=fore:#880000
+// # Symbol
+// style.metapost.3=fore:#7F7F00
+// # Command
+// style.metapost.4=fore:#008800
+// # Text
+// style.metapost.5=fore:#000000
+
+// lexer.tex.comment.process=0
+
+// Auxiliary functions:
+
+static inline bool endOfLine(Accessor &styler, unsigned int i) {
+ return
+ (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
+}
+
+static inline bool isMETAPOSTcomment(int ch) {
+ return
+ (ch == '%') ;
+}
+
+static inline bool isMETAPOSTone(int ch) {
+ return
+ (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') ||
+ (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') ||
+ (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ;
+}
+
+static inline bool isMETAPOSTtwo(int ch) {
+ return
+ (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#');
+}
+
+static inline bool isMETAPOSTthree(int ch) {
+ return
+ (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') ||
+ (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') ||
+ (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') ||
+ (ch == '%') ;
+}
+
+static inline bool isMETAPOSTidentifier(int ch) {
+ return
+ ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
+ (ch == '_') ;
+}
+
+static inline bool isMETAPOSTnumber(int ch) {
+ return
+ (ch >= '0') && (ch <= '9') ;
+}
+
+static inline bool isMETAPOSTstring(int ch) {
+ return
+ (ch == '\"') ;
+}
+
+static inline bool isMETAPOSTcolon(int ch) {
+ return
+ (ch == ':') ;
+}
+
+static inline bool isMETAPOSTequal(int ch) {
+ return
+ (ch == '=') ;
+}
+
+static int CheckMETAPOSTInterface(
+ unsigned int startPos,
+ int length,
+ Accessor &styler,
+ int defaultInterface) {
+
+ char lineBuffer[1024] ;
+ unsigned int linePos = 0 ;
+
+ // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)...
+
+ if (styler.SafeGetCharAt(0) == '%') {
+ for (unsigned int i = 0; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
+ if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ lineBuffer[linePos] = '\0';
+ if (strstr(lineBuffer, "interface=none")) {
+ return 0 ;
+ } else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) {
+ return 1 ;
+ } else if (strstr(lineBuffer, "interface=metafun")) {
+ return 2 ;
+ } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
+ // better would be to limit the search to just one line
+ return 2 ;
+ } else {
+ return defaultInterface ;
+ }
+ }
+ }
+ }
+
+ return defaultInterface ;
+}
+
+static void ColouriseMETAPOSTDoc(
+ unsigned int startPos,
+ int length,
+ int,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ styler.StartAt(startPos) ;
+ styler.StartSegment(startPos) ;
+
+ bool processComment = styler.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ;
+ int defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ;
+
+ int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;
+
+ // 0 no keyword highlighting
+ // 1 metapost keyword hightlighting
+ // 2+ metafun keyword hightlighting
+
+ int extraInterface = 0 ;
+
+ if (currentInterface != 0) {
+ extraInterface = currentInterface ;
+ }
+
+ WordList &keywords = *keywordlists[0] ;
+ WordList &keywords2 = *keywordlists[extraInterface-1] ;
+
+ StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ;
+
+ char key[100] ;
+
+ bool inTeX = false ;
+ bool inComment = false ;
+ bool inString = false ;
+ bool inClause = false ;
+
+ bool going = sc.More() ; // needed because of a fuzzy end of file state
+
+ for (; going; sc.Forward()) {
+
+ if (! sc.More()) { going = false ; } // we need to go one behind the end of text
+
+ if (inClause) {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ inClause = false ;
+ }
+
+ if (inComment) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ inTeX = false ;
+ inComment = false ;
+ inClause = false ;
+ inString = false ; // not correct but we want to stimulate one-lines
+ }
+ } else if (inString) {
+ if (isMETAPOSTstring(sc.ch)) {
+ sc.SetState(SCE_METAPOST_SPECIAL) ;
+ sc.ForwardSetState(SCE_METAPOST_TEXT) ;
+ inString = false ;
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ inTeX = false ;
+ inComment = false ;
+ inClause = false ;
+ inString = false ; // not correct but we want to stimulate one-lines
+ }
+ } else {
+ if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) {
+ if (sc.state == SCE_METAPOST_COMMAND) {
+ sc.GetCurrent(key, sizeof(key)) ;
+ if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) {
+ sc.ChangeState(SCE_METAPOST_GROUP) ;
+ inTeX = true ;
+ } else if (inTeX) {
+ if (strcmp(key,"etex") == 0) {
+ sc.ChangeState(SCE_METAPOST_GROUP) ;
+ inTeX = false ;
+ } else {
+ sc.ChangeState(SCE_METAPOST_TEXT) ;
+ }
+ } else {
+ if (keywords && keywords.InList(key)) {
+ sc.ChangeState(SCE_METAPOST_COMMAND) ;
+ } else if (keywords2 && keywords2.InList(key)) {
+ sc.ChangeState(SCE_METAPOST_EXTRA) ;
+ } else {
+ sc.ChangeState(SCE_METAPOST_TEXT) ;
+ }
+ }
+ }
+ }
+ if (isMETAPOSTcomment(sc.ch)) {
+ if (! inTeX) {
+ sc.SetState(SCE_METAPOST_SYMBOL) ;
+ sc.ForwardSetState(SCE_METAPOST_DEFAULT) ;
+ inComment = ! processComment ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTstring(sc.ch)) {
+ if (! inTeX) {
+ sc.SetState(SCE_METAPOST_SPECIAL) ;
+ if (! isMETAPOSTstring(sc.chNext)) {
+ sc.ForwardSetState(SCE_METAPOST_TEXT) ;
+ }
+ inString = true ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTcolon(sc.ch)) {
+ if (! inTeX) {
+ if (! isMETAPOSTequal(sc.chNext)) {
+ sc.SetState(SCE_METAPOST_COMMAND) ;
+ inClause = true ;
+ } else {
+ sc.SetState(SCE_METAPOST_SPECIAL) ;
+ }
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTone(sc.ch)) {
+ if (! inTeX) {
+ sc.SetState(SCE_METAPOST_SPECIAL) ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTtwo(sc.ch)) {
+ if (! inTeX) {
+ sc.SetState(SCE_METAPOST_GROUP) ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTthree(sc.ch)) {
+ if (! inTeX) {
+ sc.SetState(SCE_METAPOST_SYMBOL) ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ } else if (isMETAPOSTidentifier(sc.ch)) {
+ if (sc.state != SCE_METAPOST_COMMAND) {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ sc.ChangeState(SCE_METAPOST_COMMAND) ;
+ }
+ } else if (isMETAPOSTnumber(sc.ch)) {
+ // rather redundant since for the moment we don't handle numbers
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ inTeX = false ;
+ inComment = false ;
+ inClause = false ;
+ inString = false ;
+ } else {
+ sc.SetState(SCE_METAPOST_TEXT) ;
+ }
+ }
+
+ }
+
+ sc.Complete();
+
+}
+
+// Hooks info the system:
+
+static const char * const metapostWordListDesc[] = {
+ "MetaPost",
+ "MetaFun",
+ 0
+} ;
+
+static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) {
+ WordList& keywordsStart=*keywordlists[3];
+ WordList& keywordsStop1=*keywordlists[4];
+
+ if (keywordsStart.InList(s)) {return 1;}
+ else if (keywordsStop1.InList(s)) {return -1;}
+ return 0;
+
+}
+
+static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word)
+{
+ int length=0;
+ char ch=styler.SafeGetCharAt(pos);
+ *word=0;
+
+ while(isMETAPOSTidentifier(ch) && isalpha(ch) && length<100){
+ word[length]=ch;
+ length++;
+ ch=styler.SafeGetCharAt(pos+length);
+ }
+ word[length]=0;
+ return length;
+}
+
+static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler)
+{
+ 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];
+
+ char buffer[100]="";
+
+ for (unsigned int i=startPos; i < endPos; i++) {
+ char ch=chNext;
+ chNext=styler.SafeGetCharAt(i+1);
+ char chPrev=styler.SafeGetCharAt(i-1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if(i==0 || chPrev == '\r' || chPrev=='\n'|| chPrev==' '|| chPrev=='(' || chPrev=='$')
+ {
+ ParseMetapostWord(i, styler, buffer);
+ levelCurrent += classifyFoldPointMetapost(buffer,keywordlists);
+ }
+
+ 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);
+
+}
+
+
+LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", FoldMetapostDoc, metapostWordListDesc);
diff --git a/scintilla/src/LexMySQL.cxx b/scintilla/src/LexMySQL.cxx
new file mode 100644
index 0000000..767cdfb
--- /dev/null
+++ b/scintilla/src/LexMySQL.cxx
@@ -0,0 +1,518 @@
+/**
+ * Scintilla source code edit control
+ * @file LexMySQL.cxx
+ * Lexer for MySQL
+ *
+ * Improved by Mike Lischke <mike.lischke@sun.com>
+ * Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
+ * Original work by Neil Hodgson <neilh@scintilla.org>
+ * Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
+ * 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+ return (ch < 0x80) && (isalpha(ch) || ch == '_');
+}
+
+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 == '+');
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Check if the current content context represent a keyword and set the context state if so.
+ */
+static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[])
+{
+ int length = sc.LengthCurrent() + 1; // +1 for the next char
+ char* s = new char[length];
+ sc.GetCurrentLowered(s, length);
+ if (keywordlists[0]->InList(s))
+ sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
+ else
+ if (keywordlists[1]->InList(s))
+ sc.ChangeState(SCE_MYSQL_KEYWORD);
+ else
+ if (keywordlists[2]->InList(s))
+ sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
+ else
+ if (keywordlists[3]->InList(s))
+ sc.ChangeState(SCE_MYSQL_FUNCTION);
+ else
+ if (keywordlists[5]->InList(s))
+ sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
+ else
+ if (keywordlists[6]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER1);
+ else
+ if (keywordlists[7]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER2);
+ else
+ if (keywordlists[8]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER3);
+ delete [] s;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+ // Determine if the current state should terminate.
+ switch (sc.state)
+ {
+ case SCE_MYSQL_OPERATOR:
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_NUMBER:
+ // We stop the number definition on non-numerical non-dot non-eE non-sign char.
+ if (!IsANumberChar(sc.ch))
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_IDENTIFIER:
+ // Switch from identifier to keyword state and open a new state for the new char.
+ if (!IsAWordChar(sc.ch))
+ {
+ CheckForKeyword(sc, keywordlists);
+
+ // Additional check for function keywords needed.
+ // A function name must be followed by an opening parenthesis.
+ if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
+ sc.ChangeState(SCE_MYSQL_DEFAULT);
+
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_VARIABLE:
+ if (!IsAWordChar(sc.ch))
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_SYSTEMVARIABLE:
+ if (!IsAWordChar(sc.ch))
+ {
+ int length = sc.LengthCurrent() + 1;
+ char* s = new char[length];
+ sc.GetCurrentLowered(s, length);
+
+ // Check for known system variables here.
+ if (keywordlists[4]->InList(&s[2]))
+ sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
+ delete [] s;
+
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_QUOTEDIDENTIFIER:
+ if (sc.ch == '`')
+ {
+ if (sc.chNext == '`')
+ sc.Forward(); // Ignore it
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_COMMENT:
+ case SCE_MYSQL_HIDDENCOMMAND:
+ if (sc.Match('*', '/'))
+ {
+ sc.Forward();
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_COMMENTLINE:
+ if (sc.atLineStart)
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_SQSTRING:
+ if (sc.ch == '\\')
+ sc.Forward(); // Escape sequence
+ else
+ if (sc.ch == '\'')
+ {
+ // End of single quoted string reached?
+ if (sc.chNext == '\'')
+ sc.Forward();
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_DQSTRING:
+ if (sc.ch == '\\')
+ sc.Forward(); // Escape sequence
+ else
+ if (sc.ch == '\"')
+ {
+ // End of single quoted string reached?
+ if (sc.chNext == '\"')
+ sc.Forward();
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_MYSQL_DEFAULT)
+ {
+ switch (sc.ch)
+ {
+ case '@':
+ if (sc.chNext == '@')
+ {
+ sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
+ sc.Forward(2); // Skip past @@.
+ }
+ else
+ if (IsAWordStart(sc.ch))
+ {
+ sc.SetState(SCE_MYSQL_VARIABLE);
+ sc.Forward(); // Skip past @.
+ }
+ else
+ sc.SetState(SCE_MYSQL_OPERATOR);
+ break;
+ case '`':
+ sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
+ break;
+ case '#':
+ sc.SetState(SCE_MYSQL_COMMENTLINE);
+ break;
+ case '\'':
+ sc.SetState(SCE_MYSQL_SQSTRING);
+ break;
+ case '\"':
+ sc.SetState(SCE_MYSQL_DQSTRING);
+ break;
+ default:
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
+ sc.SetState(SCE_MYSQL_NUMBER);
+ else
+ if (IsAWordStart(sc.ch))
+ sc.SetState(SCE_MYSQL_IDENTIFIER);
+ else
+ if (sc.Match('/', '*'))
+ {
+ sc.SetState(SCE_MYSQL_COMMENT);
+
+ // Skip comment introducer and check for hidden command.
+ sc.Forward(2);
+ if (sc.ch == '!')
+ {
+ sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
+ sc.Forward();
+ }
+ }
+ else
+ if (sc.Match("--"))
+ {
+ // Special MySQL single line comment.
+ sc.SetState(SCE_MYSQL_COMMENTLINE);
+ sc.Forward(2);
+
+ // Check the third character too. It must be a space or EOL.
+ if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r')
+ sc.ChangeState(SCE_MYSQL_OPERATOR);
+ }
+ else
+ if (isoperator(static_cast<char>(sc.ch)))
+ sc.SetState(SCE_MYSQL_OPERATOR);
+ }
+ }
+ }
+
+ // Do a final check for keywords if we currently have an identifier, to highlight them
+ // also at the end of a line.
+ if (sc.state == SCE_MYSQL_IDENTIFIER)
+ {
+ CheckForKeyword(sc, keywordlists);
+
+ // Additional check for function keywords needed.
+ // A function name must be followed by an opening parenthesis.
+ if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
+ sc.ChangeState(SCE_MYSQL_DEFAULT);
+ }
+
+ sc.Complete();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper function to determine if we have a foldable comment currently.
+ */
+static bool IsStreamCommentStyle(int style)
+{
+ return style == SCE_MYSQL_COMMENT;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Code copied from StyleContext and modified to work here. Should go into Accessor as a
+ * companion to Match()...
+ */
+bool MatchIgnoreCase(Accessor &styler, int currentPos, const char *s)
+{
+ for (int n = 0; *s; n++)
+ {
+ if (*s != tolower(styler.SafeGetCharAt(currentPos + n)))
+ return false;
+ s++;
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+// 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 FoldMySQLDoc(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;
+ bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0;
+
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
+ int levelNext = levelCurrent;
+
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+
+ bool endFound = false;
+ bool whenFound = false;
+ bool elseFound = false;
+
+ char nextChar = styler.SafeGetCharAt(startPos);
+ for (unsigned int i = startPos; length > 0; i++, length--)
+ {
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+
+ char currentChar = nextChar;
+ nextChar = styler.SafeGetCharAt(i + 1);
+ bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n');
+
+ switch (style)
+ {
+ case SCE_MYSQL_COMMENT:
+ if (foldComment)
+ {
+ // Multiline comment style /* .. */.
+ if (IsStreamCommentStyle(style))
+ {
+ // Increase level if we just start a foldable comment.
+ if (!IsStreamCommentStyle(stylePrev))
+ levelNext++;
+ else
+ // If we are in the middle of a foldable comment check if it ends now.
+ // Don't end at the line end, though.
+ if (!IsStreamCommentStyle(styleNext) && !atEOL)
+ levelNext--;
+ }
+ }
+ break;
+ case SCE_MYSQL_COMMENTLINE:
+ if (foldComment)
+ {
+ // Not really a standard, but we add support for single line comments
+ // with special curly braces syntax as foldable comments too.
+ // MySQL needs -- comments to be followed by space or control char
+ if (styler.Match(i, "--"))
+ {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ char chNext3 = styler.SafeGetCharAt(i + 3);
+ if (chNext2 == '{' || chNext3 == '{')
+ levelNext++;
+ else
+ if (chNext2 == '}' || chNext3 == '}')
+ levelNext--;
+ }
+ }
+ break;
+ case SCE_MYSQL_HIDDENCOMMAND:
+ if (style != stylePrev)
+ levelNext++;
+ else
+ if (style != styleNext)
+ levelNext--;
+ break;
+ case SCE_MYSQL_OPERATOR:
+ if (currentChar == '(')
+ levelNext++;
+ else
+ if (currentChar == ')')
+ levelNext--;
+ break;
+ case SCE_MYSQL_MAJORKEYWORD:
+ case SCE_MYSQL_KEYWORD:
+ case SCE_MYSQL_FUNCTION:
+ case SCE_MYSQL_PROCEDUREKEYWORD:
+ // Reserved and other keywords.
+ if (style != stylePrev)
+ {
+ bool beginFound = MatchIgnoreCase(styler, i, "begin");
+ bool ifFound = MatchIgnoreCase(styler, i, "if");
+ bool thenFound = MatchIgnoreCase(styler, i, "then");
+ bool whileFound = MatchIgnoreCase(styler, i, "while");
+ bool loopFound = MatchIgnoreCase(styler, i, "loop");
+ bool repeatFound = MatchIgnoreCase(styler, i, "repeat");
+
+ if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound))
+ {
+ endFound = false;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+
+ // Note that "else" is special here. It may or may not be followed by an "if .. then",
+ // but in any case the level stays the same. When followed by an "if .. then" the level
+ // will be increased later, if not, then at eol.
+ }
+ else
+ if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else"))
+ {
+ levelNext--;
+ elseFound = true;
+ }
+ else
+ if (!foldOnlyBegin && thenFound)
+ {
+ if (whenFound)
+ whenFound = false;
+ else
+ levelNext++;
+ }
+ else
+ if (ifFound)
+ elseFound = false;
+ else
+ if (MatchIgnoreCase(styler, i, "when"))
+ whenFound = true;
+ else
+ {
+ if (beginFound)
+ levelNext++;
+ else
+ if (!foldOnlyBegin && (loopFound || repeatFound || whileFound))
+ {
+ if (endFound)
+ endFound = false;
+ else
+ levelNext++;
+ }
+ else
+ if (MatchIgnoreCase(styler, i, "end"))
+ {
+ // Multiple "end" in a row are counted multiple times!
+ if (endFound)
+ {
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
+ endFound = true;
+ whenFound = false;
+ }
+ }
+ }
+ break;
+ }
+
+ // Handle the case of a trailing end without an if / while etc, as in the case of a begin.
+ if (endFound)
+ {
+ endFound = false;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
+
+ if (atEOL)
+ {
+ if (elseFound)
+ {
+ levelNext++;
+ elseFound = false;
+ }
+
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+
+ lineCurrent++;
+ levelCurrent = levelNext;
+ visibleChars = 0;
+ endFound = false;
+ whenFound = false;
+ }
+
+ if (!isspacechar(currentChar))
+ visibleChars++;
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+static const char * const mysqlWordListDesc[] = {
+ "Major Keywords",
+ "Keywords",
+ "Database Objects",
+ "Functions",
+ "System Variables",
+ "Procedure keywords",
+ "User Keywords 1",
+ "User Keywords 2",
+ "User Keywords 3",
+ 0
+};
+
+LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc);
diff --git a/scintilla/src/LexNimrod.cxx b/scintilla/src/LexNimrod.cxx
new file mode 100644
index 0000000..d798b93
--- /dev/null
+++ b/scintilla/src/LexNimrod.cxx
@@ -0,0 +1,430 @@
+// Scintilla source code edit control
+// Nimrod lexer
+// (c) 2009 Andreas Rumpf
+/** @file LexNimrod.cxx
+ ** Lexer for Nimrod.
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return (ch >= 0x80) || isalnum(ch) || ch == '_';
+}
+
+static int tillEndOfTripleQuote(Accessor &styler, int pos, int max) {
+ /* search for """ */
+ for (;;) {
+ if (styler.SafeGetCharAt(pos, '\0') == '\0') return pos;
+ if (pos >= max) return pos;
+ if (styler.Match(pos, "\"\"\"")) {
+ return pos + 2;
+ }
+ pos++;
+ }
+}
+
+#define CR 13 /* use both because Scite allows changing the line ending */
+#define LF 10
+
+static bool inline isNewLine(int ch) {
+ return ch == CR || ch == LF;
+}
+
+static int scanString(Accessor &styler, int pos, int max, bool rawMode) {
+ for (;;) {
+ if (pos >= max) return pos;
+ char ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == CR || ch == LF || ch == '\0') return pos;
+ if (ch == '"') return pos;
+ if (ch == '\\' && !rawMode) {
+ pos += 2;
+ } else {
+ pos++;
+ }
+ }
+}
+
+static int scanChar(Accessor &styler, int pos, int max) {
+ for (;;) {
+ if (pos >= max) return pos;
+ char ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == CR || ch == LF || ch == '\0') return pos;
+ if (ch == '\'' && !isalnum(styler.SafeGetCharAt(pos+1, '\0')) )
+ return pos;
+ if (ch == '\\') {
+ pos += 2;
+ } else {
+ pos++;
+ }
+ }
+}
+
+static int scanIdent(Accessor &styler, int pos, WordList &keywords) {
+ char buf[100]; /* copy to lowercase and ignore underscores */
+ int i = 0;
+
+ for (;;) {
+ char ch = styler.SafeGetCharAt(pos, '\0');
+ if (!IsAWordChar(ch)) break;
+ if (ch != '_' && i < ((int)sizeof(buf))-1) {
+ buf[i] = static_cast<char>(tolower(ch));
+ i++;
+ }
+ pos++;
+ }
+ buf[i] = '\0';
+ /* look for keyword */
+ if (keywords.InList(buf)) {
+ styler.ColourTo(pos-1, SCE_P_WORD);
+ } else {
+ styler.ColourTo(pos-1, SCE_P_IDENTIFIER);
+ }
+ return pos;
+}
+
+static int scanNumber(Accessor &styler, int pos) {
+ char ch, ch2;
+ ch = styler.SafeGetCharAt(pos, '\0');
+ ch2 = styler.SafeGetCharAt(pos+1, '\0');
+ if (ch == '0' && (ch2 == 'b' || ch2 == 'B')) {
+ /* binary number: */
+ pos += 2;
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos;
+ else break;
+ }
+ } else if (ch == '0' &&
+ (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) {
+ /* octal number: */
+ pos += 2;
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '7')) ++pos;
+ else break;
+ }
+ } else if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) {
+ /* hexadecimal number: */
+ pos += 2;
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '9')
+ || (ch >= 'a' && ch <= 'f')
+ || (ch >= 'A' && ch <= 'F')) ++pos;
+ else break;
+ }
+ } else {
+ // skip decimal part:
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
+ else break;
+ }
+ ch2 = styler.SafeGetCharAt(pos+1, '\0');
+ if (ch == '.' && ch2 >= '0' && ch2 <= '9') {
+ ++pos; // skip '.'
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
+ else break;
+ }
+ }
+ if (ch == 'e' || ch == 'E') {
+ ++pos;
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '-' || ch == '+') ++pos;
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
+ else break;
+ }
+ }
+ }
+ if (ch == '\'') {
+ /* a type suffix: */
+ pos++;
+ for (;;) {
+ ch = styler.SafeGetCharAt(pos);
+ if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z') || ch == '_') ++pos;
+ else break;
+ }
+ }
+ styler.ColourTo(pos-1, SCE_P_NUMBER);
+ return pos;
+}
+
+/* rewritten from scratch, because I couldn't get rid of the bugs...
+ (A character based approach sucks!)
+*/
+static void ColouriseNimrodDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ int pos = startPos;
+ int max = startPos + length;
+ char ch;
+ WordList &keywords = *keywordlists[0];
+
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+
+ switch (initStyle) {
+ /* check where we are: */
+ case SCE_P_TRIPLEDOUBLE:
+ pos = tillEndOfTripleQuote(styler, pos, max);
+ styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
+ pos++;
+ break;
+ default: /* nothing to do: */
+ break;
+ }
+ while (pos < max) {
+ ch = styler.SafeGetCharAt(pos, '\0');
+ switch (ch) {
+ case '\0': return;
+ case '#': {
+ bool doccomment = (styler.SafeGetCharAt(pos+1) == '#');
+ while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++;
+ if (doccomment)
+ styler.ColourTo(pos, SCE_C_COMMENTLINEDOC);
+ else
+ styler.ColourTo(pos, SCE_P_COMMENTLINE);
+ } break;
+ case 'r': case 'R': {
+ if (styler.SafeGetCharAt(pos+1) == '"') {
+ pos = scanString(styler, pos+2, max, true);
+ styler.ColourTo(pos, SCE_P_STRING);
+ pos++;
+ } else {
+ pos = scanIdent(styler, pos, keywords);
+ }
+ } break;
+ case '"':
+ if (styler.Match(pos+1, "\"\"")) {
+ pos = tillEndOfTripleQuote(styler, pos+3, max);
+ styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
+ } else {
+ pos = scanString(styler, pos+1, max, false);
+ styler.ColourTo(pos, SCE_P_STRING);
+ }
+ pos++;
+ break;
+ case '\'':
+ pos = scanChar(styler, pos+1, max);
+ styler.ColourTo(pos, SCE_P_CHARACTER);
+ pos++;
+ break;
+ default: // identifers, numbers, operators, whitespace
+ if (ch >= '0' && ch <= '9') {
+ pos = scanNumber(styler, pos);
+ } else if (IsAWordChar(ch)) {
+ pos = scanIdent(styler, pos, keywords);
+ } else if (ch == '`') {
+ pos++;
+ while (pos < max) {
+ ch = styler.SafeGetCharAt(pos, LF);
+ if (ch == '`') {
+ ++pos;
+ break;
+ }
+ if (ch == CR || ch == LF) break;
+ ++pos;
+ }
+ styler.ColourTo(pos, SCE_P_IDENTIFIER);
+ } else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", ch)) {
+ styler.ColourTo(pos, SCE_P_OPERATOR);
+ pos++;
+ } else {
+ styler.ColourTo(pos, SCE_P_DEFAULT);
+ pos++;
+ }
+ break;
+ }
+ }
+}
+
+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 bool IsQuoteLine(int line, Accessor &styler) {
+ int style = styler.StyleAt(styler.LineStart(line)) & 31;
+ return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
+}
+
+
+static void FoldNimrodDoc(unsigned int startPos, int length,
+ int /*initStyle - unused*/,
+ WordList *[], Accessor &styler) {
+ const int maxPos = startPos + length;
+ const int maxLines = styler.GetLine(maxPos - 1); // Requested last line
+ const int docLines = styler.GetLine(styler.Length() - 1); // Available last line
+ const bool foldComment = styler.GetPropertyInt("fold.comment.nimrod") != 0;
+ const bool foldQuotes = styler.GetPropertyInt("fold.quotes.nimrod") != 0;
+
+ // Backtrack to previous non-blank line so we can determine indent level
+ // for any white space lines (needed esp. within triple quoted strings)
+ // and so we can fix any preceding fold level (which is why we go back
+ // at least one line in all cases)
+ int spaceFlags = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ while (lineCurrent > 0) {
+ lineCurrent--;
+ indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
+ (!IsCommentLine(lineCurrent, styler)) &&
+ (!IsQuoteLine(lineCurrent, styler)))
+ break;
+ }
+ int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+ // Set up initial loop state
+ startPos = styler.LineStart(lineCurrent);
+ int prev_state = SCE_P_DEFAULT & 31;
+ if (lineCurrent >= 1)
+ prev_state = styler.StyleAt(startPos - 1) & 31;
+ int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) ||
+ (prev_state == SCE_P_TRIPLEDOUBLE));
+ int prevComment = 0;
+ if (lineCurrent >= 1)
+ prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
+
+ // Process all characters to end of requested range or end of any triple quote
+ // or comment that hangs over the end of the range. Cap processing in all cases
+ // to end of document (in case of unclosed quote or comment at end).
+ while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) ||
+ prevQuote || prevComment)) {
+
+ // Gather info
+ int lev = indentCurrent;
+ int lineNext = lineCurrent + 1;
+ int indentNext = indentCurrent;
+ int quote = false;
+ if (lineNext <= docLines) {
+ // Information about next line is only available if not at end of document
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ int style = styler.StyleAt(styler.LineStart(lineNext)) & 31;
+ quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
+ }
+ const int quote_start = (quote && !prevQuote);
+ const int quote_continue = (quote && prevQuote);
+ const int comment = foldComment && IsCommentLine(lineCurrent, styler);
+ const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
+ IsCommentLine(lineNext, styler) &&
+ (lev > SC_FOLDLEVELBASE));
+ const int comment_continue = (comment && prevComment);
+ if ((!quote || !prevQuote) && !comment)
+ indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+ if (quote)
+ indentNext = indentCurrentLevel;
+ if (indentNext & SC_FOLDLEVELWHITEFLAG)
+ indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+ if (quote_start) {
+ // Place fold point at start of triple quoted string
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (quote_continue || prevQuote) {
+ // Add level to rest of lines in the string
+ lev = lev + 1;
+ } else if (comment_start) {
+ // Place fold point at start of a block of comments
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (comment_continue) {
+ // Add level to rest of lines in the block
+ lev = lev + 1;
+ }
+
+ // Skip past any blank lines for next indent level info; we skip also
+ // comments (all comments, not just those starting in column 0)
+ // which effectively folds them into surrounding code rather
+ // than screwing up folding.
+
+ while (!quote &&
+ (lineNext < docLines) &&
+ ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
+ (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+
+ lineNext++;
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ }
+
+ const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
+ const int levelBeforeComments =
+ Platform::Maximum(indentCurrentLevel,levelAfterComments);
+
+ // Now set all the indent levels on the lines we skipped
+ // Do this from end to start. Once we encounter one line
+ // which is indented more than the line after the end of
+ // the comment-block, use the level of the block before
+
+ int skipLine = lineNext;
+ int skipLevel = levelAfterComments;
+
+ while (--skipLine > lineCurrent) {
+ int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+ if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
+ skipLevel = levelBeforeComments;
+
+ int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+ styler.SetLevel(skipLine, skipLevel | whiteFlag);
+ }
+
+ // Set fold header on non-quote/non-comment line
+ if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) <
+ (indentNext & SC_FOLDLEVELNUMBERMASK))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+
+ // Keep track of triple quote and block comment state of previous line
+ prevQuote = quote;
+ prevComment = comment_start || comment_continue;
+
+ // Set fold level for this line and move to next line
+ styler.SetLevel(lineCurrent, lev);
+ indentCurrent = indentNext;
+ lineCurrent = lineNext;
+ }
+
+ // NOTE: Cannot set level of last line here because indentCurrent doesn't have
+ // header flag set; the loop above is crafted to take care of this case!
+ //styler.SetLevel(lineCurrent, indentCurrent);
+}
+
+static const char * const nimrodWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmNimrod(SCLEX_NIMROD, ColouriseNimrodDoc, "nimrod", FoldNimrodDoc,
+ nimrodWordListDesc);
diff --git a/scintilla/src/LexNsis.cxx b/scintilla/src/LexNsis.cxx
new file mode 100644
index 0000000..37e4a18
--- /dev/null
+++ b/scintilla/src/LexNsis.cxx
@@ -0,0 +1,655 @@
+// Scintilla source code edit control
+/** @file LexNsis.cxx
+ ** Lexer for NSIS
+ **/
+// 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>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "CharClassify.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+// located in SciLexer.h
+#define SCLEX_NSIS 43
+
+#define SCE_NSIS_DEFAULT 0
+#define SCE_NSIS_COMMENT 1
+#define SCE_NSIS_STRINGDQ 2
+#define SCE_NSIS_STRINGLQ 3
+#define SCE_NSIS_STRINGRQ 4
+#define SCE_NSIS_FUNCTION 5
+#define SCE_NSIS_VARIABLE 6
+#define SCE_NSIS_LABEL 7
+#define SCE_NSIS_USERDEFINED 8
+#define SCE_NSIS_SECTIONDEF 9
+#define SCE_NSIS_SUBSECTIONDEF 10
+#define SCE_NSIS_IFDEFINEDEF 11
+#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)
+{
+ return (ch >= '0' && ch <= '9');
+}
+
+static bool isNsisChar(char ch)
+{
+ return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+}
+
+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 found 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( const char *s1, const char *s2, bool bIgnoreCase )
+{
+ if( bIgnoreCase )
+ return CompareCaseInsensitive( s1, s2);
+
+ return strcmp( s1, s2 );
+}
+
+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 > 20 )
+ 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[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';
+ }
+
+ if( s[0] == '!' )
+ {
+ if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 || NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 )
+ 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, "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, "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;
+}
+
+static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
+{
+ bool bIgnoreCase = false;
+ if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
+ bIgnoreCase = true;
+
+ bool bUserVars = false;
+ if( styler.GetPropertyInt("nsis.uservars") == 1 )
+ bUserVars = true;
+
+ char s[100];
+
+ WordList &Functions = *keywordLists[0];
+ WordList &Variables = *keywordLists[1];
+ WordList &Lables = *keywordLists[2];
+ WordList &UserDefined = *keywordLists[3];
+
+ for (unsigned int i = 0; i < end - start + 1 && i < 99; i++)
+ {
+ if( bIgnoreCase )
+ s[i] = static_cast<char>( tolower(styler[ start + i ] ) );
+ else
+ s[i] = static_cast<char>( styler[ start + i ] );
+ s[i + 1] = '\0';
+ }
+
+ // Check for special words...
+ if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !macro and !macroend
+ return SCE_NSIS_MACRODEF;
+
+ if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) // Covers !ifdef, !ifndef and !endif
+ return SCE_NSIS_IFDEFINEDEF;
+
+ if( NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // Covers !if and else
+ return SCE_NSIS_IFDEFINEDEF;
+
+ if (NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 ) // Covers !ifmacrodef and !ifnmacrodef
+ 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, "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;
+
+ if ( Variables.InList(s) )
+ return SCE_NSIS_VARIABLE;
+
+ if ( Lables.InList(s) )
+ return SCE_NSIS_LABEL;
+
+ if( UserDefined.InList(s) )
+ return SCE_NSIS_USERDEFINED;
+
+ if( strlen(s) > 3 )
+ {
+ if( s[1] == '{' && s[strlen(s)-1] == '}' )
+ return SCE_NSIS_VARIABLE;
+ }
+
+ // See if the variable is a user defined variable
+ if( s[0] == '$' && bUserVars )
+ {
+ bool bHasSimpleNsisChars = true;
+ for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
+ {
+ if( !isNsisChar( s[j] ) )
+ {
+ bHasSimpleNsisChars = false;
+ break;
+ }
+ }
+
+ if( bHasSimpleNsisChars )
+ return SCE_NSIS_VARIABLE;
+ }
+
+ // To check for numbers
+ if( isNsisNumber( s[0] ) )
+ {
+ bool bHasSimpleNsisNumber = true;
+ for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
+ {
+ if( !isNsisNumber( s[j] ) )
+ {
+ bHasSimpleNsisNumber = false;
+ break;
+ }
+ }
+
+ if( bHasSimpleNsisNumber )
+ return SCE_NSIS_NUMBER;
+ }
+
+ return SCE_NSIS_DEFAULT;
+}
+
+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 );
+
+ unsigned int nLengthDoc = startPos + length;
+ styler.StartSegment( startPos );
+
+ char cCurrChar;
+ bool bVarInString = false;
+ bool bClassicVarInString = false;
+
+ unsigned int i;
+ for( i = startPos; i < nLengthDoc; i++ )
+ {
+ cCurrChar = styler.SafeGetCharAt( i );
+ char cNextChar = styler.SafeGetCharAt(i+1);
+
+ switch(state)
+ {
+ case SCE_NSIS_DEFAULT:
+ if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line
+ {
+ styler.ColourTo(i-1, state );
+ state = SCE_NSIS_COMMENT;
+ break;
+ }
+ if( cCurrChar == '"' )
+ {
+ styler.ColourTo(i-1, state );
+ state = SCE_NSIS_STRINGDQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+ if( cCurrChar == '\'' )
+ {
+ styler.ColourTo(i-1, state );
+ state = SCE_NSIS_STRINGRQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+ if( cCurrChar == '`' )
+ {
+ styler.ColourTo(i-1, state );
+ state = SCE_NSIS_STRINGLQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ break;
+ }
+
+ // NSIS KeyWord,Function, Variable, UserDefined:
+ if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' )
+ {
+ styler.ColourTo(i-1,state);
+ state = SCE_NSIS_FUNCTION;
+
+ // If it is a number, we must check and set style here first...
+ if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
+ styler.ColourTo( i, SCE_NSIS_NUMBER);
+
+ break;
+ }
+
+ if( cCurrChar == '/' && cNextChar == '*' )
+ {
+ styler.ColourTo(i-1,state);
+ state = SCE_NSIS_COMMENTBOX;
+ break;
+ }
+
+ break;
+ case SCE_NSIS_COMMENT:
+ if( cNextChar == '\n' || cNextChar == '\r' )
+ {
+ // 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:
+ 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,state);
+ state = SCE_NSIS_DEFAULT;
+ break;
+ }
+
+ if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
+ {
+ styler.ColourTo(i,state);
+ state = SCE_NSIS_DEFAULT;
+ break;
+ }
+
+ if( cCurrChar == '\'' && state == 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:
+ if( cCurrChar == '$' )
+ state = SCE_NSIS_DEFAULT;
+ else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
+ state = SCE_NSIS_DEFAULT;
+ else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
+ {
+ state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
+ styler.ColourTo( i, state);
+ state = SCE_NSIS_DEFAULT;
+ }
+ else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' )
+ {
+ if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER )
+ styler.ColourTo( i-1, SCE_NSIS_NUMBER );
+
+ state = SCE_NSIS_DEFAULT;
+
+ if( cCurrChar == '"' )
+ {
+ state = SCE_NSIS_STRINGDQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if( cCurrChar == '`' )
+ {
+ state = SCE_NSIS_STRINGLQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if( cCurrChar == '\'' )
+ {
+ state = SCE_NSIS_STRINGRQ;
+ bVarInString = false;
+ bClassicVarInString = false;
+ }
+ else if( cCurrChar == '#' || cCurrChar == ';' )
+ {
+ state = SCE_NSIS_COMMENT;
+ }
+ }
+ 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 || state == SCE_NSIS_COMMENTBOX )
+ {
+ styler.ColourTo(i,state);
+ }
+ else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ )
+ {
+ bool bIngoreNextDollarSign = false;
+ bool bUserVars = false;
+ if( styler.GetPropertyInt("nsis.uservars") == 1 )
+ bUserVars = true;
+
+ if( bVarInString && cCurrChar == '$' )
+ {
+ bVarInString = false;
+ bIngoreNextDollarSign = true;
+ }
+ else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
+ {
+ styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
+ bVarInString = false;
+ bIngoreNextDollarSign = false;
+ }
+
+ // Covers "$INSTDIR and user vars like $MYVAR"
+ else if( bVarInString && !isNsisChar(cNextChar) )
+ {
+ int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
+ if( nWordState == SCE_NSIS_VARIABLE )
+ styler.ColourTo( i, SCE_NSIS_STRINGVAR);
+ else if( bUserVars )
+ styler.ColourTo( i, SCE_NSIS_STRINGVAR);
+ bVarInString = false;
+ }
+ // Covers "${TEST}..."
+ else if( bClassicVarInString && cNextChar == '}' )
+ {
+ styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
+ bClassicVarInString = false;
+ }
+
+ // Start of var in string
+ if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' )
+ {
+ styler.ColourTo( i-1, state);
+ bClassicVarInString = true;
+ bVarInString = false;
+ }
+ else if( !bIngoreNextDollarSign && cCurrChar == '$' )
+ {
+ styler.ColourTo( i-1, state);
+ bVarInString = true;
+ bClassicVarInString = false;
+ }
+ }
+ }
+
+ // Colourise remaining document
+ styler.ColourTo(nLengthDoc-1,state);
+}
+
+static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ // No folding enabled, no reason to continue...
+ 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 );
+
+ bool bArg1 = true;
+ int nWordStart = -1;
+
+ int levelCurrent = SC_FOLDLEVELBASE;
+ 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 && !blockComment)
+ {
+ if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
+ {
+ nWordStart = i;
+ }
+ else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
+ {
+ 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;
+ }
+ }
+
+ 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 )
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+
+ lineCurrent++;
+ levelCurrent = levelNext;
+ bArg1 = true; // New line, lets look at first argument again
+ nWordStart = -1;
+ }
+ }
+
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+}
+
+static const char * const nsisWordLists[] = {
+ "Functions",
+ "Variables",
+ "Lables",
+ "UserDefined",
+ 0, };
+
+
+LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);
+
diff --git a/scintilla/src/LexOpal.cxx b/scintilla/src/LexOpal.cxx
new file mode 100644
index 0000000..4cbbeaf
--- /dev/null
+++ b/scintilla/src/LexOpal.cxx
@@ -0,0 +1,522 @@
+// Scintilla source code edit control
+/** @file LexOpal.cxx
+ ** Lexer for OPAL (functional language similar to Haskell)
+ ** Written by Sebastian Pipping <webmaster@hartwork.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 "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "StyleContext.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+inline static void getRange( unsigned int start, unsigned int end, Accessor & styler, char * s, unsigned int len )
+{
+ unsigned int i = 0;
+ while( ( i < end - start + 1 ) && ( i < len - 1 ) )
+ {
+ s[i] = static_cast<char>( styler[ start + i ] );
+ i++;
+ }
+ s[ i ] = '\0';
+}
+
+inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
+{
+ char ch;
+
+ // Wait for string to close
+ bool even_backslash_count = true; // Without gaps in between
+ cur++; // Skip initial quote
+ for( ; ; )
+ {
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_STRING );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( ( ch == '\015' ) || ( ch == '\012' ) ) // Deny multi-line strings
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_STRING );
+ styler.StartSegment( cur );
+ return true;
+ }
+ else
+ {
+ if( even_backslash_count )
+ {
+ if( ch == '"' )
+ {
+ styler.ColourTo( cur, SCE_OPAL_STRING );
+ cur++;
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ else if( ch == '\\' )
+ {
+ even_backslash_count = false;
+ }
+ }
+ else
+ {
+ even_backslash_count = true;
+ }
+ }
+
+ cur++;
+ }
+}
+
+inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
+{
+ char ch;
+
+ if( could_fail )
+ {
+ cur++;
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( ch != '*' )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+
+ // Wait for comment close
+ cur++;
+ bool star_found = false;
+ for( ; ; )
+ {
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( star_found )
+ {
+ if( ch == '/' )
+ {
+ styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK );
+ cur++;
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ else if( ch != '*' )
+ {
+ star_found = false;
+ }
+ }
+ else if( ch == '*' )
+ {
+ star_found = true;
+ }
+ cur++;
+ }
+}
+
+inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
+{
+ char ch;
+
+ if( could_fail )
+ {
+ cur++;
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( ch != '-' )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ styler.StartSegment( cur );
+ return true;
+ }
+
+ cur++;
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( ( ch != ' ' ) && ( ch != '\t' ) )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+
+ // Wait for end of line
+ bool fifteen_found = false;
+
+ for( ; ; )
+ {
+ cur++;
+
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( fifteen_found )
+ {
+/*
+ if( ch == '\012' )
+ {
+ // One newline on Windows (015, 012)
+ }
+ else
+ {
+ // One newline on MAC (015) and another char
+ }
+*/
+ cur--;
+ styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
+ styler.StartSegment( cur );
+ return true;
+ }
+ else
+ {
+ if( ch == '\015' )
+ {
+ fifteen_found = true;
+ }
+ else if( ch == '\012' )
+ {
+ // One newline on Linux (012)
+ styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ }
+}
+
+inline bool HandlePar( unsigned int & cur, Accessor & styler )
+{
+ styler.ColourTo( cur, SCE_OPAL_PAR );
+
+ cur++;
+
+ styler.StartSegment( cur );
+ return true;
+}
+
+inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
+{
+ char ch;
+
+ cur++;
+ for( ; ; )
+ {
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
+ return false;
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ switch( ch )
+ {
+ case ' ':
+ case '\t':
+ case '\015':
+ case '\012':
+ cur++;
+ break;
+
+ default:
+ styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+}
+
+inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
+{
+ char ch;
+
+ for( ; ; )
+ {
+ cur++;
+ if( cur >= one_too_much )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
+ return false; // STOP
+ }
+
+ ch = styler.SafeGetCharAt( cur );
+ if( !( isascii( ch ) && isdigit( ch ) ) )
+ {
+ styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+}
+
+inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] )
+{
+ char ch;
+ const unsigned int beg = cur;
+
+ cur++;
+ for( ; ; )
+ {
+ ch = styler.SafeGetCharAt( cur );
+ if( ( ch != '_' ) && ( ch != '-' ) &&
+ !( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break;
+
+ cur++;
+ if( cur >= one_too_much )
+ {
+ break;
+ }
+ }
+
+ const int ide_len = cur - beg + 1;
+ char * ide = new char[ ide_len ];
+ getRange( beg, cur, styler, ide, ide_len );
+
+ WordList & keywords = *keywordlists[ 0 ];
+ WordList & classwords = *keywordlists[ 1 ];
+
+ if( keywords.InList( ide ) ) // Keyword
+ {
+ delete [] ide;
+
+ styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD );
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ else if( classwords.InList( ide ) ) // Sort
+ {
+ delete [] ide;
+
+ styler.ColourTo( cur - 1, SCE_OPAL_SORT );
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const
+ {
+ delete [] ide;
+
+ styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST );
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+ else // Unknown keyword
+ {
+ delete [] ide;
+
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+ }
+
+}
+
+inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
+{
+ cur++;
+ styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
+ if( cur >= one_too_much )
+ {
+ return false; // STOP
+ }
+ else
+ {
+ styler.StartSegment( cur );
+ return true;
+ }
+}
+
+static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler )
+{
+ styler.StartAt( startPos );
+ styler.StartSegment( startPos );
+
+ unsigned int & cur = startPos;
+ const unsigned int one_too_much = startPos + length;
+
+ int state = initStyle;
+
+ for( ; ; )
+ {
+ switch( state )
+ {
+ case SCE_OPAL_KEYWORD:
+ case SCE_OPAL_SORT:
+ if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;
+ state = SCE_OPAL_DEFAULT;
+ break;
+
+ case SCE_OPAL_INTEGER:
+ if( !HandleInteger( cur, one_too_much, styler ) ) return;
+ state = SCE_OPAL_DEFAULT;
+ break;
+
+ case SCE_OPAL_COMMENT_BLOCK:
+ if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return;
+ state = SCE_OPAL_DEFAULT;
+ break;
+
+ case SCE_OPAL_COMMENT_LINE:
+ if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return;
+ state = SCE_OPAL_DEFAULT;
+ break;
+
+ case SCE_OPAL_STRING:
+ if( !HandleString( cur, one_too_much, styler ) ) return;
+ state = SCE_OPAL_DEFAULT;
+ break;
+
+ default: // SCE_OPAL_DEFAULT:
+ {
+ char ch = styler.SafeGetCharAt( cur );
+
+ switch( ch )
+ {
+ // String
+ case '"':
+ if( !HandleString( cur, one_too_much, styler ) ) return;
+ break;
+
+ // Comment block
+ case '/':
+ if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return;
+ break;
+
+ // Comment line
+ case '-':
+ if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return;
+ break;
+
+ // Par
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ if( !HandlePar( cur, styler ) ) return;
+ break;
+
+ // Whitespace
+ case ' ':
+ case '\t':
+ case '\015':
+ case '\012':
+ if( !HandleSpace( cur, one_too_much, styler ) ) return;
+ break;
+
+ default:
+ {
+ // Integer
+ if( isascii( ch ) && isdigit( ch ) )
+ {
+ if( !HandleInteger( cur, one_too_much, styler ) ) return;
+ }
+
+ // Keyword
+ else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) )
+ {
+ if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;
+
+ }
+
+ // Skip
+ else
+ {
+ if( !HandleSkip( cur, one_too_much, styler ) ) return;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+static const char * const opalWordListDesc[] = {
+ "Keywords",
+ "Sorts",
+ 0
+};
+
+LexerModule lmOpal(SCLEX_OPAL, ColouriseOpalDoc, "opal", NULL, opalWordListDesc);
diff --git a/scintilla/src/LexOthers.cxx b/scintilla/src/LexOthers.cxx
new file mode 100644
index 0000000..c5c6ef2
--- /dev/null
+++ b/scintilla/src/LexOthers.cxx
@@ -0,0 +1,1286 @@
+// Scintilla source code edit control
+/** @file LexOthers.cxx
+ ** Lexers for batch files, diff results, properties files, make files and error lists.
+ ** Also lexer for LaTeX documents.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "CharClassify.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static bool strstart(const char *haystack, const char *needle) {
+ return strncmp(haystack, needle, strlen(needle)) == 0;
+}
+
+static bool Is0To9(char ch) {
+ return (ch >= '0') && (ch <= '9');
+}
+
+static bool Is1To9(char ch) {
+ return (ch >= '1') && (ch <= '9');
+}
+
+static bool IsAlphabetic(int ch) {
+ return isascii(ch) && isalpha(ch);
+}
+
+static inline bool AtEOL(Accessor &styler, unsigned int i) {
+ return (styler[i] == '\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 == ')');
+}
+
+static void ColouriseBatchLine(
+ char *lineBuffer,
+ unsigned int lengthLine,
+ unsigned int startLine,
+ unsigned int endPos,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ unsigned int offset = 0; // Line Buffer Offset
+ 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
+ WordList &keywords = *keywordlists[0]; // Internal Commands
+ WordList &keywords2 = *keywordlists[1]; // External Commands (optional)
+
+ // 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
+
+ // Skip initial spaces
+ while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
+ offset++;
+ }
+ // 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 {
+ // Colorize Real Label
+ styler.ColourTo(endPos, SCE_BAT_LABEL);
+ }
+ return;
+ // Check for Drive Change (Drive Change is internal command) - return if found
+ } else if ((IsAlphabetic(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++;
+ }
+ // 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';
+ wbo = 0;
+
+ // Check for Comment - return if found
+ if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
+ styler.ColourTo(endPos, SCE_BAT_COMMENT);
+ return;
+ }
+ // 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
+ if (!keywords2) {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+ } else if (keywords2.InList(wordBuffer)) {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+ } else {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+ }
+ // 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)) {
+ // 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] != '%') &&
+ (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);
+ }
+ }
+ // 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] != '%') &&
+ (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
+ if (!keywords2) {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+ } else if (keywords2.InList(wordBuffer)) {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+ } else {
+ styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+ }
+ // No need to Reset Offset
+ // Check for Default Text
+ } else {
+ // Read up to %, Operator or Separator
+ while ((wbo < wbl) &&
+ (wordBuffer[wbo] != '%') &&
+ (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) or (%*)
+ if (((Is0To9(wordBuffer[1])) || (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 Expanded Argument (%~...) / Variable (%%~...)
+ } else if (((wbl > 1) && (wordBuffer[1] == '~')) ||
+ ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) {
+ // Check for External Command / Program
+ if (cmdLoc == offset - wbl) {
+ cmdLoc = offset - (wbl - wbo);
+ }
+ // Colorize Expanded Argument / Variable
+ styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
+ // Reset Offset to re-process remainder of word
+ offset -= (wbl - wbo);
+ // 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 (
+ (wbl > 2) &&
+ (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 Environment Variable (!x...!)
+ } 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++;
+ }
+ if (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 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++;
+ }
+ // 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] != '%') &&
+ (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++;
+ }
+ }
+ // Colorize Default Text for remainder of line - currently not lexed
+ styler.ColourTo(endPos, SCE_BAT_DEFAULT);
+}
+
+static void ColouriseBatchDoc(
+ unsigned int startPos,
+ int length,
+ int /*initStyle*/,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ char lineBuffer[1024];
+
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ unsigned int startLine = startPos;
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler);
+ linePos = 0;
+ startLine = i + 1;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ lineBuffer[linePos] = '\0';
+ ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
+ keywordlists, styler);
+ }
+}
+
+static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
+ // It is needed to remember the current state to recognize starting
+ // comment lines before the first "diff " or "--- ". If a real
+ // difference starts then each line starting with ' ' is a whitespace
+ // otherwise it is considered a comment (Only in..., Binary file...)
+ if (0 == strncmp(lineBuffer, "diff ", 5)) {
+ styler.ColourTo(endLine, SCE_DIFF_COMMAND);
+ } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff
+ styler.ColourTo(endLine, SCE_DIFF_COMMAND);
+ } else if (0 == strncmp(lineBuffer, "---", 3)) {
+ // In a context diff, --- appears in both the header and the position markers
+ if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/'))
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n')
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ else
+ styler.ColourTo(endLine, SCE_DIFF_HEADER);
+ } else if (0 == strncmp(lineBuffer, "+++ ", 4)) {
+ // I don't know of any diff where "+++ " is a position marker, but for
+ // consistency, do the same as with "--- " and "*** ".
+ if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ else
+ styler.ColourTo(endLine, SCE_DIFF_HEADER);
+ } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff
+ styler.ColourTo(endLine, SCE_DIFF_HEADER);
+ } else if (0 == strncmp(lineBuffer, "***", 3)) {
+ // In a context diff, *** appears in both the header and the position markers.
+ // Also ******** is a chunk header, but here it's treated as part of the
+ // position marker since there is no separate style for a chunk header.
+ if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ else if (lineBuffer[3] == '*')
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ else
+ styler.ColourTo(endLine, SCE_DIFF_HEADER);
+ } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib
+ styler.ColourTo(endLine, SCE_DIFF_HEADER);
+ } else if (lineBuffer[0] == '@') {
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') {
+ styler.ColourTo(endLine, SCE_DIFF_POSITION);
+ } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
+ styler.ColourTo(endLine, SCE_DIFF_DELETED);
+ } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
+ styler.ColourTo(endLine, SCE_DIFF_ADDED);
+ } else if (lineBuffer[0] == '!') {
+ styler.ColourTo(endLine, SCE_DIFF_CHANGED);
+ } else if (lineBuffer[0] != ' ') {
+ styler.ColourTo(endLine, SCE_DIFF_COMMENT);
+ } else {
+ styler.ColourTo(endLine, SCE_DIFF_DEFAULT);
+ }
+}
+
+static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ char lineBuffer[1024];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColouriseDiffLine(lineBuffer, i, styler);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColouriseDiffLine(lineBuffer, startPos + length - 1, styler);
+ }
+}
+
+static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ int curLine = styler.GetLine(startPos);
+ int curLineStart = styler.LineStart(curLine);
+ int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE;
+ int nextLevel;
+
+ do {
+ int lineType = styler.StyleAt(curLineStart);
+ if (lineType == SCE_DIFF_COMMAND)
+ nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ else if (lineType == SCE_DIFF_HEADER)
+ nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
+ else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-')
+ nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
+ else if (prevLevel & SC_FOLDLEVELHEADERFLAG)
+ nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
+ else
+ nextLevel = prevLevel;
+
+ 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);
+}
+
+static void ColourisePoLine(
+ char *lineBuffer,
+ unsigned int lengthLine,
+ unsigned int startLine,
+ unsigned int endPos,
+ Accessor &styler) {
+
+ unsigned int i = 0;
+ static unsigned int state = SCE_PO_DEFAULT;
+ unsigned int state_start = SCE_PO_DEFAULT;
+
+ while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
+ i++;
+ if (i < lengthLine) {
+ if (lineBuffer[i] == '#') {
+ // check if the comment contains any flags ("#, ") and
+ // then whether the flags contain "fuzzy"
+ if (strstart(lineBuffer, "#, ") && strstr(lineBuffer, "fuzzy"))
+ styler.ColourTo(endPos, SCE_PO_FUZZY);
+ else
+ styler.ColourTo(endPos, SCE_PO_COMMENT);
+ } else {
+ if (lineBuffer[0] == '"') {
+ // line continuation, use previous style
+ styler.ColourTo(endPos, state);
+ return;
+ // this implicitly also matches "msgid_plural"
+ } else if (strstart(lineBuffer, "msgid")) {
+ state_start = SCE_PO_MSGID;
+ state = SCE_PO_MSGID_TEXT;
+ } else if (strstart(lineBuffer, "msgstr")) {
+ state_start = SCE_PO_MSGSTR;
+ state = SCE_PO_MSGSTR_TEXT;
+ } else if (strstart(lineBuffer, "msgctxt")) {
+ state_start = SCE_PO_MSGCTXT;
+ state = SCE_PO_MSGCTXT_TEXT;
+ }
+ if (state_start != SCE_PO_DEFAULT) {
+ // find the next space
+ while ((i < lengthLine) && ! isspacechar(lineBuffer[i]))
+ i++;
+ styler.ColourTo(startLine + i - 1, state_start);
+ styler.ColourTo(startLine + i, SCE_PO_DEFAULT);
+ styler.ColourTo(endPos, state);
+ }
+ }
+ } else {
+ styler.ColourTo(endPos, SCE_PO_DEFAULT);
+ }
+}
+
+static void ColourisePoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ char lineBuffer[1024];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ unsigned int startLine = startPos;
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColourisePoLine(lineBuffer, linePos, startLine, i, styler);
+ linePos = 0;
+ startLine = i + 1;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColourisePoLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
+ }
+}
+
+static inline bool isassignchar(unsigned char ch) {
+ return (ch == '=') || (ch == ':');
+}
+
+static void ColourisePropsLine(
+ char *lineBuffer,
+ unsigned int lengthLine,
+ unsigned int startLine,
+ unsigned int endPos,
+ Accessor &styler,
+ bool allowInitialSpaces) {
+
+ unsigned int i = 0;
+ if (allowInitialSpaces) {
+ while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
+ i++;
+ } else {
+ if (isspacechar(lineBuffer[i])) // don't allow initial spaces
+ i = lengthLine;
+ }
+
+ if (i < lengthLine) {
+ if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
+ styler.ColourTo(endPos, SCE_PROPS_COMMENT);
+ } else if (lineBuffer[i] == '[') {
+ styler.ColourTo(endPos, SCE_PROPS_SECTION);
+ } else if (lineBuffer[i] == '@') {
+ styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
+ if (isassignchar(lineBuffer[i++]))
+ styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
+ styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
+ } else {
+ // Search for the '=' character
+ while ((i < lengthLine) && !isassignchar(lineBuffer[i]))
+ i++;
+ if ((i < lengthLine) && isassignchar(lineBuffer[i])) {
+ styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY);
+ styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
+ styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
+ } else {
+ styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
+ }
+ }
+ } else {
+ styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
+ }
+}
+
+static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ char lineBuffer[1024];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ unsigned int startLine = startPos;
+
+ // property lexer.props.allow.initial.spaces
+ // For properties files, set to 0 to style all lines that start with whitespace in the default style.
+ // This is not suitable for SciTE .properties files which use indentation for flow control but
+ // can be used for RFC2822 text where indentation is used for continuation lines.
+ bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
+
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces);
+ linePos = 0;
+ startLine = i + 1;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces);
+ }
+}
+
+// adaption by ksc, using the "} else {" trick of 1.53
+// 030721
+static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ bool headerPoint = false;
+ int lev;
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler[i+1];
+
+ int style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if (style == SCE_PROPS_SECTION) {
+ headerPoint = true;
+ }
+
+ if (atEOL) {
+ lev = SC_FOLDLEVELBASE;
+
+ if (lineCurrent > 0) {
+ int levelPrevious = styler.LevelAt(lineCurrent - 1);
+
+ if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
+ lev = SC_FOLDLEVELBASE + 1;
+ } else {
+ lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
+ }
+ }
+
+ if (headerPoint) {
+ lev = SC_FOLDLEVELBASE;
+ }
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+
+ if (headerPoint) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+
+ lineCurrent++;
+ visibleChars = 0;
+ headerPoint = false;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+
+ if (lineCurrent > 0) {
+ int levelPrevious = styler.LevelAt(lineCurrent - 1);
+ if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
+ lev = SC_FOLDLEVELBASE + 1;
+ } else {
+ lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
+ }
+ } else {
+ lev = SC_FOLDLEVELBASE;
+ }
+ int flagsNext = styler.LevelAt(lineCurrent);
+ styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK));
+}
+
+static void ColouriseMakeLine(
+ char *lineBuffer,
+ unsigned int lengthLine,
+ unsigned int startLine,
+ unsigned int endPos,
+ Accessor &styler) {
+
+ unsigned int i = 0;
+ int lastNonSpace = -1;
+ unsigned int state = SCE_MAKE_DEFAULT;
+ bool bSpecial = false;
+
+ // check for a tab character in column 0 indicating a command
+ bool bCommand = false;
+ if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
+ bCommand = true;
+
+ // Skip initial spaces
+ while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
+ i++;
+ }
+ if (lineBuffer[i] == '#') { // Comment
+ styler.ColourTo(endPos, SCE_MAKE_COMMENT);
+ return;
+ }
+ if (lineBuffer[i] == '!') { // Special directive
+ styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
+ return;
+ }
+ while (i < lengthLine) {
+ if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') {
+ styler.ColourTo(startLine + i - 1, state);
+ state = SCE_MAKE_IDENTIFIER;
+ } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
+ styler.ColourTo(startLine + i, state);
+ state = SCE_MAKE_DEFAULT;
+ }
+
+ // skip identifier and target styling if this is a command line
+ if (!bSpecial && !bCommand) {
+ if (lineBuffer[i] == ':') {
+ if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
+ // it's a ':=', so style as an identifier
+ if (lastNonSpace >= 0)
+ styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
+ styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
+ styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
+ } else {
+ // We should check that no colouring was made since the beginning of the line,
+ // to avoid colouring stuff like /OUT:file
+ if (lastNonSpace >= 0)
+ styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
+ styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
+ styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
+ }
+ bSpecial = true; // Only react to the first ':' of the line
+ state = SCE_MAKE_DEFAULT;
+ } else if (lineBuffer[i] == '=') {
+ if (lastNonSpace >= 0)
+ styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
+ styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
+ styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
+ bSpecial = true; // Only react to the first '=' of the line
+ state = SCE_MAKE_DEFAULT;
+ }
+ }
+ if (!isspacechar(lineBuffer[i])) {
+ lastNonSpace = i;
+ }
+ i++;
+ }
+ if (state == SCE_MAKE_IDENTIFIER) {
+ styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
+ } else {
+ styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
+ }
+}
+
+static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ char lineBuffer[1024];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ unsigned int startLine = startPos;
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
+ linePos = 0;
+ startLine = i + 1;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
+ }
+}
+
+static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) {
+ if (lineBuffer[0] == '>') {
+ // Command or return status
+ return SCE_ERR_CMD;
+ } else if (lineBuffer[0] == '<') {
+ // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
+ return SCE_ERR_DEFAULT;
+ } else if (lineBuffer[0] == '!') {
+ return SCE_ERR_DIFF_CHANGED;
+ } else if (lineBuffer[0] == '+') {
+ if (strstart(lineBuffer, "+++ ")) {
+ return SCE_ERR_DIFF_MESSAGE;
+ } else {
+ return SCE_ERR_DIFF_ADDITION;
+ }
+ } else if (lineBuffer[0] == '-') {
+ 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
+ return SCE_ERR_ABSF;
+ } else if (strstart(lineBuffer, "fortcom:")) {
+ // Intel Fortran Compiler v8.0 error/warning message
+ return SCE_ERR_IFORT;
+ } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
+ return SCE_ERR_PYTHON;
+ } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
+ return SCE_ERR_PHP;
+ } else if ((strstart(lineBuffer, "Error ") ||
+ strstart(lineBuffer, "Warning ")) &&
+ strstr(lineBuffer, " at (") &&
+ strstr(lineBuffer, ") : ") &&
+ (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
+ // Intel Fortran Compiler error/warning message
+ return SCE_ERR_IFC;
+ } else if (strstart(lineBuffer, "Error ")) {
+ // Borland error message
+ return SCE_ERR_BORLAND;
+ } else if (strstart(lineBuffer, "Warning ")) {
+ // Borland warning message
+ 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
+ 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 ")))) {
+ // perl error message
+ return SCE_ERR_PERL;
+ } else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
+ strstr(lineBuffer, ":line ")) {
+ // A .NET traceback
+ return SCE_ERR_NET;
+ } else if (strstart(lineBuffer, "Line ") &&
+ strstr(lineBuffer, ", file ")) {
+ // Essential Lahey Fortran error message
+ return SCE_ERR_ELF;
+ } else if (strstart(lineBuffer, "line ") &&
+ strstr(lineBuffer, " column ")) {
+ // HTML tidy style: line 42 column 1
+ return SCE_ERR_TIDY;
+ } else if (strstart(lineBuffer, "\tat ") &&
+ strstr(lineBuffer, "(") &&
+ strstr(lineBuffer, ".java:")) {
+ // Java stack back trace
+ return SCE_ERR_JAVA_STACK;
+ } else {
+ // 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>
+ // Lua 5.1: <exe>: <filename>:<line>:<message>
+ bool initialTab = (lineBuffer[0] == '\t');
+ bool initialColonPart = false;
+ 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 == stInitial) {
+ if (ch == ':') {
+ // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
+ if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) {
+ // This check is not completely accurate as may be on
+ // GTK+ with a file name that includes ':'.
+ state = stGccStart;
+ } else if (chNext == ' ') { // indicates a Lua 5.1 error message
+ initialColonPart = true;
+ }
+ } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
+ // May be Microsoft
+ // Check against '0' often removes phone numbers
+ state = stMsStart;
+ } else if ((ch == '\t') && (!initialTab)) {
+ // May be CTags
+ state = stCtagsStart;
+ }
+ } else if (state == stGccStart) { // <filename>:
+ state = Is1To9(ch) ? stGccDigit : stUnrecognized;
+ } else if (state == stGccDigit) { // <filename>:<line>
+ if (ch == ':') {
+ state = stGcc; // :9.*: is GCC
+ startValue = i + 1;
+ break;
+ } else if (!Is0To9(ch)) {
+ state = stUnrecognized;
+ }
+ } else if (state == stMsStart) { // <filename>(
+ state = Is0To9(ch) ? stMsDigit : stUnrecognized;
+ } else if (state == stMsDigit) { // <filename>(<line>
+ if (ch == ',') {
+ state = stMsDigitComma;
+ } else if (ch == ')') {
+ state = stMsBracket;
+ } else if ((ch != ' ') && !Is0To9(ch)) {
+ state = stUnrecognized;
+ }
+ } else if (state == stMsBracket) { // <filename>(<line>)
+ if ((ch == ' ') && (chNext == ':')) {
+ 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 && IsAlphabetic(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 = stUnrecognized;
+ }
+ } else if (state == stMsDigitComma) { // <filename>(<line>,
+ if (ch == ')') {
+ state = stMsDotNet;
+ break;
+ } else if ((ch != ' ') && !Is0To9(ch)) {
+ state = stUnrecognized;
+ }
+ } 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 = stCtagsStartString;
+ }
+ } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
+ state = stCtagsStringDollar;
+ break;
+ }
+ }
+ if (state == stGcc) {
+ return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC;
+ } else if ((state == stMsVc) || (state == stMsDotNet)) {
+ return SCE_ERR_MS;
+ } else if ((state == stCtagsStringDollar) || (state == stCtags)) {
+ return SCE_ERR_CTAG;
+ } else {
+ return SCE_ERR_DEFAULT;
+ }
+ }
+}
+
+static void ColouriseErrorListLine(
+ char *lineBuffer,
+ unsigned int lengthLine,
+ unsigned int endPos,
+ Accessor &styler,
+ bool valueSeparate) {
+ int startValue = -1;
+ int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue);
+ if (valueSeparate && (startValue >= 0)) {
+ styler.ColourTo(endPos - (lengthLine - startValue), style);
+ styler.ColourTo(endPos, SCE_ERR_VALUE);
+ } else {
+ styler.ColourTo(endPos, style);
+ }
+}
+
+static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+ char lineBuffer[10000];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+
+ // property lexer.errorlist.value.separate
+ // For lines in the output pane that are matches from Find in Files or GCC-style
+ // diagnostics, style the path and line number separately from the rest of the
+ // line with style 21 used for the rest of the line.
+ // This allows matched text to be more easily distinguished from its location.
+ bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
+ for (unsigned int i = startPos; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate);
+ linePos = 0;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate);
+ }
+}
+
+static int isSpecial(char s) {
+ return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
+ (s == '\"') || (s == '`') || (s == '^') || (s == '~');
+}
+
+static int isTag(int start, Accessor &styler) {
+ char s[6];
+ unsigned int i = 0, e = 1;
+ while (i < 5 && e) {
+ s[i] = styler[start + i];
+ i++;
+ e = styler[start + i] != '{';
+ }
+ s[i] = '\0';
+ return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
+}
+
+static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler) {
+
+ styler.StartAt(startPos);
+
+ int state = initStyle;
+ char chNext = styler[startPos];
+ styler.StartSegment(startPos);
+ int lengthDoc = startPos + length;
+
+ for (int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ i++;
+ continue;
+ }
+ switch (state) {
+ case SCE_L_DEFAULT :
+ switch (ch) {
+ case '\\' :
+ styler.ColourTo(i - 1, state);
+ if (isSpecial(styler[i + 1])) {
+ styler.ColourTo(i + 1, SCE_L_COMMAND);
+ i++;
+ chNext = styler.SafeGetCharAt(i + 1);
+ } else {
+ if (isTag(i + 1, styler))
+ state = SCE_L_TAG;
+ else
+ state = SCE_L_COMMAND;
+ }
+ break;
+ case '$' :
+ styler.ColourTo(i - 1, state);
+ state = SCE_L_MATH;
+ if (chNext == '$') {
+ i++;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ break;
+ case '%' :
+ styler.ColourTo(i - 1, state);
+ state = SCE_L_COMMENT;
+ break;
+ }
+ break;
+ case SCE_L_COMMAND :
+ if (chNext == '[' || chNext == '{' || chNext == '}' ||
+ chNext == ' ' || chNext == '\r' || chNext == '\n') {
+ styler.ColourTo(i, state);
+ state = SCE_L_DEFAULT;
+ i++;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ break;
+ case SCE_L_TAG :
+ if (ch == '}') {
+ styler.ColourTo(i, state);
+ state = SCE_L_DEFAULT;
+ }
+ break;
+ case SCE_L_MATH :
+ if (ch == '$') {
+ if (chNext == '$') {
+ i++;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ styler.ColourTo(i, state);
+ state = SCE_L_DEFAULT;
+ }
+ break;
+ case SCE_L_COMMENT :
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_L_DEFAULT;
+ }
+ }
+ }
+ styler.ColourTo(lengthDoc-1, state);
+}
+
+static const char *const batchWordListDesc[] = {
+ "Internal Commands",
+ "External Commands",
+ 0
+};
+
+static const char *const emptyWordListDesc[] = {
+ 0
+};
+
+static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
+ Accessor &styler) {
+ // Null language means all style bytes are 0 so just mark the end - no need to fill in.
+ if (length > 0) {
+ styler.StartAt(startPos + length - 1);
+ styler.StartSegment(startPos + length - 1);
+ styler.ColourTo(startPos + length - 1, 0);
+ }
+}
+
+LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
+LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc);
+LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc);
+LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
+LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
+LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
+LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
+LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");
diff --git a/scintilla/src/LexPB.cxx b/scintilla/src/LexPB.cxx
new file mode 100644
index 0000000..1e39961
--- /dev/null
+++ b/scintilla/src/LexPB.cxx
@@ -0,0 +1,362 @@
+// Scintilla source code edit control
+// @file LexPB.cxx
+// Lexer for PowerBasic by Roland Walter, roland@rowalt.de (for PowerBasic see www.powerbasic.com)
+//
+// Changes:
+// 17.10.2003: Toggling of subs/functions now until next sub/function - this gives better results
+// 29.10.2003: 1. Bug: Toggling didn't work for subs/functions added in editor
+// 2. Own colors for PB constants and Inline Assembler SCE_B_CONSTANT and SCE_B_ASM
+// 3. Several smaller syntax coloring improvements and speed optimizations
+// 12.07.2004: 1. Toggling for macros added
+// 2. Further folding speed optimitations (for people dealing with very large listings)
+//
+// Necessary changes for the PB lexer in Scintilla project:
+// - In SciLexer.h and Scintilla.iface:
+//
+// #define SCLEX_POWERBASIC 51 //ID for PowerBasic lexer
+// (...)
+// #define SCE_B_DEFAULT 0 //in both VB and PB lexer
+// #define SCE_B_COMMENT 1 //in both VB and PB lexer
+// #define SCE_B_NUMBER 2 //in both VB and PB lexer
+// #define SCE_B_KEYWORD 3 //in both VB and PB lexer
+// #define SCE_B_STRING 4 //in both VB and PB lexer
+// #define SCE_B_PREPROCESSOR 5 //VB lexer only, not in PB lexer
+// #define SCE_B_OPERATOR 6 //in both VB and PB lexer
+// #define SCE_B_IDENTIFIER 7 //in both VB and PB lexer
+// #define SCE_B_DATE 8 //VB lexer only, not in PB lexer
+// #define SCE_B_CONSTANT 13 //PB lexer only, not in VB lexer
+// #define SCE_B_ASM 14 //PB lexer only, not in VB lexer
+
+// - Statement added to KeyWords.cxx: 'LINK_LEXER(lmPB);'
+// - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)'
+//
+// 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.
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsTypeCharacter(const int ch)
+{
+ return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$' || ch == '?';
+}
+
+static inline bool IsAWordChar(const int ch)
+{
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(const int ch)
+{
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+bool MatchUpperCase(Accessor &styler, int pos, const char *s) //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
+{
+ char ch;
+ for (int i=0; *s; i++)
+ {
+ ch=styler.SafeGetCharAt(pos+i);
+ if (ch > 0x60) ch -= '\x20';
+ if (*s != ch) return false;
+ s++;
+ }
+ return true;
+}
+
+static void ColourisePBDoc(unsigned int startPos, int length, int initStyle,WordList *keywordlists[],Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+
+ styler.StartAt(startPos);
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+ switch (sc.state)
+ {
+ case SCE_B_OPERATOR:
+ {
+ sc.SetState(SCE_B_DEFAULT);
+ break;
+ }
+ case SCE_B_KEYWORD:
+ {
+ if (!IsAWordChar(sc.ch))
+ {
+ if (!IsTypeCharacter(sc.ch))
+ {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s))
+ {
+ if (strcmp(s, "rem") == 0)
+ {
+ sc.ChangeState(SCE_B_COMMENT);
+ if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
+ }
+ else if (strcmp(s, "asm") == 0)
+ {
+ sc.ChangeState(SCE_B_ASM);
+ if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
+ }
+ else
+ {
+ sc.SetState(SCE_B_DEFAULT);
+ }
+ }
+ else
+ {
+ sc.ChangeState(SCE_B_IDENTIFIER);
+ sc.SetState(SCE_B_DEFAULT);
+ }
+ }
+ }
+ break;
+ }
+ case SCE_B_NUMBER:
+ {
+ if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);}
+ break;
+ }
+ case SCE_B_STRING:
+ {
+ if (sc.ch == '\"'){sc.ForwardSetState(SCE_B_DEFAULT);}
+ break;
+ }
+ case SCE_B_CONSTANT:
+ {
+ if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);}
+ break;
+ }
+ case SCE_B_COMMENT:
+ {
+ if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
+ break;
+ }
+ case SCE_B_ASM:
+ {
+ if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
+ break;
+ }
+ } //switch (sc.state)
+
+ // Determine if a new state should be entered:
+ if (sc.state == SCE_B_DEFAULT)
+ {
+ if (sc.ch == '\'') {sc.SetState(SCE_B_COMMENT);}
+ else if (sc.ch == '\"') {sc.SetState(SCE_B_STRING);}
+ else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {sc.SetState(SCE_B_NUMBER);}
+ else if (sc.ch == '&' && tolower(sc.chNext) == 'b') {sc.SetState(SCE_B_NUMBER);}
+ else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {sc.SetState(SCE_B_NUMBER);}
+ else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_B_NUMBER);}
+ else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_B_KEYWORD);}
+ else if (sc.ch == '%') {sc.SetState(SCE_B_CONSTANT);}
+ else if (sc.ch == '$') {sc.SetState(SCE_B_CONSTANT);}
+ else if (sc.ch == '#') {sc.SetState(SCE_B_KEYWORD);}
+ else if (sc.ch == '!') {sc.SetState(SCE_B_ASM);}
+ else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {sc.SetState(SCE_B_OPERATOR);}
+ }
+ } //for (; sc.More(); sc.Forward())
+ sc.Complete();
+}
+
+//The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted,
+//nothing more. I had worked with this kind of toggling for several years when I used the great good old
+//GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops
+//and so on too I found this is more disturbing then helping (for me). So if You think in another way
+//you can (or must) write Your own toggling routine ;-)
+static void FoldPBDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ // No folding enabled, no reason to continue...
+ if( styler.GetPropertyInt("fold") == 0 )
+ return;
+
+ unsigned int endPos = startPos + length;
+ int lineCurrent = styler.GetLine(startPos);
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+
+ bool fNewLine=true;
+ bool fMightBeMultiLineMacro=false;
+ bool fBeginOfCommentFound=false;
+ for (unsigned int i = startPos; i < endPos; i++)
+ {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if (fNewLine) //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
+ {
+ fNewLine=false;
+ fBeginOfCommentFound=false;
+ switch (ch)
+ {
+ case ' ': //Most lines start with space - so check this first, the code is the same as for 'default:'
+ case '\t': //Handle tab too
+ {
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ styler.SetLevel(lineCurrent, lev);
+ break;
+ }
+ case 'F':
+ case 'f':
+ {
+ switch (chNext)
+ {
+ case 'U':
+ case 'u':
+ {
+ if( MatchUpperCase(styler,i,"FUNCTION") )
+ {
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 'S':
+ case 's':
+ {
+ switch (chNext)
+ {
+ case 'U':
+ case 'u':
+ {
+ if( MatchUpperCase(styler,i,"SUB") )
+ {
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ break;
+ }
+ case 'T':
+ case 't':
+ {
+ if( MatchUpperCase(styler,i,"STATIC FUNCTION") )
+ {
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ else if( MatchUpperCase(styler,i,"STATIC SUB") )
+ {
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 'C':
+ case 'c':
+ {
+ switch (chNext)
+ {
+ case 'A':
+ case 'a':
+ {
+ if( MatchUpperCase(styler,i,"CALLBACK FUNCTION") )
+ {
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 'M':
+ case 'm':
+ {
+ switch (chNext)
+ {
+ case 'A':
+ case 'a':
+ {
+ if( MatchUpperCase(styler,i,"MACRO") )
+ {
+ fMightBeMultiLineMacro=true; //Set folder level at end of line, we have to check for single line macro
+ }
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ styler.SetLevel(lineCurrent, lev);
+ break;
+ }
+ } //switch (ch)
+ } //if( fNewLine )
+
+ switch (ch)
+ {
+ case '=': //To test single line macros
+ {
+ if (fBeginOfCommentFound==false)
+ fMightBeMultiLineMacro=false; //The found macro is a single line macro only;
+ break;
+ }
+ case '\'': //A comment starts
+ {
+ fBeginOfCommentFound=true;
+ break;
+ }
+ case '\n':
+ {
+ if (fMightBeMultiLineMacro) //The current line is the begin of a multi line macro
+ {
+ fMightBeMultiLineMacro=false;
+ styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
+ levelNext=SC_FOLDLEVELBASE+1;
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ fNewLine=true;
+ break;
+ }
+ case '\r':
+ {
+ if (chNext != '\n')
+ {
+ lineCurrent++;
+ levelCurrent = levelNext;
+ fNewLine=true;
+ }
+ break;
+ }
+ } //switch (ch)
+ } //for (unsigned int i = startPos; i < endPos; i++)
+}
+
+static const char * const pbWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmPB(SCLEX_POWERBASIC, ColourisePBDoc, "powerbasic", FoldPBDoc, pbWordListDesc);
diff --git a/scintilla/src/LexPLM.cxx b/scintilla/src/LexPLM.cxx
new file mode 100644
index 0000000..de73f25
--- /dev/null
+++ b/scintilla/src/LexPLM.cxx
@@ -0,0 +1,198 @@
+// Copyright (c) 1990-2007, Scientific Toolworks, Inc.
+// Author: Jason Haslam
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void GetRange(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static void ColourisePlmDoc(unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler)
+{
+ unsigned int endPos = startPos + length;
+ int state = initStyle;
+
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = styler.SafeGetCharAt(i);
+ char chNext = styler.SafeGetCharAt(i + 1);
+
+ if (state == SCE_PLM_DEFAULT) {
+ if (ch == '/' && chNext == '*') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_COMMENT;
+ } else if (ch == '\'') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_STRING;
+ } else if (isdigit(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_NUMBER;
+ } else if (isalpha(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_IDENTIFIER;
+ } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
+ ch == '=' || ch == '<' || ch == '>' || ch == ':') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_OPERATOR;
+ } else if (ch == '$') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_CONTROL;
+ }
+ } else if (state == SCE_PLM_COMMENT) {
+ if (ch == '*' && chNext == '/') {
+ i++;
+ styler.ColourTo(i, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ } else if (state == SCE_PLM_STRING) {
+ if (ch == '\'') {
+ if (chNext == '\'') {
+ i++;
+ } else {
+ styler.ColourTo(i, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ }
+ } else if (state == SCE_PLM_NUMBER) {
+ if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
+ i--;
+ styler.ColourTo(i, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ } else if (state == SCE_PLM_IDENTIFIER) {
+ if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
+ // Get the entire identifier.
+ char word[1024];
+ int segmentStart = styler.GetStartSegment();
+ GetRange(segmentStart, i - 1, styler, word, sizeof(word));
+
+ i--;
+ if (keywordlists[0]->InList(word))
+ styler.ColourTo(i, SCE_PLM_KEYWORD);
+ else
+ styler.ColourTo(i, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ } else if (state == SCE_PLM_OPERATOR) {
+ if (ch != '=' && ch != '>') {
+ i--;
+ styler.ColourTo(i, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ } else if (state == SCE_PLM_CONTROL) {
+ if (ch == '\r' || ch == '\n') {
+ styler.ColourTo(i - 1, state);
+ state = SCE_PLM_DEFAULT;
+ }
+ }
+ }
+ styler.ColourTo(endPos - 1, state);
+}
+
+static void FoldPlmDoc(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 levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ int startKeyword = 0;
+
+ 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 (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD)
+ startKeyword = i;
+
+ if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) {
+ char word[1024];
+ GetRange(startKeyword, i, styler, word, sizeof(word));
+
+ if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0)
+ levelCurrent++;
+ else if (strcmp(word, "end") == 0)
+ levelCurrent--;
+ }
+
+ if (foldComment) {
+ if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT)
+ levelCurrent++;
+ else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT)
+ 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++;
+ }
+
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static const char *const plmWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc);
diff --git a/scintilla/src/LexPOV.cxx b/scintilla/src/LexPOV.cxx
new file mode 100644
index 0000000..33be6fe
--- /dev/null
+++ b/scintilla/src/LexPOV.cxx
@@ -0,0 +1,316 @@
+// Scintilla source code edit control
+/** @file LexPOV.cxx
+ ** 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-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:
+// Identifiers start only by a character.
+// No line continuation character.
+// Strings are limited to 256 characters.
+// Directives are similar to preprocessor commands,
+// but we match directive keywords and colorize incorrect ones.
+// Block comments can be nested (code stolen from my code in LexLua).
+
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return ch < 0x80 && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+ return ch < 0x80 && isalpha(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 == '+');
+}
+
+static void ColourisePovDoc(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords1 = *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 block comment /* */ nesting level, if we are inside such a comment.
+ int blockCommentLevel = 0;
+ if (initStyle == SCE_POV_COMMENT) {
+ blockCommentLevel = styler.GetLineState(currentLine - 1);
+ }
+
+ // Do not leak onto next line
+ if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) {
+ initStyle = SCE_POV_DEFAULT;
+ }
+
+ 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
+ currentLine = styler.GetLine(sc.currentPos);
+ if (sc.state == SCE_POV_COMMENT) {
+ // Inside a block comment, we set the line state
+ styler.SetLineState(currentLine, blockCommentLevel);
+ } else {
+ // Reset the line state
+ styler.SetLineState(currentLine, 0);
+ }
+ }
+
+ if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {
+ // Prevent SCE_POV_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_POV_STRING);
+ }
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_POV_OPERATOR) {
+ sc.SetState(SCE_POV_DEFAULT);
+ } else if (sc.state == SCE_POV_NUMBER) {
+ // We stop the number definition on non-numerical non-dot non-eE non-sign char
+ if (!IsANumberChar(sc.ch)) {
+ sc.SetState(SCE_POV_DEFAULT);
+ }
+ } else if (sc.state == SCE_POV_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD4);
+ } else if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD5);
+ } else if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD6);
+ } else if (keywords7.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD7);
+ } else if (keywords8.InList(s)) {
+ sc.ChangeState(SCE_POV_WORD8);
+ }
+ sc.SetState(SCE_POV_DEFAULT);
+ }
+ } else if (sc.state == SCE_POV_DIRECTIVE) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ char *p;
+ sc.GetCurrent(s, sizeof(s));
+ p = s;
+ // Skip # and whitespace between # and directive word
+ do {
+ p++;
+ } while ((*p == ' ' || *p == '\t') && *p != '\0');
+ if (!keywords1.InList(p)) {
+ sc.ChangeState(SCE_POV_BADDIRECTIVE);
+ }
+ sc.SetState(SCE_POV_DEFAULT);
+ }
+ } else if (sc.state == SCE_POV_COMMENT) {
+ if (sc.Match('/', '*')) {
+ blockCommentLevel++;
+ sc.Forward();
+ } else if (sc.Match('*', '/') && blockCommentLevel > 0) {
+ blockCommentLevel--;
+ sc.Forward();
+ if (blockCommentLevel == 0) {
+ sc.ForwardSetState(SCE_POV_DEFAULT);
+ }
+ }
+ } else if (sc.state == SCE_POV_COMMENTLINE) {
+ if (sc.atLineEnd) {
+ sc.ForwardSetState(SCE_POV_DEFAULT);
+ }
+ } else if (sc.state == SCE_POV_STRING) {
+ if (sc.ch == '\\') {
+ stringLen++;
+ if (strchr("abfnrtuv0'\"", sc.chNext)) {
+ // Compound characters are counted as one.
+ // Note: for Unicode chars \u, we shouldn't count the next 4 digits...
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_POV_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_POV_STRINGEOL);
+ sc.ForwardSetState(SCE_POV_DEFAULT);
+ } else {
+ stringLen++;
+ }
+ if (stringLen > 256) {
+ // Strings are limited to 256 chars
+ sc.SetState(SCE_POV_STRINGEOL);
+ }
+ } else if (sc.state == SCE_POV_STRINGEOL) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_C_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ForwardSetState(SCE_POV_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_POV_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_POV_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_POV_IDENTIFIER);
+ } else if (sc.Match('/', '*')) {
+ blockCommentLevel = 1;
+ sc.SetState(SCE_POV_COMMENT);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(SCE_POV_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_POV_STRING);
+ stringLen = 0;
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_POV_DIRECTIVE);
+ // Skip whitespace between # and directive word
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_POV_DEFAULT);
+ }
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_POV_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldPovDoc(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *[],
+ Accessor &styler) {
+
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldDirective = styler.GetPropertyInt("fold.directive") != 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];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+ if (foldComment && (style == SCE_POV_COMMENT)) {
+ if (stylePrev != SCE_POV_COMMENT) {
+ levelCurrent++;
+ } else if ((styleNext != SCE_POV_COMMENT) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+ if (foldComment && (style == SCE_POV_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelCurrent++;
+ } else if (chNext2 == '}') {
+ levelCurrent--;
+ }
+ }
+ }
+ if (foldDirective && (style == SCE_POV_DIRECTIVE)) {
+ if (ch == '#') {
+ unsigned int j=i+1;
+ while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ j++;
+ }
+ }
+ }
+ if (style == SCE_POV_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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 povWordLists[] = {
+ "Language directives",
+ "Objects & CSG & Appearance",
+ "Types & Modifiers & Items",
+ "Predefined Identifiers",
+ "Predefined Functions",
+ "User defined 1",
+ "User defined 2",
+ "User defined 3",
+ 0,
+};
+
+LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists);
diff --git a/scintilla/src/LexPS.cxx b/scintilla/src/LexPS.cxx
new file mode 100644
index 0000000..7b236b0
--- /dev/null
+++ b/scintilla/src/LexPS.cxx
@@ -0,0 +1,347 @@
+// Scintilla source code edit control
+/** @file LexPS.cxx
+ ** Lexer for PostScript
+ **
+ ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
+ ** The License.txt file describes the conditions under which this software may be distributed.
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsASelfDelimitingChar(const int ch) {
+ return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||
+ ch == '/' || ch == '<' || ch == '>' ||
+ ch == '(' || ch == ')' || ch == '%');
+}
+
+static inline bool IsAWhitespaceChar(const int ch) {
+ return (ch == ' ' || ch == '\t' || ch == '\r' ||
+ ch == '\n' || ch == '\f' || ch == '\0');
+}
+
+static bool IsABaseNDigit(const int ch, const int base) {
+ int maxdig = '9';
+ int letterext = -1;
+
+ if (base <= 10)
+ maxdig = '0' + base - 1;
+ else
+ letterext = base - 11;
+
+ return ((ch >= '0' && ch <= maxdig) ||
+ (ch >= 'A' && ch <= ('A' + letterext)) ||
+ (ch >= 'a' && ch <= ('a' + letterext)));
+}
+
+static inline bool IsABase85Char(const int ch) {
+ return ((ch >= '!' && ch <= 'u') || ch == 'z');
+}
+
+static void ColourisePSDoc(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords1 = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+ WordList &keywords5 = *keywordlists[4];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0;
+ int pslevel = styler.GetPropertyInt("ps.level", 3);
+ int lineCurrent = styler.GetLine(startPos);
+ int nestTextCurrent = 0;
+ if (lineCurrent > 0 && initStyle == SCE_PS_TEXT)
+ nestTextCurrent = styler.GetLineState(lineCurrent - 1);
+ int numRadix = 0;
+ bool numHasPoint = false;
+ bool numHasExponent = false;
+ bool numHasSign = false;
+
+ // Clear out existing tokenization
+ if (tokenizing && length > 0) {
+ styler.StartAt(startPos, static_cast<char>(INDIC2_MASK));
+ styler.ColourTo(startPos + length-1, 0);
+ styler.Flush();
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ }
+
+ for (; sc.More(); sc.Forward()) {
+ if (sc.atLineStart)
+ lineCurrent = styler.GetLine(sc.currentPos);
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_C_DEFAULT);
+ }
+ } else if (sc.state == SCE_PS_DSC_COMMENT) {
+ if (sc.ch == ':') {
+ sc.Forward();
+ if (!sc.atLineEnd)
+ sc.SetState(SCE_PS_DSC_VALUE);
+ else
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') {
+ sc.ChangeState(SCE_PS_COMMENT);
+ }
+ } else if (sc.state == SCE_PS_NUMBER) {
+ if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
+ if ((sc.chPrev == '+' || sc.chPrev == '-' ||
+ sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0)
+ sc.ChangeState(SCE_PS_NAME);
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (sc.ch == '#') {
+ if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) {
+ sc.ChangeState(SCE_PS_NAME);
+ } else {
+ char szradix[5];
+ sc.GetCurrent(szradix, 4);
+ numRadix = atoi(szradix);
+ if (numRadix < 2 || numRadix > 36)
+ sc.ChangeState(SCE_PS_NAME);
+ }
+ } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) {
+ if (numHasExponent) {
+ sc.ChangeState(SCE_PS_NAME);
+ } else {
+ numHasExponent = true;
+ if (sc.chNext == '+' || sc.chNext == '-')
+ sc.Forward();
+ }
+ } else if (sc.ch == '.') {
+ if (numHasPoint || numHasExponent || numRadix != 0) {
+ sc.ChangeState(SCE_PS_NAME);
+ } else {
+ numHasPoint = true;
+ }
+ } else if (numRadix == 0) {
+ if (!IsABaseNDigit(sc.ch, 10))
+ sc.ChangeState(SCE_PS_NAME);
+ } else {
+ if (!IsABaseNDigit(sc.ch, numRadix))
+ sc.ChangeState(SCE_PS_NAME);
+ }
+ } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) {
+ if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if ((pslevel >= 1 && keywords1.InList(s)) ||
+ (pslevel >= 2 && keywords2.InList(s)) ||
+ (pslevel >= 3 && keywords3.InList(s)) ||
+ keywords4.InList(s) || keywords5.InList(s)) {
+ sc.ChangeState(SCE_PS_KEYWORD);
+ }
+ sc.SetState(SCE_C_DEFAULT);
+ }
+ } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) {
+ if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch))
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT ||
+ sc.state == SCE_PS_PAREN_PROC) {
+ sc.SetState(SCE_C_DEFAULT);
+ } else if (sc.state == SCE_PS_TEXT) {
+ if (sc.ch == '(') {
+ nestTextCurrent++;
+ } else if (sc.ch == ')') {
+ if (--nestTextCurrent == 0)
+ sc.ForwardSetState(SCE_PS_DEFAULT);
+ } else if (sc.ch == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.state == SCE_PS_HEXSTRING) {
+ if (sc.ch == '>') {
+ sc.ForwardSetState(SCE_PS_DEFAULT);
+ } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) {
+ sc.SetState(SCE_PS_HEXSTRING);
+ styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
+ }
+ } else if (sc.state == SCE_PS_BASE85STRING) {
+ if (sc.Match('~', '>')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_PS_DEFAULT);
+ } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) {
+ sc.SetState(SCE_PS_BASE85STRING);
+ styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_C_DEFAULT) {
+ unsigned int tokenpos = sc.currentPos;
+
+ if (sc.ch == '[' || sc.ch == ']') {
+ sc.SetState(SCE_PS_PAREN_ARRAY);
+ } else if (sc.ch == '{' || sc.ch == '}') {
+ sc.SetState(SCE_PS_PAREN_PROC);
+ } else if (sc.ch == '/') {
+ if (sc.chNext == '/') {
+ sc.SetState(SCE_PS_IMMEVAL);
+ sc.Forward();
+ } else {
+ sc.SetState(SCE_PS_LITERAL);
+ }
+ } else if (sc.ch == '<') {
+ if (sc.chNext == '<') {
+ sc.SetState(SCE_PS_PAREN_DICT);
+ sc.Forward();
+ } else if (sc.chNext == '~') {
+ sc.SetState(SCE_PS_BASE85STRING);
+ sc.Forward();
+ } else {
+ sc.SetState(SCE_PS_HEXSTRING);
+ }
+ } else if (sc.ch == '>' && sc.chNext == '>') {
+ sc.SetState(SCE_PS_PAREN_DICT);
+ sc.Forward();
+ } else if (sc.ch == '>' || sc.ch == ')') {
+ sc.SetState(SCE_C_DEFAULT);
+ styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
+ } else if (sc.ch == '(') {
+ sc.SetState(SCE_PS_TEXT);
+ nestTextCurrent = 1;
+ } else if (sc.ch == '%') {
+ if (sc.chNext == '%' && sc.atLineStart) {
+ sc.SetState(SCE_PS_DSC_COMMENT);
+ sc.Forward();
+ if (sc.chNext == '+') {
+ sc.Forward();
+ sc.ForwardSetState(SCE_PS_DSC_VALUE);
+ }
+ } else {
+ sc.SetState(SCE_PS_COMMENT);
+ }
+ } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') &&
+ IsABaseNDigit(sc.chNext, 10)) {
+ sc.SetState(SCE_PS_NUMBER);
+ numRadix = 0;
+ numHasPoint = (sc.ch == '.');
+ numHasExponent = false;
+ numHasSign = (sc.ch == '+' || sc.ch == '-');
+ } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' &&
+ IsABaseNDigit(sc.GetRelative(2), 10)) {
+ sc.SetState(SCE_PS_NUMBER);
+ numRadix = 0;
+ numHasPoint = false;
+ numHasExponent = false;
+ numHasSign = true;
+ } else if (IsABaseNDigit(sc.ch, 10)) {
+ sc.SetState(SCE_PS_NUMBER);
+ numRadix = 0;
+ numHasPoint = false;
+ numHasExponent = false;
+ numHasSign = false;
+ } else if (!IsAWhitespaceChar(sc.ch)) {
+ sc.SetState(SCE_PS_NAME);
+ }
+
+ // Mark the start of tokens
+ if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT &&
+ sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) {
+ styler.Flush();
+ styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK));
+ styler.ColourTo(tokenpos, INDIC2_MASK);
+ styler.Flush();
+ styler.StartAt(tokenpos);
+ styler.StartSegment(tokenpos);
+ }
+ }
+
+ if (sc.atLineEnd)
+ styler.SetLineState(lineCurrent, nestTextCurrent);
+ }
+
+ sc.Complete();
+}
+
+static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[],
+ Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac??
+ if ((style & 31) == SCE_PS_PAREN_PROC) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+}
+
+static const char * const psWordListDesc[] = {
+ "PS Level 1 operators",
+ "PS Level 2 operators",
+ "PS Level 3 operators",
+ "RIP-specific operators",
+ "User-defined operators",
+ 0
+};
+
+LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc);
diff --git a/scintilla/src/LexPascal.cxx b/scintilla/src/LexPascal.cxx
new file mode 100644
index 0000000..545eaef
--- /dev/null
+++ b/scintilla/src/LexPascal.cxx
@@ -0,0 +1,592 @@
+// Scintilla source code edit control
+/** @file LexPascal.cxx
+ ** Lexer for Pascal.
+ ** Written by Laurent le Tynevez
+ ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
+ ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
+ ** Completely rewritten by Marko Njezic <sf@maxempire.com> October 2008
+ **/
+
+/*
+
+A few words about features of the new completely rewritten LexPascal...
+
+Generally speaking LexPascal tries to support all available Delphi features (up
+to Delphi 2009 at this time), including .NET specific features.
+
+~ HIGHLIGHTING:
+
+If you enable "lexer.pascal.smart.highlighting" property, some keywords will
+only be highlighted in appropriate context. As implemented those are keywords
+related to property and DLL exports declarations (similar to how Delphi IDE
+works).
+
+For example, keywords "read" and "write" will only be highlighted if they are in
+property declaration:
+
+property MyProperty: boolean read FMyProperty write FMyProperty;
+
+~ FOLDING:
+
+Folding is supported in the following cases:
+
+- Folding of stream-like comments
+- Folding of groups of consecutive line comments
+- Folding of preprocessor blocks (the following preprocessor blocks are
+supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION
+blocks), including nesting of preprocessor blocks up to 255 levels
+- Folding of code blocks on appropriate keywords (the following code blocks are
+supported: "begin, asm, record, try, case / end" blocks, class & object
+declarations and interface declarations)
+
+Remarks:
+
+- Folding of code blocks tries to handle all special cases in which folding
+should not occur. As implemented those are:
+
+1. Structure "record case / end" (there's only one "end" statement and "case" is
+ignored as fold point)
+2. Forward class declarations ("type TMyClass = class;") and object method
+declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are
+ignored as fold points
+3. Simplified complete class declarations ("type TMyClass = class(TObject);")
+are ignored as fold points
+4. Every other situation when class keyword doesn't actually start class
+declaration ("class procedure", "class function", "class of", "class var",
+"class property" and "class operator")
+
+- Folding of code blocks inside preprocessor blocks is disabled (any comments
+inside them will be folded fine) because there is no guarantee that complete
+code block will be contained inside folded preprocessor block in which case
+folded code block could end prematurely at the end of preprocessor block if
+there is no closing statement inside. This was done in order to properly process
+document that may contain something like this:
+
+type
+{$IFDEF UNICODE}
+ TMyClass = class(UnicodeAncestor)
+{$ELSE}
+ TMyClass = class(AnsiAncestor)
+{$ENDIF}
+ private
+ ...
+ public
+ ...
+ published
+ ...
+end;
+
+If class declarations were folded, then the second class declaration would end
+at "$ENDIF" statement, first class statement would end at "end;" statement and
+preprocessor "$IFDEF" block would go all the way to the end of document.
+However, having in mind all this, if you want to enable folding of code blocks
+inside preprocessor blocks, you can disable folding of preprocessor blocks by
+changing "fold.preprocessor" property, in which case everything inside them
+would be folded.
+
+~ KEYWORDS:
+
+The list of keywords that can be used in pascal.properties file (up to Delphi
+2009):
+
+- Keywords: absolute abstract and array as asm assembler automated begin case
+cdecl class const constructor deprecated destructor dispid dispinterface div do
+downto dynamic else end except export exports external far file final
+finalization finally for forward function goto if implementation in inherited
+initialization inline interface is label library message mod near nil not object
+of on or out overload override packed pascal platform private procedure program
+property protected public published raise record register reintroduce repeat
+resourcestring safecall sealed set shl shr static stdcall strict string then
+threadvar to try type unit unsafe until uses var varargs virtual while with xor
+
+- Keywords related to the "smart highlithing" feature: add default implements
+index name nodefault read readonly remove stored write writeonly
+
+- Keywords related to Delphi packages (in addition to all above): package
+contains requires
+
+*/
+
+#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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void GetRangeLowered(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static void GetForwardRangeLowered(unsigned int start,
+ CharacterSet &charSet,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) {
+ s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
+ i++;
+ }
+ s[i] = '\0';
+
+}
+
+enum {
+ stateInAsm = 0x1000,
+ stateInProperty = 0x2000,
+ stateInExport = 0x4000,
+ stateFoldInPreprocessor = 0x0100,
+ stateFoldInRecord = 0x0200,
+ stateFoldInPreprocessorLevelMask = 0x00FF,
+ stateFoldMaskAll = 0x0FFF
+};
+
+static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) {
+ WordList& keywords = *keywordlists[0];
+
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords.InList(s)) {
+ if (curLineState & stateInAsm) {
+ if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') {
+ curLineState &= ~stateInAsm;
+ sc.ChangeState(SCE_PAS_WORD);
+ } else {
+ sc.ChangeState(SCE_PAS_ASM);
+ }
+ } else {
+ bool ignoreKeyword = false;
+ if (strcmp(s, "asm") == 0) {
+ curLineState |= stateInAsm;
+ } else if (bSmartHighlighting) {
+ if (strcmp(s, "property") == 0) {
+ curLineState |= stateInProperty;
+ } else if (strcmp(s, "exports") == 0) {
+ curLineState |= stateInExport;
+ } else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) {
+ ignoreKeyword = true;
+ } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) {
+ ignoreKeyword = true;
+ } else if (!(curLineState & stateInProperty) &&
+ (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 ||
+ strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 ||
+ strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 ||
+ strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 ||
+ strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) {
+ ignoreKeyword = true;
+ }
+ }
+ if (!ignoreKeyword) {
+ sc.ChangeState(SCE_PAS_WORD);
+ }
+ }
+ } else if (curLineState & stateInAsm) {
+ sc.ChangeState(SCE_PAS_ASM);
+ }
+ sc.SetState(SCE_PAS_DEFAULT);
+}
+
+static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0;
+
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
+ CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
+ CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
+ CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}");
+
+ int curLine = styler.GetLine(startPos);
+ int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 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
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, curLineState);
+ }
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_PAS_NUMBER:
+ if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) {
+ sc.SetState(SCE_PAS_DEFAULT);
+ } else if (sc.ch == '-' || sc.ch == '+') {
+ if (sc.chPrev != 'E' && sc.chPrev != 'e') {
+ sc.SetState(SCE_PAS_DEFAULT);
+ }
+ }
+ break;
+ case SCE_PAS_IDENTIFIER:
+ if (!setWord.Contains(sc.ch)) {
+ ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
+ }
+ break;
+ case SCE_PAS_HEXNUMBER:
+ if (!setHexNumber.Contains(sc.ch)) {
+ sc.SetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_COMMENT:
+ case SCE_PAS_PREPROCESSOR:
+ if (sc.ch == '}') {
+ sc.ForwardSetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_COMMENT2:
+ case SCE_PAS_PREPROCESSOR2:
+ if (sc.Match('*', ')')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_STRING:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_PAS_STRINGEOL);
+ } else if (sc.ch == '\'' && sc.chNext == '\'') {
+ sc.Forward();
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_STRINGEOL:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_CHARACTER:
+ if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') {
+ sc.SetState(SCE_PAS_DEFAULT);
+ }
+ break;
+ case SCE_PAS_OPERATOR:
+ if (bSmartHighlighting && sc.chPrev == ';') {
+ curLineState &= ~(stateInProperty | stateInExport);
+ }
+ sc.SetState(SCE_PAS_DEFAULT);
+ break;
+ case SCE_PAS_ASM:
+ sc.SetState(SCE_PAS_DEFAULT);
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_PAS_DEFAULT) {
+ if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) {
+ sc.SetState(SCE_PAS_NUMBER);
+ } else if (setWordStart.Contains(sc.ch)) {
+ sc.SetState(SCE_PAS_IDENTIFIER);
+ } else if (sc.ch == '$' && !(curLineState & stateInAsm)) {
+ sc.SetState(SCE_PAS_HEXNUMBER);
+ } else if (sc.Match('{', '$')) {
+ sc.SetState(SCE_PAS_PREPROCESSOR);
+ } else if (sc.ch == '{') {
+ sc.SetState(SCE_PAS_COMMENT);
+ } else if (sc.Match("(*$")) {
+ sc.SetState(SCE_PAS_PREPROCESSOR2);
+ } else if (sc.Match('(', '*')) {
+ sc.SetState(SCE_PAS_COMMENT2);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(SCE_PAS_COMMENTLINE);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_PAS_STRING);
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_PAS_CHARACTER);
+ } else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) {
+ sc.SetState(SCE_PAS_OPERATOR);
+ } else if (curLineState & stateInAsm) {
+ sc.SetState(SCE_PAS_ASM);
+ }
+ }
+ }
+
+ if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) {
+ ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
+ }
+
+ sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2;
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+ int pos = styler.LineStart(line);
+ int eolPos = styler.LineStart(line + 1) - 1;
+ for (int i = pos; i < eolPos; i++) {
+ char ch = styler[i];
+ char chNext = styler.SafeGetCharAt(i + 1);
+ int style = styler.StyleAt(i);
+ if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) {
+ return true;
+ } else if (!IsASpaceOrTab(ch)) {
+ return false;
+ }
+ }
+ return false;
+}
+
+static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) {
+ return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask;
+}
+
+static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) {
+ lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask;
+ lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask;
+}
+
+static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
+ unsigned int startPos, Accessor &styler) {
+ CharacterSet setWord(CharacterSet::setAlpha);
+
+ char s[11]; // Size of the longest possible keyword + one additional character + null
+ GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));
+
+ unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent);
+
+ if (strcmp(s, "if") == 0 ||
+ strcmp(s, "ifdef") == 0 ||
+ strcmp(s, "ifndef") == 0 ||
+ strcmp(s, "ifopt") == 0 ||
+ strcmp(s, "region") == 0) {
+ nestLevel++;
+ SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
+ lineFoldStateCurrent |= stateFoldInPreprocessor;
+ levelCurrent++;
+ } else if (strcmp(s, "endif") == 0 ||
+ strcmp(s, "ifend") == 0 ||
+ strcmp(s, "endregion") == 0) {
+ nestLevel--;
+ SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
+ if (nestLevel == 0) {
+ lineFoldStateCurrent &= ~stateFoldInPreprocessor;
+ }
+ levelCurrent--;
+ if (levelCurrent < SC_FOLDLEVELBASE) {
+ levelCurrent = SC_FOLDLEVELBASE;
+ }
+ }
+}
+
+static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos,
+ Accessor &styler, bool includeChars = false) {
+ CharacterSet setWord(CharacterSet::setAlphaNum, "_");
+ unsigned int j = currentPos + 1;
+ char ch = styler.SafeGetCharAt(j);
+ while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
+ IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) {
+ j++;
+ ch = styler.SafeGetCharAt(j);
+ }
+ return j;
+}
+
+static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
+ int startPos, unsigned int endPos,
+ unsigned int lastStart, unsigned int currentPos, Accessor &styler) {
+ char s[100];
+ GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
+
+ if (strcmp(s, "record") == 0) {
+ lineFoldStateCurrent |= stateFoldInRecord;
+ levelCurrent++;
+ } else if (strcmp(s, "begin") == 0 ||
+ strcmp(s, "asm") == 0 ||
+ strcmp(s, "try") == 0 ||
+ (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) {
+ levelCurrent++;
+ } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) {
+ // "class" & "object" keywords require special handling...
+ bool ignoreKeyword = false;
+ unsigned int j = SkipWhiteSpace(currentPos, endPos, styler);
+ if (j < endPos) {
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_");
+ CharacterSet setWord(CharacterSet::setAlphaNum, "_");
+
+ if (styler.SafeGetCharAt(j) == ';') {
+ // Handle forward class declarations ("type TMyClass = class;")
+ // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;")
+ ignoreKeyword = true;
+ } else if (strcmp(s, "class") == 0) {
+ // "class" keyword has a few more special cases...
+ if (styler.SafeGetCharAt(j) == '(') {
+ // Handle simplified complete class declarations ("type TMyClass = class(TObject);")
+ j = SkipWhiteSpace(j, endPos, styler, true);
+ if (j < endPos && styler.SafeGetCharAt(j) == ')') {
+ j = SkipWhiteSpace(j, endPos, styler);
+ if (j < endPos && styler.SafeGetCharAt(j) == ';') {
+ ignoreKeyword = true;
+ }
+ }
+ } else if (setWordStart.Contains(styler.SafeGetCharAt(j))) {
+ char s2[11]; // Size of the longest possible keyword + one additional character + null
+ GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2));
+
+ if (strcmp(s2, "procedure") == 0 ||
+ strcmp(s2, "function") == 0 ||
+ strcmp(s2, "of") == 0 ||
+ strcmp(s2, "var") == 0 ||
+ strcmp(s2, "property") == 0 ||
+ strcmp(s2, "operator") == 0) {
+ ignoreKeyword = true;
+ }
+ }
+ }
+ }
+ if (!ignoreKeyword) {
+ levelCurrent++;
+ }
+ } else if (strcmp(s, "interface") == 0) {
+ // "interface" keyword requires special handling...
+ bool ignoreKeyword = true;
+ int j = lastStart - 1;
+ char ch = styler.SafeGetCharAt(j);
+ while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
+ IsStreamCommentStyle(styler.StyleAt(j)))) {
+ j--;
+ ch = styler.SafeGetCharAt(j);
+ }
+ if (j >= startPos && styler.SafeGetCharAt(j) == '=') {
+ ignoreKeyword = false;
+ }
+ if (!ignoreKeyword) {
+ levelCurrent++;
+ }
+ } else if (strcmp(s, "end") == 0) {
+ lineFoldStateCurrent &= ~stateFoldInRecord;
+ levelCurrent--;
+ if (levelCurrent < SC_FOLDLEVELBASE) {
+ levelCurrent = SC_FOLDLEVELBASE;
+ }
+ }
+}
+
+static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 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;
+ int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+
+ int lastStart = 0;
+ CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
+
+ 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)) {
+ levelCurrent++;
+ } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+ 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 (foldPreprocessor) {
+ if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') {
+ ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler);
+ } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*'
+ && styler.SafeGetCharAt(i + 2) == '$') {
+ ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler);
+ }
+ }
+
+ if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD)
+ {
+ // Store last word start point.
+ lastStart = i;
+ }
+ if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) {
+ if(setWord.Contains(ch) && !setWord.Contains(chNext)) {
+ ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler);
+ }
+ }
+
+ if (!IsASpace(ch))
+ visibleChars++;
+
+ 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);
+ }
+ int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
+ styler.SetLineState(lineCurrent, newLineState);
+ lineCurrent++;
+ levelPrev = levelCurrent;
+ visibleChars = 0;
+ }
+ }
+
+ // If we didn't reach the EOL in previous loop, store line level and whitespace information.
+ // The rest will be filled in later...
+ int lev = levelPrev;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ styler.SetLevel(lineCurrent, lev);
+}
+
+static const char * const pascalWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc);
diff --git a/scintilla/src/LexPerl.cxx b/scintilla/src/LexPerl.cxx
new file mode 100644
index 0000000..66bf34a
--- /dev/null
+++ b/scintilla/src/LexPerl.cxx
@@ -0,0 +1,1305 @@
+// Scintilla source code edit control
+/** @file LexPerl.cxx
+ ** Lexer for Perl.
+ **/
+// Copyright 1998-2008 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 <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"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Info for HERE document handling from perldata.pod (reformatted):
+// ----------------------------------------------------------------
+// A line-oriented form of quoting is based on the shell ``here-doc'' syntax.
+// Following a << you specify a string to terminate the quoted material, and
+// all lines following the current line down to the terminating string are
+// the value of the item.
+// * The terminating string may be either an identifier (a word), or some
+// quoted text.
+// * If quoted, the type of quotes you use determines the treatment of the
+// text, just as in regular quoting.
+// * An unquoted identifier works like double quotes.
+// * There must be no space between the << and the identifier.
+// (If you put a space it will be treated as a null identifier,
+// which is valid, and matches the first empty line.)
+// (This is deprecated, -w warns of this syntax)
+// * The terminating string must appear by itself (unquoted and
+// with no surrounding whitespace) on the terminating line.
+
+#define HERE_DELIM_MAX 256 // maximum length of HERE doc delimiter
+
+#define PERLNUM_BINARY 1 // order is significant: 1-4 cannot have a dot
+#define PERLNUM_HEX 2
+#define PERLNUM_OCTAL 3
+#define PERLNUM_FLOAT_EXP 4 // exponent part only
+#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
+
+static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler)
+{
+ // old-style keyword matcher; needed because GetCurrent() needs
+ // current segment to be committed, but we may abandon early...
+ char s[100];
+ 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 int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int fw,
+ int backFlag, unsigned int backPos, unsigned int endPos)
+{
+ // identifiers are recognized by Perl as barewords under some
+ // conditions, the following attempts to do the disambiguation
+ // by looking backward and forward; result in 2 LSB
+ int result = 0;
+ bool moreback = false; // true if passed newline/comments
+ bool brace = false; // true if opening brace found
+ // if BACK_NONE, neither operator nor keyword, so skip test
+ if (backFlag == BACK_NONE)
+ return result;
+ // first look backwards past whitespace/comments to set EOL flag
+ // (some disambiguation patterns must be on a single line)
+ if (backPos <= static_cast<unsigned int>(styler.LineStart(styler.GetLine(bk))))
+ moreback = true;
+ // look backwards at last significant lexed item for disambiguation
+ bk = backPos - 1;
+ int ch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
+ if (ch == '{' && !moreback) {
+ // {bareword: possible variable spec
+ brace = true;
+ } else if ((ch == '&' && styler.SafeGetCharAt(bk - 1) != '&')
+ // &bareword: subroutine call
+ || styler.Match(bk - 1, "->")
+ // ->bareword: part of variable spec
+ || styler.Match(bk - 2, "sub")) {
+ // sub bareword: subroutine declaration
+ // (implied BACK_KEYWORD, no keywords end in 'sub'!)
+ result |= 1;
+ }
+ // next, scan forward after word past tab/spaces only;
+ // if ch isn't one of '[{(,' we can skip the test
+ if ((ch == '{' || ch == '(' || ch == '['|| ch == ',')
+ && fw < endPos) {
+ while (ch = static_cast<unsigned char>(styler.SafeGetCharAt(fw)),
+ IsASpaceOrTab(ch) && fw < endPos) {
+ fw++;
+ }
+ if ((ch == '}' && brace)
+ // {bareword}: variable spec
+ || styler.Match(fw, "=>")) {
+ // [{(, bareword=>: hash literal
+ result |= 2;
+ }
+ }
+ return result;
+}
+
+static void skipWhitespaceComment(Accessor &styler, unsigned int &p)
+{
+ // when backtracking, we need to skip whitespace and comments
+ int style;
+ while ((p > 0) && (style = styler.StyleAt(p),
+ style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE))
+ p--;
+}
+
+static int styleBeforeBracePair(Accessor &styler, unsigned int bk)
+{
+ // backtrack to find open '{' corresponding to a '}', balanced
+ // return significant style to be tested for '/' disambiguation
+ int braceCount = 1;
+ if (bk == 0)
+ return SCE_PL_DEFAULT;
+ while (--bk > 0) {
+ if (styler.StyleAt(bk) == SCE_PL_OPERATOR) {
+ int bkch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
+ if (bkch == ';') { // early out
+ break;
+ } else if (bkch == '}') {
+ braceCount++;
+ } else if (bkch == '{') {
+ if (--braceCount == 0) break;
+ }
+ }
+ }
+ if (bk > 0 && braceCount == 0) {
+ // balanced { found, bk > 0, skip more whitespace/comments
+ bk--;
+ skipWhitespaceComment(styler, bk);
+ return styler.StyleAt(bk);
+ }
+ return SCE_PL_DEFAULT;
+}
+
+static int styleCheckIdentifier(Accessor &styler, unsigned int bk)
+{
+ // backtrack to classify sub-styles of identifier under test
+ // return sub-style to be tested for '/' disambiguation
+ if (styler.SafeGetCharAt(bk) == '>') // inputsymbol, like <foo>
+ return 1;
+ // backtrack to check for possible "->" or "::" before identifier
+ while (bk > 0 && styler.StyleAt(bk) == SCE_PL_IDENTIFIER) {
+ bk--;
+ }
+ while (bk > 0) {
+ int bkstyle = styler.StyleAt(bk);
+ if (bkstyle == SCE_PL_DEFAULT
+ || bkstyle == SCE_PL_COMMENTLINE) {
+ // skip whitespace, comments
+ } else if (bkstyle == SCE_PL_OPERATOR) {
+ // test for "->" and "::"
+ if (styler.Match(bk - 1, "->") || styler.Match(bk - 1, "::"))
+ return 2;
+ } else
+ return 3; // bare identifier
+ bk--;
+ }
+ return 0;
+}
+
+static int inputsymbolScan(Accessor &styler, unsigned int pos, unsigned int endPos)
+{
+ // looks forward for matching > on same line; a bit ugly
+ unsigned int fw = pos;
+ while (++fw < endPos) {
+ int fwch = static_cast<unsigned char>(styler.SafeGetCharAt(fw));
+ if (fwch == '\r' || fwch == '\n') {
+ return 0;
+ } else if (fwch == '>') {
+ if (styler.Match(fw - 2, "<=>")) // '<=>' case
+ return 0;
+ return fw - pos;
+ }
+ }
+ return 0;
+}
+
+static int podLineScan(Accessor &styler, unsigned int &pos, unsigned int endPos)
+{
+ // forward scan the current line to classify line for POD style
+ int state = -1;
+ while (pos <= endPos) {
+ int ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
+ if (ch == '\n' || ch == '\r' || pos >= endPos) {
+ if (ch == '\r' && styler.SafeGetCharAt(pos + 1) == '\n') pos++;
+ break;
+ }
+ if (IsASpaceOrTab(ch)) { // whitespace, take note
+ if (state == -1)
+ state = SCE_PL_DEFAULT;
+ } else if (state == SCE_PL_DEFAULT) { // verbatim POD line
+ state = SCE_PL_POD_VERB;
+ } else if (state != SCE_PL_POD_VERB) { // regular POD line
+ state = SCE_PL_POD;
+ }
+ pos++;
+ }
+ if (state == -1)
+ state = SCE_PL_DEFAULT;
+ return state;
+}
+
+static bool styleCheckSubPrototype(Accessor &styler, unsigned int bk)
+{
+ // backtrack to identify if we're starting a subroutine prototype
+ // we also need to ignore whitespace/comments:
+ // 'sub' [whitespace|comment] <identifier> [whitespace|comment]
+ styler.Flush();
+ skipWhitespaceComment(styler, bk);
+ if (bk == 0 || styler.StyleAt(bk) != SCE_PL_IDENTIFIER) // check identifier
+ return false;
+ while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_IDENTIFIER)) {
+ bk--;
+ }
+ skipWhitespaceComment(styler, bk);
+ if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD // check "sub" keyword
+ || !styler.Match(bk - 2, "sub")) // assume suffix is unique!
+ return false;
+ return true;
+}
+
+static bool isMatch(const char *sref, char *s)
+{
+ // match per-line delimiter - must kill trailing CR if CRLF
+ int i = strlen(s);
+ if (i != 0 && s[i - 1] == '\r')
+ s[i - 1] = '\0';
+ return (strcmp(sref, s) == 0);
+}
+
+static int actualNumStyle(int numberStyle) {
+ 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 int opposite(int ch) {
+ if (ch == '(') return ')';
+ if (ch == '[') return ']';
+ if (ch == '{') return '}';
+ if (ch == '<') return '>';
+ return ch;
+}
+
+static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+
+ // keywords that forces /PATTERN/ at all times; should track vim's behaviour
+ WordList reWords;
+ reWords.Set("elsif if split while");
+
+ // charset classes
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
+ CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC");
+ // lexing of "%*</" operators is non-trivial; these are missing in the set below
+ CharacterSet setPerlOperator(CharacterSet::setNone, "^&\\()-+=|{}[]:;>,?!.~");
+ CharacterSet setQDelim(CharacterSet::setNone, "qrwx");
+ CharacterSet setModifiers(CharacterSet::setAlpha);
+ CharacterSet setPreferRE(CharacterSet::setNone, "*/<%");
+ // setArray and setHash also accepts chars for special vars like $_,
+ // which are then truncated when the next char does not match setVar
+ CharacterSet setVar(CharacterSet::setAlphaNum, "#$_'", 0x80, true);
+ CharacterSet setArray(CharacterSet::setAlpha, "#$_+-", 0x80, true);
+ CharacterSet setHash(CharacterSet::setAlpha, "#$_!^+-", 0x80, true);
+ CharacterSet &setPOD = setModifiers;
+ CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@");
+ CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_");
+ CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*];");
+ // for format identifiers
+ CharacterSet setFormatStart(CharacterSet::setAlpha, "_=");
+ CharacterSet &setFormat = setHereDocDelim;
+
+ // Lexer for perl 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.
+
+ class HereDocCls { // Class to manage HERE doc sequence
+ public:
+ int State; // 0: '<<' encountered
+ // 1: collect the delimiter
+ // 2: here doc text (lines after the delimiter)
+ int Quote; // the char after '<<'
+ bool Quoted; // true if Quote in ('\'','"','`')
+ int DelimiterLength; // strlen(Delimiter)
+ 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';
+ }
+ void Append(int ch) {
+ Delimiter[DelimiterLength++] = static_cast<char>(ch);
+ Delimiter[DelimiterLength] = '\0';
+ }
+ ~HereDocCls() {
+ delete []Delimiter;
+ }
+ };
+ HereDocCls HereDoc; // TODO: FIFO for stacked here-docs
+
+ class QuoteCls { // Class to manage quote pairs
+ public:
+ int Rep;
+ int Count;
+ int Up, Down;
+ QuoteCls() {
+ this->New(1);
+ }
+ void New(int r = 1) {
+ Rep = r;
+ Count = 0;
+ Up = '\0';
+ Down = '\0';
+ }
+ void Open(int u) {
+ Count++;
+ Up = u;
+ Down = opposite(Up);
+ }
+ };
+ QuoteCls Quote;
+
+ // additional state for number lexing
+ int numState = PERLNUM_DECIMAL;
+ int dotCount = 0;
+
+ unsigned int endPos = startPos + length;
+
+ // Backtrack to beginning of style if required...
+ // If in a long distance lexical state, backtrack to find quote characters.
+ // Includes strings (may be multi-line), numbers (additional state), format
+ // bodies, as well as POD sections.
+ if (initStyle == SCE_PL_HERE_Q
+ || initStyle == SCE_PL_HERE_QQ
+ || initStyle == SCE_PL_HERE_QX
+ || initStyle == SCE_PL_FORMAT
+ ) {
+ int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM;
+ while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) {
+ startPos--;
+ }
+ startPos = styler.LineStart(styler.GetLine(startPos));
+ initStyle = styler.StyleAt(startPos - 1);
+ }
+ if (initStyle == SCE_PL_STRING_Q
+ || initStyle == SCE_PL_STRING_QQ
+ || initStyle == SCE_PL_STRING_QX
+ || initStyle == SCE_PL_STRING_QR
+ || initStyle == SCE_PL_STRING_QW
+ || initStyle == SCE_PL_REGEX
+ || initStyle == SCE_PL_REGSUBST
+ || initStyle == SCE_PL_STRING
+ || initStyle == SCE_PL_BACKTICKS
+ || initStyle == SCE_PL_CHARACTER
+ || initStyle == SCE_PL_NUMBER
+ || initStyle == SCE_PL_IDENTIFIER
+ || initStyle == SCE_PL_ERROR
+ || initStyle == SCE_PL_SUB_PROTOTYPE
+ ) {
+ while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) {
+ startPos--;
+ }
+ initStyle = SCE_PL_DEFAULT;
+ } else if (initStyle == SCE_PL_POD
+ || initStyle == SCE_PL_POD_VERB
+ ) {
+ // POD backtracking finds preceeding blank lines and goes back past them
+ int ln = styler.GetLine(startPos);
+ if (ln > 0) {
+ initStyle = styler.StyleAt(styler.LineStart(--ln));
+ if (initStyle == SCE_PL_POD || initStyle == SCE_PL_POD_VERB) {
+ while (ln > 0 && styler.GetLineState(ln) == SCE_PL_DEFAULT)
+ ln--;
+ }
+ startPos = styler.LineStart(++ln);
+ initStyle = styler.StyleAt(startPos - 1);
+ } else {
+ startPos = 0;
+ initStyle = SCE_PL_DEFAULT;
+ }
+ }
+
+ // backFlag, backPos are additional state to aid identifier corner cases.
+ // Look backwards past whitespace and comments in order to detect either
+ // operator or keyword. Later updated as we go along.
+ int backFlag = BACK_NONE;
+ unsigned int backPos = startPos;
+ if (backPos > 0) {
+ backPos--;
+ skipWhitespaceComment(styler, backPos);
+ if (styler.StyleAt(backPos) == SCE_PL_OPERATOR)
+ backFlag = BACK_OPERATOR;
+ else if (styler.StyleAt(backPos) == SCE_PL_WORD)
+ backFlag = BACK_KEYWORD;
+ backPos++;
+ }
+
+ StyleContext sc(startPos, endPos - startPos, initStyle, styler, static_cast<char>(STYLE_MAX));
+
+ for (; sc.More(); sc.Forward()) {
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_PL_OPERATOR:
+ sc.SetState(SCE_PL_DEFAULT);
+ backFlag = BACK_OPERATOR;
+ backPos = sc.currentPos;
+ break;
+ case SCE_PL_IDENTIFIER: // identifier, bareword, inputsymbol
+ if ((!setWord.Contains(sc.ch) && sc.ch != '\'')
+ || sc.Match('.', '.')
+ || sc.chPrev == '>') { // end of inputsymbol
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ break;
+ case SCE_PL_WORD: // keyword, plus special cases
+ if (!setWord.Contains(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) {
+ sc.ChangeState(SCE_PL_DATASECTION);
+ } else {
+ if ((strcmp(s, "format") == 0)) {
+ sc.SetState(SCE_PL_FORMAT_IDENT);
+ HereDoc.State = 0;
+ } else {
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ backFlag = BACK_KEYWORD;
+ backPos = sc.currentPos;
+ }
+ }
+ break;
+ case SCE_PL_SCALAR:
+ case SCE_PL_ARRAY:
+ case SCE_PL_HASH:
+ case SCE_PL_SYMBOLTABLE:
+ if (sc.Match(':', ':')) { // skip ::
+ sc.Forward();
+ } else if (!setVar.Contains(sc.ch)) {
+ if (sc.LengthCurrent() == 1) {
+ // Special variable: $(, $_ etc.
+ sc.Forward();
+ }
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ break;
+ case SCE_PL_NUMBER:
+ // if no early break, number style is terminated at "(go through)"
+ if (sc.ch == '.') {
+ if (sc.chNext == '.') {
+ // double dot is always an operator (go through)
+ } else if (numState <= PERLNUM_FLOAT_EXP) {
+ // non-decimal number or float exponent, consume next dot
+ sc.SetState(SCE_PL_OPERATOR);
+ break;
+ } else { // decimal or vectors allows dots
+ dotCount++;
+ if (numState == PERLNUM_DECIMAL) {
+ if (dotCount <= 1) // number with one dot in it
+ break;
+ if (IsADigit(sc.chNext)) { // really a vector
+ numState = PERLNUM_VECTOR;
+ break;
+ }
+ // number then dot (go through)
+ } else if (IsADigit(sc.chNext)) // vectors
+ break;
+ // vector then dot (go through)
+ }
+ } else if (sc.ch == '_') {
+ // permissive underscoring for number and vector literals
+ break;
+ } else if (numState == PERLNUM_DECIMAL) {
+ if (sc.ch == 'E' || sc.ch == 'e') { // exponent, sign
+ numState = PERLNUM_FLOAT_EXP;
+ if (sc.chNext == '+' || sc.chNext == '-') {
+ sc.Forward();
+ }
+ break;
+ } else if (IsADigit(sc.ch))
+ break;
+ // number then word (go through)
+ } else if (numState == PERLNUM_HEX) {
+ if (IsADigit(sc.ch, 16))
+ break;
+ } else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
+ if (IsADigit(sc.ch)) // vector
+ break;
+ if (setWord.Contains(sc.ch) && dotCount == 0) { // change to word
+ sc.ChangeState(SCE_PL_IDENTIFIER);
+ break;
+ }
+ // vector then word (go through)
+ } else if (IsADigit(sc.ch)) {
+ if (numState == PERLNUM_FLOAT_EXP) {
+ break;
+ } else if (numState == PERLNUM_OCTAL) {
+ if (sc.ch <= '7') break;
+ } else if (numState == PERLNUM_BINARY) {
+ if (sc.ch <= '1') break;
+ }
+ // mark invalid octal, binary numbers (go through)
+ numState = PERLNUM_BAD;
+ break;
+ }
+ // complete current number or vector
+ sc.ChangeState(actualNumStyle(numState));
+ sc.SetState(SCE_PL_DEFAULT);
+ break;
+ case SCE_PL_COMMENTLINE:
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ break;
+ case SCE_PL_HERE_DELIM:
+ if (HereDoc.State == 0) { // '<<' encountered
+ int delim_ch = sc.chNext;
+ int ws_skip = 0;
+ HereDoc.State = 1; // pre-init HERE doc class
+ HereDoc.Quote = sc.chNext;
+ HereDoc.Quoted = false;
+ HereDoc.DelimiterLength = 0;
+ HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+ if (IsASpaceOrTab(delim_ch)) {
+ // skip whitespace; legal only for quoted delimiters
+ unsigned int i = sc.currentPos + 1;
+ while ((i < endPos) && IsASpaceOrTab(delim_ch)) {
+ i++;
+ delim_ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
+ }
+ ws_skip = i - sc.currentPos - 1;
+ }
+ if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') {
+ // a quoted here-doc delimiter; skip any whitespace
+ sc.Forward(ws_skip + 1);
+ HereDoc.Quote = delim_ch;
+ HereDoc.Quoted = true;
+ } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext))
+ || ws_skip > 0) {
+ // left shift << or <<= operator cases
+ // restore position if operator
+ sc.ChangeState(SCE_PL_OPERATOR);
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ backFlag = BACK_OPERATOR;
+ backPos = sc.currentPos;
+ HereDoc.State = 0;
+ } else {
+ // specially handle initial '\' for identifier
+ if (ws_skip == 0 && HereDoc.Quote == '\\')
+ sc.Forward();
+ // 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 (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ } else if (!sc.atLineEnd) {
+ if (sc.Match('\\', static_cast<char>(HereDoc.Quote))) { // escaped quote
+ sc.Forward();
+ }
+ if (sc.ch != '\r') { // skip CR if CRLF
+ HereDoc.Append(sc.ch);
+ }
+ }
+ } else { // an unquoted here-doc delimiter
+ if (setHereDocDelim.Contains(sc.ch)) {
+ HereDoc.Append(sc.ch);
+ } else {
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ }
+ if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) {
+ sc.SetState(SCE_PL_ERROR);
+ HereDoc.State = 0;
+ }
+ }
+ break;
+ case SCE_PL_HERE_Q:
+ case SCE_PL_HERE_QQ:
+ case SCE_PL_HERE_QX: {
+ // also implies HereDoc.State == 2
+ sc.Complete();
+ while (!sc.atLineEnd)
+ sc.Forward();
+ char s[HERE_DELIM_MAX];
+ sc.GetCurrent(s, sizeof(s));
+ if (isMatch(HereDoc.Delimiter, s)) {
+ sc.SetState(SCE_PL_DEFAULT);
+ backFlag = BACK_NONE;
+ HereDoc.State = 0;
+ }
+ } break;
+ case SCE_PL_POD:
+ case SCE_PL_POD_VERB: {
+ unsigned int fw = sc.currentPos;
+ int ln = styler.GetLine(fw);
+ if (sc.atLineStart && sc.Match("=cut")) { // end of POD
+ sc.SetState(SCE_PL_POD);
+ sc.Forward(4);
+ sc.SetState(SCE_PL_DEFAULT);
+ styler.SetLineState(ln, SCE_PL_POD);
+ break;
+ }
+ int pod = podLineScan(styler, fw, endPos); // classify POD line
+ styler.SetLineState(ln, pod);
+ if (pod == SCE_PL_DEFAULT) {
+ if (sc.state == SCE_PL_POD_VERB) {
+ unsigned int fw2 = fw;
+ while (fw2 <= endPos && pod == SCE_PL_DEFAULT) {
+ fw = fw2++; // penultimate line (last blank line)
+ pod = podLineScan(styler, fw2, endPos);
+ styler.SetLineState(styler.GetLine(fw2), pod);
+ }
+ if (pod == SCE_PL_POD) { // truncate verbatim POD early
+ sc.SetState(SCE_PL_POD);
+ } else
+ fw = fw2;
+ } else
+ pod = SCE_PL_POD;
+ } else {
+ if (pod == SCE_PL_POD_VERB // still part of current paragraph
+ && (styler.GetLineState(ln - 1) == SCE_PL_POD)) {
+ pod = SCE_PL_POD;
+ styler.SetLineState(ln, pod);
+ } else if (pod == SCE_PL_POD
+ && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) {
+ pod = SCE_PL_POD_VERB;
+ styler.SetLineState(ln, pod);
+ }
+ sc.SetState(pod);
+ }
+ sc.Forward(fw - sc.currentPos); // commit style
+ } break;
+ case SCE_PL_REGEX:
+ case SCE_PL_STRING_QR:
+ if (Quote.Rep <= 0) {
+ if (!setModifiers.Contains(sc.ch))
+ sc.SetState(SCE_PL_DEFAULT);
+ } else if (!Quote.Up && !IsASpace(sc.ch)) {
+ Quote.Open(sc.ch);
+ } else if (sc.ch == '\\' && Quote.Up != '\\') {
+ sc.Forward();
+ } else if (sc.ch == Quote.Down) {
+ Quote.Count--;
+ if (Quote.Count == 0)
+ Quote.Rep--;
+ } else if (sc.ch == Quote.Up) {
+ Quote.Count++;
+ }
+ break;
+ case SCE_PL_REGSUBST:
+ if (Quote.Rep <= 0) {
+ if (!setModifiers.Contains(sc.ch))
+ sc.SetState(SCE_PL_DEFAULT);
+ } else if (!Quote.Up && !IsASpace(sc.ch)) {
+ Quote.Open(sc.ch);
+ } else if (sc.ch == '\\' && Quote.Up != '\\') {
+ sc.Forward();
+ } else if (Quote.Count == 0 && Quote.Rep == 1) {
+ // We matched something like s(...) or tr{...}, Perl 5.10
+ // appears to allow almost any character for use as the
+ // next delimiters. Whitespace and comments are accepted in
+ // between, but we'll limit to whitespace here.
+ // For '#', if no whitespace in between, it's a delimiter.
+ if (IsASpace(sc.ch)) {
+ // Keep going
+ } else if (sc.ch == '#' && IsASpaceOrTab(sc.chPrev)) {
+ sc.SetState(SCE_PL_DEFAULT);
+ } else {
+ Quote.Open(sc.ch);
+ }
+ } else if (sc.ch == Quote.Down) {
+ Quote.Count--;
+ if (Quote.Count == 0)
+ Quote.Rep--;
+ if (Quote.Up == Quote.Down)
+ Quote.Count++;
+ } else if (sc.ch == Quote.Up) {
+ Quote.Count++;
+ }
+ break;
+ case SCE_PL_STRING_Q:
+ case SCE_PL_STRING_QQ:
+ case SCE_PL_STRING_QX:
+ case SCE_PL_STRING_QW:
+ case SCE_PL_STRING:
+ case SCE_PL_CHARACTER:
+ case SCE_PL_BACKTICKS:
+ if (!Quote.Down && !IsASpace(sc.ch)) {
+ Quote.Open(sc.ch);
+ } else if (sc.ch == '\\' && Quote.Up != '\\') {
+ sc.Forward();
+ } else if (sc.ch == Quote.Down) {
+ Quote.Count--;
+ if (Quote.Count == 0)
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ } else if (sc.ch == Quote.Up) {
+ Quote.Count++;
+ }
+ break;
+ case SCE_PL_SUB_PROTOTYPE: {
+ int i = 0;
+ // forward scan; must all be valid proto characters
+ while (setSubPrototype.Contains(sc.GetRelative(i)))
+ i++;
+ if (sc.GetRelative(i) == ')') { // valid sub prototype
+ sc.Forward(i);
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ } else {
+ // abandon prototype, restart from '('
+ sc.ChangeState(SCE_PL_OPERATOR);
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ } break;
+ case SCE_PL_FORMAT: {
+ sc.Complete();
+ while (!sc.atLineEnd)
+ sc.Forward();
+ char s[10];
+ sc.GetCurrent(s, sizeof(s));
+ if (isMatch(".", s))
+ sc.SetState(SCE_PL_DEFAULT);
+ } break;
+ case SCE_PL_ERROR:
+ break;
+ }
+ // Needed for specific continuation styles (one follows the other)
+ switch (sc.state) {
+ // continued from SCE_PL_WORD
+ case SCE_PL_FORMAT_IDENT:
+ // occupies HereDoc state 3 to avoid clashing with HERE docs
+ if (IsASpaceOrTab(sc.ch)) { // skip whitespace
+ sc.ChangeState(SCE_PL_DEFAULT);
+ while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
+ sc.Forward();
+ sc.SetState(SCE_PL_FORMAT_IDENT);
+ }
+ if (setFormatStart.Contains(sc.ch)) { // identifier or '='
+ if (sc.ch != '=') {
+ do {
+ sc.Forward();
+ } while (setFormat.Contains(sc.ch));
+ }
+ while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
+ sc.Forward();
+ if (sc.ch == '=') {
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ HereDoc.State = 3;
+ } else {
+ // invalid indentifier; inexact fallback, but hey
+ sc.ChangeState(SCE_PL_IDENTIFIER);
+ sc.SetState(SCE_PL_DEFAULT);
+ }
+ } else {
+ sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier
+ }
+ backFlag = BACK_NONE;
+ break;
+ }
+
+ // Must check end of HereDoc states here before default state is handled
+ if (HereDoc.State == 1 && sc.atLineEnd) {
+ // Begin of here-doc (the line after the here-doc delimiter):
+ // Lexically, the here-doc starts from the next line after the >>, but the
+ // first line of here-doc seem to follow the style of the last EOL sequence
+ int st_new = SCE_PL_HERE_QQ;
+ HereDoc.State = 2;
+ if (HereDoc.Quoted) {
+ if (sc.state == SCE_PL_HERE_DELIM) {
+ // Missing quote at end of string! We are stricter than perl.
+ // Colour here-doc anyway while marking this bit as an error.
+ sc.ChangeState(SCE_PL_ERROR);
+ }
+ switch (HereDoc.Quote) {
+ case '\'': st_new = SCE_PL_HERE_Q ; break;
+ case '"' : st_new = SCE_PL_HERE_QQ; break;
+ case '`' : st_new = SCE_PL_HERE_QX; break;
+ }
+ } else {
+ if (HereDoc.Quote == '\\')
+ st_new = SCE_PL_HERE_Q;
+ }
+ sc.SetState(st_new);
+ }
+ if (HereDoc.State == 3 && sc.atLineEnd) {
+ // Start of format body.
+ HereDoc.State = 0;
+ sc.SetState(SCE_PL_FORMAT);
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_PL_DEFAULT) {
+ if (IsADigit(sc.ch) ||
+ (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) {
+ sc.SetState(SCE_PL_NUMBER);
+ backFlag = BACK_NONE;
+ numState = PERLNUM_DECIMAL;
+ dotCount = 0;
+ if (sc.ch == '0') { // hex,bin,octal
+ if (sc.chNext == 'x') {
+ numState = PERLNUM_HEX;
+ } else if (sc.chNext == 'b') {
+ numState = PERLNUM_BINARY;
+ } else if (IsADigit(sc.chNext)) {
+ numState = PERLNUM_OCTAL;
+ }
+ if (numState != PERLNUM_DECIMAL) {
+ sc.Forward();
+ }
+ } else if (sc.ch == 'v') { // vector
+ numState = PERLNUM_V_VECTOR;
+ }
+ } else if (setWord.Contains(sc.ch)) {
+ // if immediately prefixed by '::', always a bareword
+ sc.SetState(SCE_PL_WORD);
+ if (sc.chPrev == ':' && sc.GetRelative(-2) == ':') {
+ sc.ChangeState(SCE_PL_IDENTIFIER);
+ }
+ unsigned int bk = sc.currentPos;
+ unsigned int fw = sc.currentPos + 1;
+ // first check for possible quote-like delimiter
+ if (sc.ch == 's' && !setWord.Contains(sc.chNext)) {
+ sc.ChangeState(SCE_PL_REGSUBST);
+ Quote.New(2);
+ } else if (sc.ch == 'm' && !setWord.Contains(sc.chNext)) {
+ sc.ChangeState(SCE_PL_REGEX);
+ Quote.New();
+ } else if (sc.ch == 'q' && !setWord.Contains(sc.chNext)) {
+ sc.ChangeState(SCE_PL_STRING_Q);
+ Quote.New();
+ } else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) {
+ sc.ChangeState(SCE_PL_REGSUBST);
+ Quote.New(2);
+ } else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) {
+ sc.ChangeState(SCE_PL_REGSUBST);
+ Quote.New(2);
+ sc.Forward();
+ fw++;
+ } else if (sc.ch == 'q' && setQDelim.Contains(sc.chNext)
+ && !setWord.Contains(sc.GetRelative(2))) {
+ if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ);
+ else if (sc.chNext == 'x') sc.ChangeState(SCE_PL_STRING_QX);
+ else if (sc.chNext == 'r') sc.ChangeState(SCE_PL_STRING_QR);
+ else sc.ChangeState(SCE_PL_STRING_QW); // sc.chNext == 'w'
+ Quote.New();
+ sc.Forward();
+ fw++;
+ } else if (sc.ch == 'x' && (sc.chNext == '=' || // repetition
+ !setWord.Contains(sc.chNext) ||
+ (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) {
+ sc.ChangeState(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
+ if (sc.state == SCE_PL_WORD) {
+ while (setWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(fw))))
+ fw++;
+ if (!isPerlKeyword(styler.GetStartSegment(), fw, keywords, styler)) {
+ sc.ChangeState(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 (sc.state != SCE_PL_IDENTIFIER && bk > 0) {
+ if (disambiguateBareword(styler, bk, fw, backFlag, backPos, endPos))
+ sc.ChangeState(SCE_PL_IDENTIFIER);
+ }
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_PL_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_PL_STRING);
+ Quote.New();
+ Quote.Open(sc.ch);
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '\'') {
+ if (sc.chPrev == '&' && setWordStart.Contains(sc.chNext)) {
+ // Archaic call
+ sc.SetState(SCE_PL_IDENTIFIER);
+ } else {
+ sc.SetState(SCE_PL_CHARACTER);
+ Quote.New();
+ Quote.Open(sc.ch);
+ }
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '`') {
+ sc.SetState(SCE_PL_BACKTICKS);
+ Quote.New();
+ Quote.Open(sc.ch);
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '$') {
+ sc.SetState(SCE_PL_SCALAR);
+ if (sc.chNext == '{') {
+ sc.ForwardSetState(SCE_PL_OPERATOR);
+ } else if (IsASpace(sc.chNext)) {
+ sc.ForwardSetState(SCE_PL_DEFAULT);
+ } else {
+ sc.Forward();
+ if (sc.Match('`', '`') || sc.Match(':', ':')) {
+ sc.Forward();
+ }
+ }
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '@') {
+ sc.SetState(SCE_PL_ARRAY);
+ if (setArray.Contains(sc.chNext)) {
+ // no special treatment
+ } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
+ sc.Forward(2);
+ } else if (sc.chNext == '{' || sc.chNext == '[') {
+ sc.ForwardSetState(SCE_PL_OPERATOR);
+ } else {
+ sc.ChangeState(SCE_PL_OPERATOR);
+ }
+ backFlag = BACK_NONE;
+ } else if (setPreferRE.Contains(sc.ch)) {
+ // 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.
+ // A few symbols shares this code for disambiguation.
+ bool preferRE = false;
+ bool isHereDoc = sc.Match('<', '<');
+ bool hereDocSpace = false; // for: SCALAR [whitespace] '<<'
+ unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0;
+ unsigned int bkend;
+ sc.Complete();
+ styler.Flush();
+ if (styler.StyleAt(bk) == SCE_PL_DEFAULT)
+ hereDocSpace = true;
+ skipWhitespaceComment(styler, bk);
+ if (bk == 0) {
+ // avoid backward scanning breakage
+ preferRE = true;
+ } else {
+ int bkstyle = styler.StyleAt(bk);
+ int bkch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
+ switch(bkstyle) {
+ case SCE_PL_OPERATOR:
+ preferRE = true;
+ if (bkch == ')' || bkch == ']') {
+ preferRE = false;
+ } else if (bkch == '}') {
+ // backtrack by counting balanced brace pairs
+ // needed to test for variables like ${}, @{} etc.
+ bkstyle = styleBeforeBracePair(styler, bk);
+ if (bkstyle == SCE_PL_SCALAR
+ || bkstyle == SCE_PL_ARRAY
+ || bkstyle == SCE_PL_HASH
+ || bkstyle == SCE_PL_SYMBOLTABLE
+ || bkstyle == SCE_PL_OPERATOR) {
+ preferRE = false;
+ }
+ } else if (bkch == '+' || bkch == '-') {
+ if (bkch == static_cast<unsigned char>(styler.SafeGetCharAt(bk - 1))
+ && bkch != static_cast<unsigned char>(styler.SafeGetCharAt(bk - 2)))
+ // exceptions for operators: unary suffixes ++, --
+ preferRE = false;
+ }
+ break;
+ case SCE_PL_IDENTIFIER:
+ preferRE = true;
+ bkstyle = styleCheckIdentifier(styler, bk);
+ if ((bkstyle == 1) || (bkstyle == 2)) {
+ // inputsymbol or var with "->" or "::" before identifier
+ preferRE = false;
+ } else if (bkstyle == 3) {
+ // bare identifier, test cases follows:
+ if (sc.ch == '/') {
+ // if '/', /PATTERN/ unless digit/space immediately after '/'
+ // if '//', always expect defined-or operator to follow identifier
+ if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/')
+ preferRE = false;
+ } else if (sc.ch == '*' || sc.ch == '%') {
+ if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*'))
+ preferRE = false;
+ } else if (sc.ch == '<') {
+ if (IsASpace(sc.chNext) || sc.chNext == '=')
+ preferRE = false;
+ }
+ }
+ break;
+ case SCE_PL_SCALAR: // for $var<< case:
+ if (isHereDoc && hereDocSpace) // if SCALAR whitespace '<<', *always* a HERE doc
+ preferRE = true;
+ break;
+ case SCE_PL_WORD:
+ preferRE = true;
+ // for HERE docs, always true
+ if (sc.ch == '/') {
+ // adopt heuristics similar to vim-style rules:
+ // keywords always forced as /PATTERN/: split, if, elsif, while
+ // everything else /PATTERN/ unless digit/space immediately after '/'
+ // for '//', defined-or favoured unless special keywords
+ bkend = bk + 1;
+ while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) {
+ bk--;
+ }
+ if (isPerlKeyword(bk, bkend, reWords, styler))
+ break;
+ if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/')
+ preferRE = false;
+ } else if (sc.ch == '*' || sc.ch == '%') {
+ if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*'))
+ preferRE = false;
+ } else if (sc.ch == '<') {
+ if (IsASpace(sc.chNext) || sc.chNext == '=')
+ preferRE = false;
+ }
+ break;
+ // other styles uses the default, preferRE=false
+ case SCE_PL_POD:
+ case SCE_PL_HERE_Q:
+ case SCE_PL_HERE_QQ:
+ case SCE_PL_HERE_QX:
+ preferRE = true;
+ break;
+ }
+ }
+ backFlag = BACK_NONE;
+ if (isHereDoc) { // handle '<<', HERE doc
+ if (preferRE) {
+ sc.SetState(SCE_PL_HERE_DELIM);
+ HereDoc.State = 0;
+ } else { // << operator
+ sc.SetState(SCE_PL_OPERATOR);
+ sc.Forward();
+ }
+ } else if (sc.ch == '*') { // handle '*', typeglob
+ if (preferRE) {
+ sc.SetState(SCE_PL_SYMBOLTABLE);
+ if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
+ sc.Forward(2);
+ } else if (sc.chNext == '{') {
+ sc.ForwardSetState(SCE_PL_OPERATOR);
+ } else {
+ sc.Forward();
+ }
+ } else {
+ sc.SetState(SCE_PL_OPERATOR);
+ if (sc.chNext == '*') // exponentiation
+ sc.Forward();
+ }
+ } else if (sc.ch == '%') { // handle '%', hash
+ if (preferRE) {
+ sc.SetState(SCE_PL_HASH);
+ if (setHash.Contains(sc.chNext)) {
+ sc.Forward();
+ } else if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
+ sc.Forward(2);
+ } else if (sc.chNext == '{') {
+ sc.ForwardSetState(SCE_PL_OPERATOR);
+ } else {
+ sc.ChangeState(SCE_PL_OPERATOR);
+ }
+ } else {
+ sc.SetState(SCE_PL_OPERATOR);
+ }
+ } else if (sc.ch == '<') { // handle '<', inputsymbol
+ if (preferRE) {
+ // forward scan
+ int i = inputsymbolScan(styler, sc.currentPos, endPos);
+ if (i > 0) {
+ sc.SetState(SCE_PL_IDENTIFIER);
+ sc.Forward(i);
+ } else {
+ sc.SetState(SCE_PL_OPERATOR);
+ }
+ } else {
+ sc.SetState(SCE_PL_OPERATOR);
+ }
+ } else { // handle '/', regexp
+ if (preferRE) {
+ sc.SetState(SCE_PL_REGEX);
+ Quote.New();
+ Quote.Open(sc.ch);
+ } else { // / and // operators
+ sc.SetState(SCE_PL_OPERATOR);
+ if (sc.chNext == '/') {
+ sc.Forward();
+ }
+ }
+ }
+ } else if (sc.ch == '=' // POD
+ && setPOD.Contains(sc.chNext)
+ && sc.atLineStart) {
+ sc.SetState(SCE_PL_POD);
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '-' && setWordStart.Contains(sc.chNext)) { // extended '-' cases
+ unsigned int bk = sc.currentPos;
+ unsigned int fw = 2;
+ if (setSingleCharOp.Contains(sc.chNext) && // file test operators
+ !setWord.Contains(sc.GetRelative(2))) {
+ sc.SetState(SCE_PL_WORD);
+ } else {
+ // nominally a minus and bareword; find extent of bareword
+ while (setWord.Contains(sc.GetRelative(fw)))
+ fw++;
+ sc.SetState(SCE_PL_OPERATOR);
+ }
+ // force to bareword for hash key => or {variable literal} cases
+ if (disambiguateBareword(styler, bk, bk + fw, backFlag, backPos, endPos) & 2) {
+ sc.ChangeState(SCE_PL_IDENTIFIER);
+ }
+ backFlag = BACK_NONE;
+ } else if (sc.ch == '(' && sc.currentPos > 0) { // '(' or subroutine prototype
+ sc.Complete();
+ if (styleCheckSubPrototype(styler, sc.currentPos - 1)) {
+ sc.SetState(SCE_PL_SUB_PROTOTYPE);
+ backFlag = BACK_NONE;
+ } else {
+ sc.SetState(SCE_PL_OPERATOR);
+ }
+ } else if (setPerlOperator.Contains(sc.ch)) { // operators
+ sc.SetState(SCE_PL_OPERATOR);
+ if (sc.Match('.', '.')) { // .. and ...
+ sc.Forward();
+ if (sc.chNext == '.') sc.Forward();
+ }
+ } else if (sc.ch == 4 || sc.ch == 26) { // ^D and ^Z ends valid perl source
+ sc.SetState(SCE_PL_DATASECTION);
+ } else {
+ // keep colouring defaults
+ sc.Complete();
+ }
+ }
+ }
+ sc.Complete();
+}
+
+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 (!IsASpaceOrTab(ch))
+ 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
+
+ // property fold.perl.pod
+ // Enable folding Pod blocks when using the Perl lexer.
+ bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0;
+
+ // property fold.perl.package
+ // Enable folding packages when using the Perl lexer.
+ bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0;
+
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ 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');
+ bool atLineStart = ((chPrev == '\r') || (chPrev == '\n')) || 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_PL_OPERATOR) {
+ if (ch == '{') {
+ levelCurrent++;
+ } else if (ch == '}') {
+ 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 == '=' && isascii(chNext) && 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))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelPrev = levelCurrent;
+ visibleChars = 0;
+ }
+ 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;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static const char * const perlWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc, 8);
diff --git a/scintilla/src/LexPowerPro.cxx b/scintilla/src/LexPowerPro.cxx
new file mode 100644
index 0000000..641cd5f
--- /dev/null
+++ b/scintilla/src/LexPowerPro.cxx
@@ -0,0 +1,600 @@
+// Scintilla source code edit control
+// @file LexPowerPro.cxx
+// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com
+// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net)
+//
+// Lexer code heavily borrowed from:
+// LexAU3.cxx by Jos van der Zande
+// LexCPP.cxx by Neil Hodgson
+// LexVB.cxx by Neil Hodgson
+//
+// Changes:
+// 2008-10-25 - Initial release
+// 2008-10-26 - Changed how <name> is hilighted in 'function <name>' so that
+// local isFunction = "" and local functions = "" don't get falsely highlighted
+// 2008-12-14 - Added bounds checking for szKeyword and szDo
+// - Replaced SetOfCharacters with CharacterSet
+// - Made sure that CharacterSet::Contains is passed only positive values
+// - Made sure that the return value of Accessor::SafeGetCharAt is positive before
+// passsing to functions that require positive values like isspacechar()
+// - Removed unused visibleChars processing from ColourisePowerProDoc()
+// - Fixed bug with folding logic where line continuations didn't end where
+// they were supposed to
+// - Moved all helper functions to the top of the file
+//
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Platform.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "CharacterSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsStreamCommentStyle(int style) {
+ return style == SCE_POWERPRO_COMMENTBLOCK;
+}
+
+static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
+{
+ int nsPos = styler.LineStart(szLine);
+ int nePos = styler.LineStart(szLine + 1) - 2;
+ while (nsPos < nePos)
+ {
+ int stylech = styler.StyleAt(nsPos);
+ if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) {
+ char ch = styler.SafeGetCharAt(nePos);
+ char chPrev = styler.SafeGetCharAt(nePos-1);
+ char chPrevPrev = styler.SafeGetCharAt(nePos-2);
+ if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) {
+ if (chPrevPrev == ';' && chPrev == ';' && ch == '+')
+ return true;
+ else
+ return false;
+ }
+ }
+ nePos--; // skip to next char
+ }
+ return false;
+}
+
+// Routine to find first none space on the current line and return its Style
+// needed for comment lines not starting on pos 1
+static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
+{
+ int nsPos = styler.LineStart(szLine);
+ int nePos = styler.LineStart(szLine+1) - 1;
+ char ch = styler.SafeGetCharAt(nsPos);
+
+ while (ch > 0 && isspacechar(ch) && nsPos < nePos)
+ {
+ nsPos++; // skip to next char
+ ch = styler.SafeGetCharAt(nsPos);
+
+ }
+ return styler.StyleAt(nsPos);
+}
+
+//returns true if there is a function to highlight
+//used to highlight <name> in 'function <name>'
+static bool HasFunction(Accessor &styler, unsigned int currentPos) {
+
+ //check for presence of 'function '
+ return (styler.SafeGetCharAt(currentPos) == ' '
+ && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n'
+ && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o'
+ && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i'
+ && tolower(styler.SafeGetCharAt(currentPos-4)) == 't'
+ && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c'
+ && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n'
+ && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u'
+ && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f'
+ //only allow 'function ' to appear at the beginning of a line
+ && (styler.SafeGetCharAt(currentPos-9) == '\n'
+ || styler.SafeGetCharAt(currentPos-9) == '\r'
+ || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line
+ );
+}
+
+static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler, bool caseSensitive) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+
+ //define the character sets
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+
+ StyleContext sc(startPos, length, initStyle, styler);
+ char s_save[100]; //for last line highlighting
+
+ for (; sc.More(); sc.Forward()) {
+
+ // **********************************************
+ // save the total current word for eof processing
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+
+ if ((sc.ch > 0) && setWord.Contains(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';
+ }
+ }
+ // **********************************************
+ //
+
+ if (sc.atLineStart) {
+ if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) {
+ // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which
+ // ends with a line continuation by locking in the state upto this position.
+ sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
+ }
+ }
+
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_POWERPRO_OPERATOR:
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ break;
+
+ case SCE_POWERPRO_NUMBER:
+
+ if (!IsADigit(sc.ch))
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+
+ break;
+
+ case SCE_POWERPRO_IDENTIFIER:
+ //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized
+ if ((sc.ch > 0) && !setWord.Contains(sc.ch)){ // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately
+ char s[1000];
+ if (caseSensitive) {
+ sc.GetCurrent(s, sizeof(s));
+ } else {
+ sc.GetCurrentLowered(s, sizeof(s));
+ }
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_POWERPRO_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_POWERPRO_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_POWERPRO_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_POWERPRO_WORD4);
+ }
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_LINECONTINUE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ } else if (sc.Match('/', '*') || sc.Match('/', '/')) {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_COMMENTBLOCK:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_COMMENTLINE:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_DOUBLEQUOTEDSTRING:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_POWERPRO_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_SINGLEQUOTEDSTRING:
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_POWERPRO_STRINGEOL);
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_STRINGEOL:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+
+ case SCE_POWERPRO_VERBATIM:
+ if (sc.ch == '\"') {
+ if (sc.chNext == '\"') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
+ }
+ }
+ break;
+
+ case SCE_POWERPRO_ALTQUOTE:
+ if (sc.ch == '#') {
+ if (sc.chNext == '#') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
+ }
+ }
+ break;
+
+ case SCE_POWERPRO_FUNCTION:
+ if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_POWERPRO_DEFAULT) {
+ if (sc.Match('?', '\"')) {
+ sc.SetState(SCE_POWERPRO_VERBATIM);
+ sc.Forward();
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_POWERPRO_NUMBER);
+ }else if (sc.Match('?','#')) {
+ if (sc.ch == '?' && sc.chNext == '#') {
+ sc.SetState(SCE_POWERPRO_ALTQUOTE);
+ sc.Forward();
+ }
+ } else if (HasFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>'
+ sc.SetState(SCE_POWERPRO_FUNCTION);
+ } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label]
+ sc.SetState(SCE_POWERPRO_FUNCTION);
+ } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) {
+ sc.SetState(SCE_POWERPRO_IDENTIFIER);
+ } else if (sc.Match(";;+")) {
+ sc.SetState(SCE_POWERPRO_LINECONTINUE);
+ } else if (sc.Match('/', '*')) {
+ sc.SetState(SCE_POWERPRO_COMMENTBLOCK);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ sc.SetState(SCE_POWERPRO_COMMENTLINE);
+ } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line
+ sc.SetState(SCE_POWERPRO_COMMENTLINE);
+ } else if (sc.Match(";;")) {
+ sc.SetState(SCE_POWERPRO_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_POWERPRO_OPERATOR);
+ }
+ }
+ }
+
+ //*************************************
+ // Colourize the last word correctly
+ //*************************************
+ if (sc.state == SCE_POWERPRO_IDENTIFIER)
+ {
+ if (keywords.InList(s_save)) {
+ sc.ChangeState(SCE_POWERPRO_WORD);
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ else if (keywords2.InList(s_save)) {
+ sc.ChangeState(SCE_POWERPRO_WORD2);
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ else if (keywords3.InList(s_save)) {
+ sc.ChangeState(SCE_POWERPRO_WORD3);
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ else if (keywords4.InList(s_save)) {
+ sc.ChangeState(SCE_POWERPRO_WORD4);
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ else {
+ sc.SetState(SCE_POWERPRO_DEFAULT);
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ //define the character sets
+ CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
+ CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
+
+ bool isFoldingAll = true; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
+ int endPos = startPos + length;
+ int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly
+
+ // get settings from the config files for folding comments and preprocessor lines
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
+ bool foldCompact = true;
+
+ // Backtrack to previous line in case need to fix its fold status
+ int lineCurrent = styler.GetLine(startPos);
+ if (startPos > 0) {
+ isFoldingAll = false;
+ if (lineCurrent > 0) {
+ lineCurrent--;
+ startPos = styler.LineStart(lineCurrent);
+ }
+ }
+ // vars for style of previous/current/next lines
+ int style = GetStyleFirstWord(lineCurrent,styler);
+ int stylePrev = 0;
+
+ // find the first previous line without continuation character at the end
+ while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
+ (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
+ lineCurrent--;
+ startPos = styler.LineStart(lineCurrent);
+ }
+ if (lineCurrent > 0) {
+ stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
+ }
+ // vars for getting first word to check for keywords
+ bool FirstWordStart = false;
+ bool FirstWordEnd = false;
+
+ const unsigned int KEYWORD_MAX = 10;
+ char szKeyword[KEYWORD_MAX]="";
+ unsigned int szKeywordlen = 0;
+
+ char szDo[3]="";
+ int szDolen = 0;
+ bool DoFoundLast = false;
+
+ // var for indentlevel
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0) {
+ levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ }
+ int levelNext = levelCurrent;
+
+ int visibleChars = 0;
+ int functionCount = 0;
+
+ char chNext = styler.SafeGetCharAt(startPos);
+ char chPrev = '\0';
+ char chPrevPrev = '\0';
+ char chPrevPrevPrev = '\0';
+
+ for (int i = startPos; i < endPos; i++) {
+
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch > 0) && setWord.Contains(ch)) {
+ visibleChars++;
+ }
+
+ // get the syle for the current character neede to check in comment
+ int stylech = styler.StyleAt(i);
+
+ // get first word for the line for indent check max 9 characters
+ if (FirstWordStart && (!(FirstWordEnd))) {
+ if ((ch > 0) && !setWord.Contains(ch)) {
+ FirstWordEnd = true;
+ }
+ else if (szKeywordlen < KEYWORD_MAX - 1) {
+ szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
+ szKeyword[szKeywordlen] = '\0';
+ }
+ }
+
+ // start the capture of the first word
+ if (!(FirstWordStart)) {
+ if ((ch > 0) && (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/')) {
+ FirstWordStart = true;
+ if (szKeywordlen < KEYWORD_MAX - 1) {
+ szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
+ szKeyword[szKeywordlen] = '\0';
+ }
+ }
+ }
+ // only process this logic when not in comment section
+ if (stylech != SCE_POWERPRO_COMMENTLINE) {
+ if (DoFoundLast) {
+ if (DoFoundLast && (ch > 0) && setWord.Contains(ch)) {
+ DoFoundLast = false;
+ }
+ }
+ // find out if the word "do" is the last on a "if" line
+ if (FirstWordEnd && strcmp(szKeyword,"if") == 0) {
+ if (szDolen == 2) {
+ szDo[0] = szDo[1];
+ szDo[1] = static_cast<char>(tolower(ch));
+ szDo[2] = '\0';
+ if (strcmp(szDo,"do") == 0 ) {
+ DoFoundLast = true;
+ }
+ }
+ else if (szDolen < 2) {
+ szDo[szDolen++] = static_cast<char>(tolower(ch));
+ szDo[szDolen] = '\0';
+ }
+ }
+ }
+
+ // End of Line found so process the information
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+
+ // **************************
+ // Folding logic for Keywords
+ // **************************
+
+ // if a keyword is found on the current line and the line doesn't end with ;;+ (continuation)
+ // and we are not inside a commentblock.
+ if (szKeywordlen > 0 &&
+ (!(chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev ==';')) &&
+ ((!(IsStreamCommentStyle(style)) || foldInComment)) ) {
+
+ // only fold "if" last keyword is "then" (else its a one line if)
+ if (strcmp(szKeyword,"if") == 0 && DoFoundLast) {
+ levelNext++;
+ }
+ // create new fold for these words
+ if (strcmp(szKeyword,"for") == 0) {
+ levelNext++;
+ }
+
+ //handle folding for functions/labels
+ //Note: Functions and labels don't have an explicit end like [end function]
+ // 1. functions/labels end at the start of another function
+ // 2. functions/labels end at the end of the file
+ if ((strcmp(szKeyword,"function") == 0) || (szKeywordlen > 0 && szKeyword[0] == '@')) {
+ if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script)
+
+ if (functionCount > 0) {
+ levelCurrent--;
+ } else {
+ levelNext++;
+ }
+ functionCount++;
+
+ } else { //if just folding a small piece (by clicking on the minus sign next to the word)
+ levelCurrent--;
+ }
+ }
+
+ // end the fold for these words before the current line
+ if (strcmp(szKeyword,"endif") == 0 || strcmp(szKeyword,"endfor") == 0) {
+ levelNext--;
+ levelCurrent--;
+ }
+ // end the fold for these words before the current line and Start new fold
+ if (strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) {
+ levelCurrent--;
+ }
+ }
+ // Preprocessor and Comment folding
+ int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
+
+ // *********************************
+ // Folding logic for Comment blocks
+ // *********************************
+ if (foldComment && IsStreamCommentStyle(style)) {
+ // Start of a comment block
+ if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) {
+ levelNext++;
+ }
+ // fold till the last line for normal comment lines
+ else if (IsStreamCommentStyle(stylePrev)
+ && !(styleNext == SCE_POWERPRO_COMMENTLINE)
+ && stylePrev == SCE_POWERPRO_COMMENTLINE
+ && style == SCE_POWERPRO_COMMENTLINE) {
+ levelNext--;
+ }
+ // fold till the one but last line for Blockcomment lines
+ else if (IsStreamCommentStyle(stylePrev)
+ && !(styleNext == SCE_POWERPRO_COMMENTBLOCK)
+ && style == SCE_POWERPRO_COMMENTBLOCK) {
+ levelNext--;
+ levelCurrent--;
+ }
+ }
+
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+
+ // reset values for the next line
+ lineCurrent++;
+ stylePrev = style;
+ style = styleNext;
+ levelCurrent = levelNext;
+ visibleChars = 0;
+
+ // if the last characters are ;;+ then don't reset since the line continues on the next line.
+ if (chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev == ';') {
+ //do nothing
+ } else {
+ szKeywordlen = 0;
+ szDolen = 0;
+ FirstWordStart = false;
+ FirstWordEnd = false;
+ DoFoundLast = false;
+ //blank out keyword
+ for (unsigned int i = 0; i < KEYWORD_MAX; i++) {
+ szKeyword[i] = '\0';
+ }
+ }
+ }
+
+ // save the last processed characters
+ if ((ch > 0) && !isspacechar(ch)) {
+ chPrevPrevPrev = chPrevPrev;
+ chPrevPrev = chPrev;
+ chPrev = ch;
+ visibleChars++;
+ }
+ }
+
+ //close folds on the last line - without this a 'phantom'
+ //fold can appear when an open fold is on the last line
+ //this can occur because functions and labels don't have an explicit end
+ if (lineCurrent >= lastLine) {
+ int lev = 0;
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ styler.SetLevel(lineCurrent, lev);
+ }
+
+}
+
+static const char * const powerProWordLists[] = {
+ "Keyword list 1",
+ "Keyword list 2",
+ "Keyword list 3",
+ "Keyword list 4",
+ 0,
+ };
+
+static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColourisePowerProDoc(startPos, length, initStyle, keywordlists, styler, false);
+}
+
+LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists);
diff --git a/scintilla/src/LexPowerShell.cxx b/scintilla/src/LexPowerShell.cxx
new file mode 100644
index 0000000..32a3772
--- /dev/null
+++ b/scintilla/src/LexPowerShell.cxx
@@ -0,0 +1,175 @@
+// Scintilla source code edit control
+/** @file LexPowerShell.cxx
+ ** Lexer for PowerShell scripts.
+ **/
+// Copyright 2008 by Tim Gerundt <tim@gerundt.de>
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+ return ch >= 0x80 || isalnum(ch) || ch == '-';
+}
+
+static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+
+ styler.StartAt(startPos);
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_POWERSHELL_COMMENT) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_STRING) {
+ // This is a doubles quotes string
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_CHARACTER) {
+ // This is a single quote string
+ if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_NUMBER) {
+ if (!IsADigit(sc.ch)) {
+ sc.SetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_VARIABLE) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_OPERATOR) {
+ if (!isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_POWERSHELL_DEFAULT);
+ }
+ } else if (sc.state == SCE_POWERSHELL_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_POWERSHELL_KEYWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_POWERSHELL_CMDLET);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_POWERSHELL_ALIAS);
+ }
+ sc.SetState(SCE_POWERSHELL_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_POWERSHELL_DEFAULT) {
+ if (sc.ch == '#') {
+ sc.SetState(SCE_POWERSHELL_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_POWERSHELL_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_POWERSHELL_CHARACTER);
+ } else if (sc.ch == '$') {
+ sc.SetState(SCE_POWERSHELL_VARIABLE);
+ } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_POWERSHELL_NUMBER);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_POWERSHELL_OPERATOR);
+ } else if (IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_POWERSHELL_IDENTIFIER);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldPowerShellDoc(unsigned int startPos, int length, int,
+ WordList *[], Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ 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 (style == SCE_POWERSHELL_OPERATOR) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} else {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (!IsASpace(ch))
+ visibleChars++;
+ if (atEOL || (i == endPos-1)) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ }
+}
+
+static const char * const powershellWordLists[] = {
+ "Commands",
+ "Cmdlets",
+ "Aliases",
+ 0
+};
+
+LexerModule lmPowerShell(SCLEX_POWERSHELL, ColourisePowerShellDoc, "powershell", FoldPowerShellDoc, powershellWordLists);
+
diff --git a/scintilla/src/LexProgress.cxx b/scintilla/src/LexProgress.cxx
new file mode 100644
index 0000000..9a804c4
--- /dev/null
+++ b/scintilla/src/LexProgress.cxx
@@ -0,0 +1,279 @@
+// Scintilla source code edit control
+/** @file LexProgress.cxx
+ ** Lexer for Progress 4GL.
+ ** Based on LexCPP.cxx of Neil Hodgson <neilh@scintilla.org>
+ **/
+// Copyright 2006-2007 by Yuval Papish <Yuval@YuvCom.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/** TODO:
+WebSpeed support in html lexer
+Support "end triggers" expression of the triggers phrase
+Support more than 6 comments levels
+**/
+#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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+ return (ch < 0x80) && (isalpha(ch) || ch == '_');
+}
+
+enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0
+
+static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords1 = *keywordlists[0]; // regular keywords
+ WordList &keywords2 = *keywordlists[1]; // block opening keywords, only when SentenceStart
+ WordList &keywords3 = *keywordlists[2]; // block opening keywords
+ //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented
+
+
+ int visibleChars = 0;
+ int mask;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart) {
+ // Reset states to begining of colourise so no surprises
+ // if different sets of lines lexed.
+ visibleChars = 0;
+ }
+
+ // Handle line continuation generically.
+ if ((sc.state & 0xf) < SCE_4GL_COMMENT1) {
+ if (sc.ch == '~') {
+ if (sc.chNext > ' ') {
+ // skip special char after ~
+ sc.Forward();
+ continue;
+ }
+ else {
+ // Skip whitespace between ~ and EOL
+ while (sc.More() && (sc.chNext == ' ' || sc.chNext == '\t') ) {
+ sc.Forward();
+ }
+ if (sc.chNext == '\n' || sc.chNext == '\r') {
+ sc.Forward();
+ if (sc.ch == '\r' && sc.chNext == '\n') {
+ sc.Forward();
+ }
+ sc.Forward();
+ continue;
+ }
+ }
+ }
+ }
+ // Determine if a new state should be terminated.
+ mask = sc.state & 0x10;
+ switch (sc.state & 0xf) {
+ case SCE_4GL_OPERATOR:
+ sc.SetState(SCE_4GL_DEFAULT | mask);
+ break;
+ case SCE_4GL_NUMBER:
+ if (!(IsADigit(sc.ch))) {
+ sc.SetState(SCE_4GL_DEFAULT | mask);
+ }
+ break;
+ case SCE_4GL_IDENTIFIER:
+ if (!IsAWordChar(sc.ch) && sc.ch != '-') {
+ char s[1000];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if ((((sc.state & 0x10) == 0) && keywords2.InList(s)) || keywords3.InList(s)) {
+ sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart);
+ }
+ else if (keywords1.InList(s)) {
+ if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') ||
+ (s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) {
+ sc.ChangeState(SCE_4GL_END | ResetSentenceStart);
+ }
+ else if ((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') ||
+ (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) {
+ sc.ChangeState(SCE_4GL_WORD & SetSentenceStart);
+ }
+ else {
+ sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart);
+ }
+ }
+ sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10));
+ }
+ break;
+ case SCE_4GL_PREPROCESSOR:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart);
+ }
+ /* code removed to allow comments inside preprocessor
+ else if (sc.ch == '*' && sc.chNext == '/') {
+ sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */
+ break;
+ case SCE_4GL_STRING:
+ if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
+ }
+ break;
+ case SCE_4GL_CHARACTER:
+ if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
+ }
+ break;
+ default:
+ if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) {
+ if (sc.ch == '*' && sc.chNext == '/') {
+ sc.Forward();
+ if ((sc.state & 0xf) == SCE_4GL_COMMENT1) {
+ sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
+ }
+ else
+ sc.SetState((sc.state & 0x1f) - 1);
+ } else if (sc.ch == '/' && sc.chNext == '*') {
+ sc.Forward();
+ sc.SetState((sc.state & 0x1f) + 1);
+ }
+ }
+ }
+
+ // Determine if a new state should be entered.
+ mask = sc.state & 0x10;
+ if ((sc.state & 0xf) == SCE_4GL_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart);
+ } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
+ sc.SetState(SCE_4GL_IDENTIFIER | mask);
+ } else if (sc.ch == '/' && sc.chNext == '*') {
+ sc.SetState(SCE_4GL_COMMENT1 | mask);
+ sc.Forward();
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_4GL_STRING | ResetSentenceStart);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart);
+ } else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) {
+ sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart);
+ // Skip whitespace between & and preprocessor word
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ // Handle syntactical line termination
+ } else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) {
+ sc.SetState(sc.state & SetSentenceStart);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function"
+ to be recognized as a BlockBegin */
+
+ if (sc.ch == ':')
+ sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart);
+ /* else */
+ sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart);
+ }
+ }
+
+ if (!IsASpace(sc.ch)) {
+ visibleChars++;
+ }
+ }
+ sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return (style & 0xf) >= SCE_4GL_COMMENT1 ;
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle,
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = static_cast<char>(tolower(styler[startPos]));
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = static_cast<char>(tolower(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--;
+ }
+ }
+ else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) {
+ levelNext++;
+ }
+ else if ((style & 0xf) == SCE_4GL_END && (ch == 'e' || ch == 'f')) {
+ levelNext--;
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+}
+
+static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ FoldNoBox4glDoc(startPos, length, initStyle, styler);
+}
+
+static const char * const FglWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "Documentation comment keywords",
+ "Unused",
+ "Global classes and typedefs",
+ 0,
+ };
+
+LexerModule lmProgress(SCLEX_PROGRESS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists);
diff --git a/scintilla/src/LexPython.cxx b/scintilla/src/LexPython.cxx
new file mode 100644
index 0000000..815eeae
--- /dev/null
+++ b/scintilla/src/LexPython.cxx
@@ -0,0 +1,569 @@
+// Scintilla source code edit control
+/** @file LexPython.cxx
+ ** Lexer for Python.
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/* kwCDef, kwCTypeName only used for Cython */
+enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName };
+
+static const int indicatorWhitespace = 1;
+
+static bool IsPyComment(Accessor &styler, int pos, int len) {
+ return len > 0 && styler[pos] == '#';
+}
+
+enum literalsAllowed { litNone=0, litU=1, litB=2};
+
+static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) {
+ return
+ ((allowed & litB) && (ch == 'b' || ch == 'B')) ||
+ ((allowed & litU) && (ch == 'u' || ch == 'U'));
+}
+
+static bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) {
+ if (ch == '\'' || ch == '"')
+ return true;
+ if (IsPyStringTypeChar(ch, allowed)) {
+ if (chNext == '"' || chNext == '\'')
+ return true;
+ if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\''))
+ return true;
+ }
+ if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\''))
+ return true;
+
+ return false;
+}
+
+/* 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 GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex, literalsAllowed allowed) {
+ char ch = styler.SafeGetCharAt(i);
+ char chNext = styler.SafeGetCharAt(i + 1);
+
+ // Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), 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 (IsPyStringTypeChar(ch, allowed)) {
+ if (chNext == 'r' || chNext == 'R')
+ i += 2;
+ else
+ i += 1;
+ ch = styler.SafeGetCharAt(i);
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+
+ if (ch != '"' && ch != '\'') {
+ *nextIndex = i + 1;
+ return SCE_P_DEFAULT;
+ }
+
+ if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) {
+ *nextIndex = i + 3;
+
+ if (ch == '"')
+ return SCE_P_TRIPLEDOUBLE;
+ else
+ return SCE_P_TRIPLE;
+ } else {
+ *nextIndex = i + 1;
+
+ if (ch == '"')
+ return SCE_P_STRING;
+ else
+ return SCE_P_CHARACTER;
+ }
+}
+
+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 void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+
+ int endPos = startPos + length;
+
+ // Backtrack to previous line in case need to fix its tab whinging
+ int lineCurrent = styler.GetLine(startPos);
+ if (startPos > 0) {
+ if (lineCurrent > 0) {
+ lineCurrent--;
+ // Look for backslash-continued lines
+ while (lineCurrent > 0) {
+ int eolPos = styler.LineStart(lineCurrent) - 1;
+ int eolStyle = styler.StyleAt(eolPos);
+ if (eolStyle == SCE_P_STRING
+ || eolStyle == SCE_P_CHARACTER
+ || eolStyle == SCE_P_STRINGEOL) {
+ lineCurrent -= 1;
+ } else {
+ break;
+ }
+ }
+ startPos = styler.LineStart(lineCurrent);
+ }
+ initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1);
+ }
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+
+ // property tab.timmy.whinge.level
+ // For Python code, checks whether indenting is consistent.
+ // The default, 0 turns off indentation checking,
+ // 1 checks whether each line is potentially inconsistent with the previous line,
+ // 2 checks whether any space characters occur before a tab character in the indentation,
+ // 3 checks whether any spaces are in the indentation, and
+ // 4 checks for any tab characters in the indentation.
+ // 1 is a good level to use.
+ const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
+
+ // property lexer.python.literals.binary
+ // Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712.
+ bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0;
+
+ // property lexer.python.strings.u
+ // Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3.
+ literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone;
+
+ // property lexer.python.strings.b
+ // Set to 0 to not recognise Python 3 bytes literals b"x".
+ if (styler.GetPropertyInt("lexer.python.strings.b", 1))
+ allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litB);
+
+ // property lexer.python.strings.over.newline
+ // Set to 1 to allow strings to span newline characters.
+ bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0;
+
+ initStyle = initStyle & 31;
+ if (initStyle == SCE_P_STRINGEOL) {
+ initStyle = SCE_P_DEFAULT;
+ }
+
+ kwType kwLast = kwOther;
+ int spaceFlags = 0;
+ styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
+ bool base_n_number = false;
+
+ StyleContext sc(startPos, endPos - startPos, initStyle, styler);
+
+ bool indentGood = true;
+ int startIndicator = sc.currentPos;
+ bool inContinuedString = false;
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart) {
+ styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
+ indentGood = true;
+ if (whingeLevel == 1) {
+ indentGood = (spaceFlags & wsInconsistent) == 0;
+ } else if (whingeLevel == 2) {
+ indentGood = (spaceFlags & wsSpaceTab) == 0;
+ } else if (whingeLevel == 3) {
+ indentGood = (spaceFlags & wsSpace) == 0;
+ } else if (whingeLevel == 4) {
+ indentGood = (spaceFlags & wsTab) == 0;
+ }
+ if (!indentGood) {
+ styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0);
+ startIndicator = sc.currentPos;
+ }
+ }
+
+ if (sc.atLineEnd) {
+ if ((sc.state == SCE_P_DEFAULT) ||
+ (sc.state == SCE_P_TRIPLE) ||
+ (sc.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
+ sc.SetState(sc.state);
+ }
+ lineCurrent++;
+ if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
+ if (inContinuedString || stringsOverNewline) {
+ inContinuedString = false;
+ } else {
+ sc.ChangeState(SCE_P_STRINGEOL);
+ sc.ForwardSetState(SCE_P_DEFAULT);
+ }
+ }
+ if (!sc.More())
+ break;
+ }
+
+ bool needEOLCheck = false;
+
+ // Check for a state end
+ if (sc.state == SCE_P_OPERATOR) {
+ kwLast = kwOther;
+ sc.SetState(SCE_P_DEFAULT);
+ } else if (sc.state == SCE_P_NUMBER) {
+ if (!IsAWordChar(sc.ch) &&
+ !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
+ sc.SetState(SCE_P_DEFAULT);
+ }
+ } else if (sc.state == SCE_P_IDENTIFIER) {
+ if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ int style = SCE_P_IDENTIFIER;
+ if ((kwLast == kwImport) && (strcmp(s, "as") == 0)) {
+ style = SCE_P_WORD;
+ } else if (keywords.InList(s)) {
+ style = SCE_P_WORD;
+ } else if (kwLast == kwClass) {
+ style = SCE_P_CLASSNAME;
+ } else if (kwLast == kwDef) {
+ style = SCE_P_DEFNAME;
+ } else if (kwLast == kwCDef) {
+ int pos = sc.currentPos;
+ unsigned char ch = styler.SafeGetCharAt(pos, '\0');
+ while (ch != '\0') {
+ if (ch == '(') {
+ style = SCE_P_DEFNAME;
+ break;
+ } else if (ch == ':') {
+ style = SCE_P_CLASSNAME;
+ break;
+ } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
+ pos++;
+ ch = styler.SafeGetCharAt(pos, '\0');
+ } else {
+ break;
+ }
+ }
+ } else if (keywords2.InList(s)) {
+ style = SCE_P_WORD2;
+ }
+ sc.ChangeState(style);
+ sc.SetState(SCE_P_DEFAULT);
+ if (style == SCE_P_WORD) {
+ if (0 == strcmp(s, "class"))
+ kwLast = kwClass;
+ else if (0 == strcmp(s, "def"))
+ kwLast = kwDef;
+ else if (0 == strcmp(s, "import"))
+ kwLast = kwImport;
+ else if (0 == strcmp(s, "cdef"))
+ kwLast = kwCDef;
+ else if (0 == strcmp(s, "cimport"))
+ kwLast = kwImport;
+ else if (kwLast != kwCDef)
+ kwLast = kwOther;
+ } else if (kwLast != kwCDef) {
+ kwLast = kwOther;
+ }
+ }
+ } else if ((sc.state == SCE_P_COMMENTLINE) || (sc.state == SCE_P_COMMENTBLOCK)) {
+ if (sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_P_DEFAULT);
+ }
+ } else if (sc.state == SCE_P_DECORATOR) {
+ if (!IsAWordChar(sc.ch)) {
+ 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')) {
+ sc.Forward();
+ }
+ if (sc.chNext == '\n' || sc.chNext == '\r') {
+ inContinuedString = true;
+ } else {
+ // Don't roll over the newline.
+ sc.Forward();
+ }
+ } else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) {
+ sc.ForwardSetState(SCE_P_DEFAULT);
+ needEOLCheck = true;
+ } else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) {
+ sc.ForwardSetState(SCE_P_DEFAULT);
+ needEOLCheck = true;
+ }
+ } else if (sc.state == SCE_P_TRIPLE) {
+ if (sc.ch == '\\') {
+ sc.Forward();
+ } else if (sc.Match("\'\'\'")) {
+ sc.Forward();
+ sc.Forward();
+ sc.ForwardSetState(SCE_P_DEFAULT);
+ needEOLCheck = true;
+ }
+ } else if (sc.state == SCE_P_TRIPLEDOUBLE) {
+ if (sc.ch == '\\') {
+ sc.Forward();
+ } else if (sc.Match("\"\"\"")) {
+ sc.Forward();
+ sc.Forward();
+ sc.ForwardSetState(SCE_P_DEFAULT);
+ needEOLCheck = true;
+ }
+ }
+
+ if (!indentGood && !IsASpaceOrTab(sc.ch)) {
+ styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1);
+ startIndicator = sc.currentPos;
+ indentGood = true;
+ }
+
+ // One cdef line, clear kwLast only at end of line
+ if (kwLast == kwCDef && sc.atLineEnd) {
+ kwLast = kwOther;
+ }
+
+ // State exit code may have moved on to end of line
+ if (needEOLCheck && sc.atLineEnd) {
+ lineCurrent++;
+ styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
+ if (!sc.More())
+ break;
+ }
+
+ // Check for a new state starting character
+ if (sc.state == SCE_P_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) {
+ base_n_number = true;
+ sc.SetState(SCE_P_NUMBER);
+ } else if (sc.ch == '0' &&
+ (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) {
+ if (base2or8Literals) {
+ base_n_number = true;
+ sc.SetState(SCE_P_NUMBER);
+ } else {
+ sc.SetState(SCE_P_NUMBER);
+ sc.ForwardSetState(SCE_P_IDENTIFIER);
+ }
+ } else {
+ base_n_number = false;
+ sc.SetState(SCE_P_NUMBER);
+ }
+ } else if ((isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) || sc.ch == '`') {
+ 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), allowedLiterals)) {
+ unsigned int nextIndex = 0;
+ sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals));
+ while (nextIndex > (sc.currentPos + 1) && sc.More()) {
+ sc.Forward();
+ }
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_P_IDENTIFIER);
+ }
+ }
+ }
+ styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0);
+ sc.Complete();
+}
+
+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 bool IsQuoteLine(int line, Accessor &styler) {
+ int style = styler.StyleAt(styler.LineStart(line)) & 31;
+ return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
+}
+
+
+static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/,
+ WordList *[], Accessor &styler) {
+ const int maxPos = startPos + length;
+ const int maxLines = styler.GetLine(maxPos - 1); // Requested last line
+ const int docLines = styler.GetLine(styler.Length() - 1); // Available last line
+
+ // property fold.comment.python
+ // This option enables folding multi-line comments when using the Python lexer.
+ const bool foldComment = styler.GetPropertyInt("fold.comment.python") != 0;
+
+ // property fold.quotes.python
+ // This option enables folding multi-line quoted strings when using the Python lexer.
+ const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 0;
+
+ const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;
+
+ // Backtrack to previous non-blank line so we can determine indent level
+ // for any white space lines (needed esp. within triple quoted strings)
+ // and so we can fix any preceding fold level (which is why we go back
+ // at least one line in all cases)
+ int spaceFlags = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ while (lineCurrent > 0) {
+ lineCurrent--;
+ indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
+ (!IsCommentLine(lineCurrent, styler)) &&
+ (!IsQuoteLine(lineCurrent, styler)))
+ break;
+ }
+ int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+ // Set up initial loop state
+ startPos = styler.LineStart(lineCurrent);
+ int prev_state = SCE_P_DEFAULT & 31;
+ if (lineCurrent >= 1)
+ prev_state = styler.StyleAt(startPos - 1) & 31;
+ int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE));
+ int prevComment = 0;
+ if (lineCurrent >= 1)
+ prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
+
+ // Process all characters to end of requested range or end of any triple quote
+ // or comment that hangs over the end of the range. Cap processing in all cases
+ // to end of document (in case of unclosed quote or comment at end).
+ while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote || prevComment)) {
+
+ // Gather info
+ int lev = indentCurrent;
+ int lineNext = lineCurrent + 1;
+ int indentNext = indentCurrent;
+ int quote = false;
+ if (lineNext <= docLines) {
+ // Information about next line is only available if not at end of document
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ int style = styler.StyleAt(styler.LineStart(lineNext)) & 31;
+ quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
+ }
+ const int quote_start = (quote && !prevQuote);
+ const int quote_continue = (quote && prevQuote);
+ const int comment = foldComment && IsCommentLine(lineCurrent, styler);
+ const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
+ IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
+ const int comment_continue = (comment && prevComment);
+ if ((!quote || !prevQuote) && !comment)
+ indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+ if (quote)
+ indentNext = indentCurrentLevel;
+ if (indentNext & SC_FOLDLEVELWHITEFLAG)
+ indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+ if (quote_start) {
+ // Place fold point at start of triple quoted string
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (quote_continue || prevQuote) {
+ // Add level to rest of lines in the string
+ lev = lev + 1;
+ } else if (comment_start) {
+ // Place fold point at start of a block of comments
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (comment_continue) {
+ // Add level to rest of lines in the block
+ lev = lev + 1;
+ }
+
+ // Skip past any blank lines for next indent level info; we skip also
+ // comments (all comments, not just those starting in column 0)
+ // which effectively folds them into surrounding code rather
+ // than screwing up folding.
+
+ while (!quote &&
+ (lineNext < docLines) &&
+ ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
+ (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+
+ lineNext++;
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ }
+
+ const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
+ const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);
+
+ // Now set all the indent levels on the lines we skipped
+ // Do this from end to start. Once we encounter one line
+ // which is indented more than the line after the end of
+ // the comment-block, use the level of the block before
+
+ int skipLine = lineNext;
+ int skipLevel = levelAfterComments;
+
+ while (--skipLine > lineCurrent) {
+ int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+ if (foldCompact) {
+ if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
+ skipLevel = levelBeforeComments;
+
+ int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+ styler.SetLevel(skipLine, skipLevel | whiteFlag);
+ } else {
+ if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments &&
+ !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
+ !IsCommentLine(skipLine, styler))
+ skipLevel = levelBeforeComments;
+
+ styler.SetLevel(skipLine, skipLevel);
+ }
+ }
+
+ // Set fold header on non-quote/non-comment line
+ if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+
+ // Keep track of triple quote and block comment state of previous line
+ prevQuote = quote;
+ prevComment = comment_start || comment_continue;
+
+ // Set fold level for this line and move to next line
+ styler.SetLevel(lineCurrent, lev);
+ indentCurrent = indentNext;
+ lineCurrent = lineNext;
+ }
+
+ // NOTE: Cannot set level of last line here because indentCurrent doesn't have
+ // header flag set; the loop above is crafted to take care of this case!
+ //styler.SetLevel(lineCurrent, indentCurrent);
+}
+
+static const char *const pythonWordListDesc[] = {
+ "Keywords",
+ "Highlighted identifiers",
+ 0
+};
+
+LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc, "python", FoldPyDoc,
+ pythonWordListDesc);
+
diff --git a/scintilla/src/LexR.cxx b/scintilla/src/LexR.cxx
new file mode 100644
index 0000000..06c4dcd
--- /dev/null
+++ b/scintilla/src/LexR.cxx
@@ -0,0 +1,213 @@
+// Scintilla source code edit control
+/** @file Lexr.cxx
+ ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer).
+ **
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const 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 IsAnOperator(const int ch) {
+ if (isascii(ch) && 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 == '}' || ch == '{' || ch == '[' ||
+ ch == ']')
+ return true;
+ return false;
+}
+
+static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+
+
+ // Do not leak onto next line
+ if (initStyle == SCE_R_INFIXEOL)
+ initStyle = SCE_R_DEFAULT;
+
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart && (sc.state == SCE_R_STRING)) {
+ // Prevent SCE_R_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_R_STRING);
+ }
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_R_OPERATOR) {
+ sc.SetState(SCE_R_DEFAULT);
+ } else if (sc.state == SCE_R_NUMBER) {
+ if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_R_DEFAULT);
+ }
+ } else if (sc.state == SCE_R_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_R_KWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_R_BASEKWORD);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_R_OTHERKWORD);
+ }
+ sc.SetState(SCE_R_DEFAULT);
+ }
+ } else if (sc.state == SCE_R_COMMENT) {
+ if (sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_R_DEFAULT);
+ }
+ } else if (sc.state == SCE_R_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_R_DEFAULT);
+ }
+ } else if (sc.state == SCE_R_INFIX) {
+ if (sc.ch == '%') {
+ sc.ForwardSetState(SCE_R_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_R_INFIXEOL);
+ sc.ForwardSetState(SCE_R_DEFAULT);
+ }
+ }else if (sc.state == SCE_R_STRING2) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_R_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_R_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_R_NUMBER);
+ } else if (IsAWordStart(sc.ch) ) {
+ sc.SetState(SCE_R_IDENTIFIER);
+ } else if (sc.Match('#')) {
+ sc.SetState(SCE_R_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_R_STRING);
+ } else if (sc.ch == '%') {
+ sc.SetState(SCE_R_INFIX);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_R_STRING2);
+ } else if (IsAnOperator(sc.ch)) {
+ sc.SetState(SCE_R_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldRDoc(unsigned int startPos, int length, int, WordList *[],
+ Accessor &styler) {
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ 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 (style == SCE_R_OPERATOR) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} else {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+}
+
+
+static const char * const RWordLists[] = {
+ "Language Keywords",
+ "Base / Default package function",
+ "Other Package Functions",
+ "Unused",
+ "Unused",
+ 0,
+ };
+
+
+
+LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists);
diff --git a/scintilla/src/LexRebol.cxx b/scintilla/src/LexRebol.cxx
new file mode 100644
index 0000000..adbabe8
--- /dev/null
+++ b/scintilla/src/LexRebol.cxx
@@ -0,0 +1,322 @@
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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);
+
diff --git a/scintilla/src/LexRuby.cxx b/scintilla/src/LexRuby.cxx
new file mode 100644
index 0000000..afe350d
--- /dev/null
+++ b/scintilla/src/LexRuby.cxx
@@ -0,0 +1,1715 @@
+// Scintilla source code edit control
+/** @file LexRuby.cxx
+ ** Lexer for Ruby.
+ **/
+// Copyright 2001- by Clemens Wyss <wys@helbling.ch>
+// 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"
+
+#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) {
+ // Error: scintilla's KeyWords.h includes '.' as a word-char
+ // we want to separate things that can take methods from the
+ // methods.
+ return isHighBitChar(ch) || isalnum(ch) || 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[MAX_KEYWORD_LENGTH];
+ 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];
+ }
+ s[j] = '\0';
+ int chAttr;
+ if (0 == strcmp(prevWord, "class"))
+ chAttr = SCE_RB_CLASSNAME;
+ else if (0 == strcmp(prevWord, "module"))
+ chAttr = SCE_RB_MODULE_NAME;
+ else if (0 == strcmp(prevWord, "def"))
+ 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++;
+ }
+ return true;
+}
+
+// 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;
+}
+
+//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.
+
+static void redo_char(int &i, char &ch, char &chNext, char &chNext2,
+ int &state) {
+ i--;
+ chNext2 = chNext;
+ chNext = ch;
+ state = SCE_RB_DEFAULT;
+}
+
+static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {
+ i++;
+ ch = chNext;
+ chNext = chNext2;
+}
+
+// precondition: startPos points to one after the EOL char
+static bool currLineContainsHereDelims(int& startPos,
+ Accessor &styler) {
+ if (startPos <= 1)
+ return false;
+
+ 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;
+}
+
+// This class is used by the enter and exit methods, so it needs
+// to be hoisted out of the function.
+
+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(const QuoteCls& q) {
+ // copy constructor -- use this for copying in
+ Count = q.Count;
+ Up = q.Up;
+ Down = q.Down;
+ }
+ QuoteCls& operator=(const QuoteCls& q) { // assignment constructor
+ if (this != &q) {
+ Count = q.Count;
+ Up = q.Up;
+ Down = q.Down;
+ }
+ return *this;
+ }
+
+};
+
+
+static void enterInnerExpression(int *p_inner_string_types,
+ int *p_inner_expn_brace_counts,
+ QuoteCls *p_inner_quotes,
+ int& inner_string_count,
+ int& state,
+ int& brace_counts,
+ QuoteCls curr_quote
+ ) {
+ p_inner_string_types[inner_string_count] = state;
+ state = SCE_RB_DEFAULT;
+ p_inner_expn_brace_counts[inner_string_count] = brace_counts;
+ brace_counts = 0;
+ p_inner_quotes[inner_string_count] = curr_quote;
+ ++inner_string_count;
+}
+
+static void exitInnerExpression(int *p_inner_string_types,
+ int *p_inner_expn_brace_counts,
+ QuoteCls *p_inner_quotes,
+ int& inner_string_count,
+ int& state,
+ int& brace_counts,
+ QuoteCls& curr_quote
+ ) {
+ --inner_string_count;
+ state = p_inner_string_types[inner_string_count];
+ brace_counts = p_inner_expn_brace_counts[inner_string_count];
+ curr_quote = p_inner_quotes[inner_string_count];
+}
+
+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;
+}
+
+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;
+}
+
+// Look at chars up to but not including endPos
+// Don't look at styles in case we're looking forward
+
+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) {
+
+ // 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];
+
+ 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;
+
+ QuoteCls Quote;
+
+ int numDots = 0; // For numbers --
+ // Don't start lexing in the middle of a num
+
+ synchronizeDocStart(startPos, length, initStyle, styler, // ref args
+ false);
+
+ 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;
+
+ char chPrev = styler.SafeGetCharAt(startPos - 1);
+ char chNext = styler.SafeGetCharAt(startPos);
+ bool is_real_number = true; // Differentiate between constants and ?-sequences.
+ // Ruby uses a different mask because bad indentation is marked by oring with 32
+ styler.StartAt(startPos, 127);
+ styler.StartSegment(startPos);
+
+ 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";
+
+ // In most cases a value of 2 should be ample for the code in the
+ // Ruby library, and the code the user is likely to enter.
+ // For example,
+ // fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}"
+ // if options[:verbose]
+ // from fileutils.rb nests to a level of 2
+ // If the user actually hits a 6th occurrence of '#{' in a double-quoted
+ // string (including regex'es, %Q, %<sym>, %w, and other strings
+ // that interpolate), it will stay as a string. The problem with this
+ // is that quotes might flip, a 7th '#{' will look like a comment,
+ // and code-folding might be wrong.
+
+ // If anyone runs into this problem, I recommend raising this
+ // value slightly higher to replacing the fixed array with a linked
+ // list. Keep in mind this code will be called everytime the lexer
+ // is invoked.
+
+#define INNER_STRINGS_MAX_COUNT 5
+ // These vars track our instances of "...#{,,,%Q<..#{,,,}...>,,,}..."
+ int inner_string_types[INNER_STRINGS_MAX_COUNT];
+ // Track # braces when we push a new #{ thing
+ int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT];
+ QuoteCls inner_quotes[INNER_STRINGS_MAX_COUNT];
+ int inner_string_count = 0;
+ int brace_counts = 0; // Number of #{ ... } things within an expression
+
+ int i;
+ for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) {
+ inner_string_types[i] = 0;
+ inner_expn_brace_counts[i] = 0;
+ }
+ for (i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = chNext2;
+ chPrev = ' ';
+ 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;
+ }
+
+ // Regular transitions
+ if (state == SCE_RB_DEFAULT) {
+ if (isSafeDigit(ch)) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_RB_NUMBER;
+ is_real_number = true;
+ 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 = SCE_RB_COMMENTLINE;
+ } else if (ch == '=') {
+ // =begin indicates the start of a comment (doc) block
+ 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);
+ styler.ColourTo(i, SCE_RB_OPERATOR);
+ preferRE = true;
+ }
+ } else if (ch == '"') {
+ styler.ColourTo(i - 1, state);
+ 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);
+ 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 (preferRE && !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 (ch == '?') {
+ styler.ColourTo(i - 1, state);
+ if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') {
+ styler.ColourTo(i, SCE_RB_OPERATOR);
+ } else {
+ // It's the start of a character code escape sequence
+ // Color it as a number.
+ state = SCE_RB_NUMBER;
+ is_real_number = false;
+ }
+ } 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.
+
+ if (ch == '{') {
+ ++brace_counts;
+ preferRE = true;
+ } else if (ch == '}' && --brace_counts < 0
+ && inner_string_count > 0) {
+ styler.ColourTo(i, SCE_RB_OPERATOR);
+ exitInnerExpression(inner_string_types,
+ inner_expn_brace_counts,
+ inner_quotes,
+ inner_string_count,
+ state, brace_counts, Quote);
+ } else {
+ 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 (!is_real_number) {
+ if (ch != '\\') {
+ styler.ColourTo(i, state);
+ state = SCE_RB_DEFAULT;
+ preferRE = false;
+ } else if (strchr("\\ntrfvaebs", chNext)) {
+ // Terminal escape sequence -- handle it next time
+ // Nothing more to do this time through the loop
+ } else if (chNext == 'C' || chNext == 'M') {
+ if (chNext2 != '-') {
+ // \C or \M ends the sequence -- handle it next time
+ } else {
+ // Move from abc?\C-x
+ // ^
+ // to
+ // ^
+ i += 2;
+ ch = chNext2;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ } else if (chNext == 'c') {
+ // Stay here, \c is a combining sequence
+ advance_char(i, ch, chNext, chNext2); // pass by ref
+ } else {
+ // ?\x, including ?\\ is final.
+ styler.ColourTo(i + 1, state);
+ state = SCE_RB_DEFAULT;
+ preferRE = false;
+ advance_char(i, ch, chNext, chNext2);
+ }
+ } else 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;
+ }
+ }
+ if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
+ styler.ColourTo(i - 1, state);
+ state = SCE_RB_ERROR;
+ preferRE = false;
+ }
+ }
+ } 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);
+ }
+ 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 == '#' ) {
+ if (chNext == '{'
+ && inner_string_count < INNER_STRINGS_MAX_COUNT) {
+ // process #{ ... }
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_RB_OPERATOR);
+ enterInnerExpression(inner_string_types,
+ inner_expn_brace_counts,
+ inner_quotes,
+ inner_string_count,
+ state,
+ brace_counts,
+ Quote);
+ preferRE = true;
+ // Skip one
+ advance_char(i, ch, chNext, chNext2);
+ } else {
+ //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++;
+ } else if (ch == '#' && chNext == '{'
+ && inner_string_count < INNER_STRINGS_MAX_COUNT
+ && state != SCE_RB_CHARACTER
+ && state != SCE_RB_STRING_Q) {
+ // process #{ ... }
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i + 1, SCE_RB_OPERATOR);
+ enterInnerExpression(inner_string_types,
+ inner_expn_brace_counts,
+ inner_quotes,
+ inner_string_count,
+ state,
+ brace_counts,
+ Quote);
+ preferRE = true;
+ // Skip one
+ advance_char(i, ch, chNext, chNext2);
+ }
+ }
+
+ 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;
+ }
+ }
+ 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;
+ }
+}
+
+#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
+
+ * 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);
+ int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent)
+ & SC_FOLDLEVELNUMBERMASK
+ & ~SC_FOLDLEVELBASE);
+ int levelCurrent = levelPrev;
+ char chNext = styler[startPos];
+ 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 = 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 > 0) {
+ levelCurrent--;
+ }
+ }
+ } else if (style == SCE_RB_OPERATOR) {
+ if (strchr("[{(", ch)) {
+ levelCurrent++;
+ } else if (strchr(")}]", ch)) {
+ // Don't decrement below 0
+ if (levelCurrent > 0)
+ levelCurrent--;
+ }
+ } 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;
+ }
+ stylePrev = style;
+ }
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ if (!buffer_ends_with_eol) {
+ 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[] = {
+ "Keywords",
+ 0
+};
+
+LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc);
diff --git a/scintilla/src/LexSML.cxx b/scintilla/src/LexSML.cxx
new file mode 100644
index 0000000..5f039fe
--- /dev/null
+++ b/scintilla/src/LexSML.cxx
@@ -0,0 +1,221 @@
+// Scintilla source code edit control
+/** @file LexSML.cxx
+ ** Lexer for SML.
+ **/
+// Copyright 2009 by James Moffatt and Yuzhou Xin
+// Modified from LexCaml.cxx by Robert Roessler <robertr@rftp.com> Copyright 2005
+// 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"
+
+inline int issml(int c) {return isalnum(c) || c == '_';}
+inline int issmlf(int c) {return isalpha(c) || c == '_';}
+inline int issmld(int c) {return isdigit(c) || c == '_';}
+
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+void ColouriseSMLDoc(
+ unsigned int startPos, int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+ int nesting = 0;
+ if (sc.state < SCE_SML_STRING)
+ sc.state = SCE_SML_DEFAULT;
+ if (sc.state >= SCE_SML_COMMENT)
+ nesting = (sc.state & 0x0f) - SCE_SML_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);
+
+ while (sc.More()) {
+ int state2 = -1;
+ int chColor = sc.currentPos - 1;
+ bool advance = true;
+
+ switch (sc.state & 0x0f) {
+ case SCE_SML_DEFAULT:
+ chToken = sc.currentPos;
+ if (issmlf(sc.ch))
+ state2 = SCE_SML_IDENTIFIER;
+ else if (sc.Match('`') && issmlf(sc.chNext))
+ state2 = SCE_SML_TAGNAME;
+ else if (sc.Match('#')&&isdigit(sc.chNext))
+ state2 = SCE_SML_LINENUM;
+ else if (sc.Match('#','\"')){
+ state2 = SCE_SML_CHAR,chLit = 0;
+ sc.Forward();
+
+ }
+ else if (isdigit(sc.ch)) {
+ state2 = SCE_SML_NUMBER, chBase = 10;
+ if (sc.Match('0') && strchr("xX", sc.chNext))
+ chBase = 16, sc.Forward();}
+ else if (sc.Match('\"')&&sc.chPrev!='#')
+ state2 = SCE_SML_STRING;
+ else if (sc.Match('(', '*')){
+ state2 = SCE_SML_COMMENT,
+ sc.ch = ' ',
+ sc.Forward();}
+ else if (strchr("!~"
+ "=<>@^+-*/"
+ "()[];,:.#", sc.ch))
+ state2 = SCE_SML_OPERATOR;
+ break;
+
+ case SCE_SML_IDENTIFIER:
+ if (!(issml(sc.ch) || sc.Match('\''))) {
+ const int n = sc.currentPos - chToken;
+ if (n < 24) {
+ char t[24];
+ for (int i = -n; i < 0; i++)
+ t[n + i] = static_cast<char>(sc.GetRelative(i));
+ t[n] = '\0';
+ if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
+ sc.ChangeState(SCE_SML_KEYWORD);
+ else if (keywords2.InList(t))
+ sc.ChangeState(SCE_SML_KEYWORD2);
+ else if (keywords3.InList(t))
+ sc.ChangeState(SCE_SML_KEYWORD3);
+ }
+ state2 = SCE_SML_DEFAULT, advance = false;
+ }
+ break;
+
+ case SCE_SML_TAGNAME:
+ if (!(issml(sc.ch) || sc.Match('\'')))
+ state2 = SCE_SML_DEFAULT, advance = false;
+ break;
+
+ case SCE_SML_LINENUM:
+ if (!isdigit(sc.ch))
+ state2 = SCE_SML_DEFAULT, advance = false;
+ break;
+
+ case SCE_SML_OPERATOR: {
+ const char* o = 0;
+ if (issml(sc.ch) || isspace(sc.ch)
+ || (o = strchr(")]};,\'\"`#", sc.ch),o)
+ || !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) {
+ if (o && strchr(")]};,", sc.ch)) {
+ if ((sc.Match(')') && sc.chPrev == '(')
+ || (sc.Match(']') && sc.chPrev == '['))
+ sc.ChangeState(SCE_SML_KEYWORD);
+ chColor++;
+ } else
+ advance = false;
+ state2 = SCE_SML_DEFAULT;
+ }
+ break;
+ }
+
+ case SCE_SML_NUMBER:
+ if (issmld(sc.ch) || IsADigit(sc.ch, chBase))
+ break;
+ if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
+ && (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
+ break;
+ if (chBase == 10) {
+ if (sc.Match('.') && issmld(sc.chPrev))
+ break;
+ if ((sc.Match('e') || sc.Match('E'))
+ && (issmld(sc.chPrev) || sc.chPrev == '.'))
+ break;
+ if ((sc.Match('+') || sc.Match('-'))
+ && (sc.chPrev == 'e' || sc.chPrev == 'E'))
+ break;
+ }
+ state2 = SCE_SML_DEFAULT, advance = false;
+ break;
+
+ case SCE_SML_CHAR:
+ if (sc.Match('\\')) {
+ chLit = 1;
+ if (sc.chPrev == '\\')
+ sc.ch = ' ';
+ } else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) {
+ state2 = SCE_SML_DEFAULT;
+ chLit = 1;
+ if (sc.Match('\"'))
+ chColor++;
+ else
+ sc.ChangeState(SCE_SML_IDENTIFIER);
+ } else if (chLit < 1 && sc.currentPos - chToken >= 3)
+ sc.ChangeState(SCE_SML_IDENTIFIER), advance = false;
+ break;
+
+ case SCE_SML_STRING:
+ if (sc.Match('\\') && sc.chPrev == '\\')
+ sc.ch = ' ';
+ else if (sc.Match('\"') && sc.chPrev != '\\')
+ state2 = SCE_SML_DEFAULT, chColor++;
+ break;
+
+ case SCE_SML_COMMENT:
+ case SCE_SML_COMMENT1:
+ case SCE_SML_COMMENT2:
+ case SCE_SML_COMMENT3:
+ if (sc.Match('(', '*'))
+ state2 = sc.state + 1, chToken = sc.currentPos,
+ sc.ch = ' ',
+ sc.Forward(), nesting++;
+ else if (sc.Match(')') && sc.chPrev == '*') {
+ if (nesting)
+ state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
+ else
+ state2 = SCE_SML_DEFAULT;
+ chColor++;
+ } else if (useMagic && sc.currentPos - chToken == 4
+ && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
+ sc.state |= 0x10;
+ break;
+ }
+
+ if (state2 >= 0)
+ styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
+ if (advance)
+ sc.Forward();
+ }
+
+ sc.Complete();
+}
+
+void FoldSMLDoc(
+ unsigned int, int,
+ int,
+ WordList *[],
+ Accessor &)
+{
+}
+
+static const char * const SMLWordListDesc[] = {
+ "Keywords",
+ "Keywords2",
+ "Keywords3",
+ 0
+};
+
+LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc);
+
diff --git a/scintilla/src/LexSQL.cxx b/scintilla/src/LexSQL.cxx
new file mode 100644
index 0000000..c739e4f
--- /dev/null
+++ b/scintilla/src/LexSQL.cxx
@@ -0,0 +1,357 @@
+// Scintilla source code edit control
+/** @file LexSQL.cxx
+ ** Lexer for SQL, including PL/SQL and SQL*Plus.
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+ return (ch < 0x80) && (isalpha(ch) || ch == '_');
+}
+
+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 == '+');
+}
+
+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);
+
+ // property sql.backslash.escapes
+ // Enables backslash as an escape character in SQL.
+ bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
+
+ bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0;
+ int styleBeforeDCKeyword = SCE_SQL_DEFAULT;
+ for (; sc.More(); sc.Forward()) {
+ // 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;
+ }
+
+ // 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);
+ }
+ }
+ }
+ 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;
+ bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0;
+
+ // property fold.sql.exists
+ // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS".
+ bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 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) >> 16;
+ }
+ 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--;
+ }
+ }
+ }
+ 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;
+ }
+ 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 ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) {
+ if (endFound) {
+ // ignore
+ endFound = false;
+ } else {
+ levelNext++;
+ }
+ } else if (strcmp(s, "begin") == 0) {
+ levelNext++;
+ } else if ((strcmp(s, "end") == 0) ||
+// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
+ (foldSqlExists && (strcmp(s, "exists") == 0)) ||
+// // SQL Anywhere permits IF ... ELSE ... ENDIF
+// // will only be active if "endif" appears in the
+// // keyword list.
+ (strcmp(s, "endif") == 0)) {
+ endFound = true;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE) {
+ levelNext = SC_FOLDLEVELBASE;
+ }
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ visibleChars = 0;
+ endFound = false;
+ }
+ if (!isspacechar(ch)) {
+ visibleChars++;
+ }
+ }
+}
+
+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", FoldSQLDoc, sqlWordListDesc);
diff --git a/scintilla/src/LexScriptol.cxx b/scintilla/src/LexScriptol.cxx
new file mode 100644
index 0000000..f459920
--- /dev/null
+++ b/scintilla/src/LexScriptol.cxx
@@ -0,0 +1,408 @@
+// Scintilla source code edit control
+/** @file LexScriptol.cxx
+ ** Lexer for Scriptol.
+ **/
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ClassifyWordSol(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';
+ }
+ char chAttr = SCE_SCRIPTOL_IDENTIFIER;
+ if (0 == strcmp(prevWord, "class")) chAttr = SCE_SCRIPTOL_CLASSNAME;
+ else if (wordIsNumber) chAttr = SCE_SCRIPTOL_NUMBER;
+ else if (keywords.InList(s)) chAttr = SCE_SCRIPTOL_KEYWORD;
+ else for (unsigned int i = 0; i < end - start + 1; i++) // test dotted idents
+ {
+ if (styler[start + i] == '.')
+ {
+ styler.ColourTo(start + i - 1, chAttr);
+ styler.ColourTo(start + i, SCE_SCRIPTOL_OPERATOR);
+ }
+ }
+ styler.ColourTo(end, chAttr);
+ strcpy(prevWord, s);
+}
+
+static bool IsSolComment(Accessor &styler, int pos, int len)
+{
+ char c;
+ if(len > 0)
+ {
+ c = styler[pos];
+ if(c == '`') return true;
+ if(len > 1)
+ {
+ if(c == '/')
+ {
+ c = styler[pos + 1];
+ if(c == '/') return true;
+ if(c == '*') return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool IsSolStringStart(char ch)
+{
+ if (ch == '\'' || ch == '"') return true;
+ return false;
+}
+
+static bool IsSolWordStart(char ch)
+{
+ return (iswordchar(ch) && !IsSolStringStart(ch));
+}
+
+
+static int GetSolStringState(Accessor &styler, int i, int *nextIndex)
+{
+ char ch = styler.SafeGetCharAt(i);
+ char chNext = styler.SafeGetCharAt(i + 1);
+
+ if (ch != '\"' && ch != '\'')
+ {
+ *nextIndex = i + 1;
+ return SCE_SCRIPTOL_DEFAULT;
+ }
+ // ch is either single or double quotes in string
+ // code below seem non-sense but is here for future extensions
+ if (ch == chNext && ch == styler.SafeGetCharAt(i + 2))
+ {
+ *nextIndex = i + 3;
+ if(ch == '\"') return SCE_SCRIPTOL_TRIPLE;
+ if(ch == '\'') return SCE_SCRIPTOL_TRIPLE;
+ return SCE_SCRIPTOL_STRING;
+ }
+ else
+ {
+ *nextIndex = i + 1;
+ if (ch == '"') return SCE_SCRIPTOL_STRING;
+ else return SCE_SCRIPTOL_STRING;
+ }
+}
+
+
+static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler)
+ {
+
+ int lengthDoc = startPos + length;
+ char stringType = '\"';
+
+ if (startPos > 0)
+ {
+ int lineCurrent = styler.GetLine(startPos);
+ if (lineCurrent > 0)
+ {
+ startPos = styler.LineStart(lineCurrent-1);
+ if (startPos == 0) initStyle = SCE_SCRIPTOL_DEFAULT;
+ else initStyle = styler.StyleAt(startPos-1);
+ }
+ }
+
+ styler.StartAt(startPos, 127);
+
+ WordList &keywords = *keywordlists[0];
+
+ int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
+ char prevWord[200];
+ prevWord[0] = '\0';
+ if (length == 0) return;
+
+ int state = initStyle & 31;
+
+ int nextIndex = 0;
+ char chPrev = ' ';
+ char chPrev2 = ' ';
+ char chNext = styler[startPos];
+ 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;
+ }
+
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc))
+ {
+ if ((state == SCE_SCRIPTOL_DEFAULT) ||
+ (state == SCE_SCRIPTOL_TRIPLE) ||
+ (state == SCE_SCRIPTOL_COMMENTBLOCK))
+ {
+ styler.ColourTo(i, state);
+ }
+ atStartLine = true;
+ }
+
+ if (styler.IsLeadByte(ch))
+ {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ chPrev2 = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_SCRIPTOL_STRINGEOL)
+ {
+ if (ch != '\r' && ch != '\n')
+ {
+ styler.ColourTo(i - 1, state);
+ state = SCE_SCRIPTOL_DEFAULT;
+ }
+ }
+
+ if (state == SCE_SCRIPTOL_DEFAULT)
+ {
+ if (IsSolWordStart(ch))
+ {
+ styler.ColourTo(i - 1, state);
+ state = SCE_SCRIPTOL_KEYWORD;
+ }
+ else if (ch == '`')
+ {
+ styler.ColourTo(i - 1, state);
+ state = SCE_SCRIPTOL_COMMENTLINE;
+ }
+ else if (ch == '/')
+ {
+ styler.ColourTo(i - 1, state);
+ if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE;
+ if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK;
+ }
+
+ else if (IsSolStringStart(ch))
+ {
+ styler.ColourTo(i - 1, state);
+ state = GetSolStringState(styler, i, &nextIndex);
+ if(state == SCE_SCRIPTOL_STRING)
+ {
+ stringType = ch;
+ }
+ if (nextIndex != i + 1)
+ {
+ i = nextIndex - 1;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ }
+ else if (isoperator(ch))
+ {
+ styler.ColourTo(i - 1, state);
+ styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR);
+ }
+ }
+ else if (state == SCE_SCRIPTOL_KEYWORD)
+ {
+ if (!iswordchar(ch))
+ {
+ ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
+ state = SCE_SCRIPTOL_DEFAULT;
+ if (ch == '`')
+ {
+ state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE;
+ }
+ else if (IsSolStringStart(ch))
+ {
+ styler.ColourTo(i - 1, state);
+ state = GetSolStringState(styler, i, &nextIndex);
+ if (nextIndex != i + 1)
+ {
+ i = nextIndex - 1;
+ ch = ' ';
+ chPrev = ' ';
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ }
+ else if (isoperator(ch))
+ {
+ styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR);
+ }
+ }
+ }
+ else
+ {
+ if (state == SCE_SCRIPTOL_COMMENTLINE ||
+ state == SCE_SCRIPTOL_PERSISTENT ||
+ state == SCE_SCRIPTOL_CSTYLE)
+ {
+ if (ch == '\r' || ch == '\n')
+ {
+ styler.ColourTo(i - 1, state);
+ state = SCE_SCRIPTOL_DEFAULT;
+ }
+ }
+ else if(state == SCE_SCRIPTOL_COMMENTBLOCK)
+ {
+ if(chPrev == '*' && ch == '/')
+ {
+ styler.ColourTo(i, state);
+ state = SCE_SCRIPTOL_DEFAULT;
+ }
+ }
+ else if ((state == SCE_SCRIPTOL_STRING) ||
+ (state == SCE_SCRIPTOL_CHARACTER))
+ {
+ if ((ch == '\r' || ch == '\n') && (chPrev != '\\'))
+ {
+ styler.ColourTo(i - 1, state);
+ state = SCE_SCRIPTOL_STRINGEOL;
+ }
+ else if (ch == '\\')
+ {
+ if (chNext == '\"' || chNext == '\'' || chNext == '\\')
+ {
+ i++;
+ ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ }
+ }
+ else if ((ch == '\"') || (ch == '\''))
+ {
+ // must match the entered quote type
+ if(ch == stringType)
+ {
+ styler.ColourTo(i, state);
+ state = SCE_SCRIPTOL_DEFAULT;
+ }
+ }
+ }
+ else if (state == SCE_SCRIPTOL_TRIPLE)
+ {
+ if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') ||
+ (ch == '\"' && chPrev == '\"' && chPrev2 == '\"'))
+ {
+ styler.ColourTo(i, state);
+ state = SCE_SCRIPTOL_DEFAULT;
+ }
+ }
+
+ }
+ chPrev2 = chPrev;
+ chPrev = ch;
+ }
+ if (state == SCE_SCRIPTOL_KEYWORD)
+ {
+ ClassifyWordSol(styler.GetStartSegment(),
+ lengthDoc-1, keywords, styler, prevWord);
+ }
+ else
+ {
+ styler.ColourTo(lengthDoc-1, state);
+ }
+}
+
+static void FoldSolDoc(unsigned int startPos, int length, int initStyle,
+ WordList *[], Accessor &styler)
+ {
+ int lengthDoc = startPos + length;
+
+ int lineCurrent = styler.GetLine(startPos);
+ if (startPos > 0)
+ {
+ if (lineCurrent > 0)
+ {
+ lineCurrent--;
+ startPos = styler.LineStart(lineCurrent);
+ if (startPos == 0)
+ initStyle = SCE_SCRIPTOL_DEFAULT;
+ else
+ initStyle = styler.StyleAt(startPos-1);
+ }
+ }
+ int state = initStyle & 31;
+ int spaceFlags = 0;
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment);
+ if ((state == SCE_SCRIPTOL_TRIPLE))
+ indentCurrent |= SC_FOLDLEVELWHITEFLAG;
+ char chNext = styler[startPos];
+ for (int i = startPos; i < lengthDoc; 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, IsSolComment);
+ if (style == SCE_SCRIPTOL_TRIPLE)
+ 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, IsSolComment);
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK))
+ {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ }
+ indentCurrent = indentNext;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ }
+ }
+}
+
+LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc);
diff --git a/scintilla/src/LexSmalltalk.cxx b/scintilla/src/LexSmalltalk.cxx
new file mode 100644
index 0000000..2fe96f3
--- /dev/null
+++ b/scintilla/src/LexSmalltalk.cxx
@@ -0,0 +1,321 @@
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+| 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/scintilla/src/LexSorcus.cxx b/scintilla/src/LexSorcus.cxx
new file mode 100644
index 0000000..35bbaed
--- /dev/null
+++ b/scintilla/src/LexSorcus.cxx
@@ -0,0 +1,205 @@
+// Scintilla source code edit control
+/** @file LexSorcus.cxx
+** Lexer for SORCUS installation files
+** Written by Eugen Bitter and Christoph Baumann at SORCUS Computer, Heidelberg Germany
+** Based on the ASM Lexer by The Black Horus
+**/
+
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+//each character a..z and A..Z + '_' can be part of a keyword
+//additionally numbers that follow 'M' can be contained in a keyword
+static inline bool IsSWordStart(const int ch, const int prev_ch)
+{
+ if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M')))
+ return true;
+
+ return false;
+}
+
+
+//only digits that are not preceded by 'M' count as a number
+static inline bool IsSorcusNumber(const int ch, const int prev_ch)
+{
+ if ((isdigit(ch)) && (prev_ch != 'M'))
+ return true;
+
+ return false;
+}
+
+
+//only = is a valid operator
+static inline bool IsSorcusOperator(const int ch)
+{
+ if (ch == '=')
+ return true;
+
+ return false;
+}
+
+
+static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler)
+{
+
+ WordList &Command = *keywordlists[0];
+ WordList &Parameter = *keywordlists[1];
+ WordList &Constant = *keywordlists[2];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_SORCUS_STRINGEOL)
+ initStyle = SCE_SORCUS_DEFAULT;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+
+ // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line
+ if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING))
+ {
+ sc.SetState(SCE_SORCUS_STRING);
+ }
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_SORCUS_OPERATOR)
+ {
+ if (!IsSorcusOperator(sc.ch))
+ {
+ sc.SetState(SCE_SORCUS_DEFAULT);
+ }
+ }
+ else if(sc.state == SCE_SORCUS_NUMBER)
+ {
+ if(!IsSorcusNumber(sc.ch, sc.chPrev))
+ {
+ sc.SetState(SCE_SORCUS_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_SORCUS_IDENTIFIER)
+ {
+ if (!IsSWordStart(sc.ch, sc.chPrev))
+ {
+ char s[100];
+
+ sc.GetCurrent(s, sizeof(s));
+
+ if (Command.InList(s))
+ {
+ sc.ChangeState(SCE_SORCUS_COMMAND);
+ }
+ else if (Parameter.InList(s))
+ {
+ sc.ChangeState(SCE_SORCUS_PARAMETER);
+ }
+ else if (Constant.InList(s))
+ {
+ sc.ChangeState(SCE_SORCUS_CONSTANT);
+ }
+
+ sc.SetState(SCE_SORCUS_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_SORCUS_COMMENTLINE )
+ {
+ if (sc.atLineEnd)
+ {
+ sc.SetState(SCE_SORCUS_DEFAULT);
+ }
+ }
+ else if (sc.state == SCE_SORCUS_STRING)
+ {
+ if (sc.ch == '\"')
+ {
+ sc.ForwardSetState(SCE_SORCUS_DEFAULT);
+ }
+ else if (sc.atLineEnd)
+ {
+ sc.ChangeState(SCE_SORCUS_STRINGEOL);
+ sc.ForwardSetState(SCE_SORCUS_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_SORCUS_DEFAULT)
+ {
+ if ((sc.ch == ';') || (sc.ch == '\''))
+ {
+ sc.SetState(SCE_SORCUS_COMMENTLINE);
+ }
+ else if (IsSWordStart(sc.ch, sc.chPrev))
+ {
+ sc.SetState(SCE_SORCUS_IDENTIFIER);
+ }
+ else if (sc.ch == '\"')
+ {
+ sc.SetState(SCE_SORCUS_STRING);
+ }
+ else if (IsSorcusOperator(sc.ch))
+ {
+ sc.SetState(SCE_SORCUS_OPERATOR);
+ }
+ else if (IsSorcusNumber(sc.ch, sc.chPrev))
+ {
+ sc.SetState(SCE_SORCUS_NUMBER);
+ }
+ }
+
+ }
+ sc.Complete();
+}
+
+
+static const char* const SorcusWordListDesc[] = {"Command","Parameter", "Constant", 0};
+
+LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins", 0, SorcusWordListDesc);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scintilla/src/LexSpecman.cxx b/scintilla/src/LexSpecman.cxx
new file mode 100644
index 0000000..4a7f4dd
--- /dev/null
+++ b/scintilla/src/LexSpecman.cxx
@@ -0,0 +1,289 @@
+// Scintilla source code edit control
+/** @file LexSpecman.cxx
+ ** Lexer for Specman E language.
+ ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
+}
+
+static inline bool IsANumberChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\'');
+}
+
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`');
+}
+
+static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler, bool caseSensitive) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_SN_STRINGEOL)
+ initStyle = SCE_SN_CODE;
+
+ int visibleChars = 0;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart && (sc.state == SCE_SN_STRING)) {
+ // Prevent SCE_SN_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_SN_STRING);
+ }
+
+ // 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_SN_OPERATOR) {
+ sc.SetState(SCE_SN_CODE);
+ } else if (sc.state == SCE_SN_NUMBER) {
+ if (!IsANumberChar(sc.ch)) {
+ sc.SetState(SCE_SN_CODE);
+ }
+ } else if (sc.state == SCE_SN_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)) {
+ sc.ChangeState(SCE_SN_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_SN_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_SN_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_SN_USER);
+ }
+ sc.SetState(SCE_SN_CODE);
+ }
+ } else if (sc.state == SCE_SN_PREPROCESSOR) {
+ if (IsASpace(sc.ch)) {
+ sc.SetState(SCE_SN_CODE);
+ }
+ } else if (sc.state == SCE_SN_DEFAULT) {
+ if (sc.Match('<', '\'')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_SN_CODE);
+ }
+ } else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_SN_CODE);
+ visibleChars = 0;
+ }
+ } else if (sc.state == SCE_SN_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_SN_CODE);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_SN_STRINGEOL);
+ sc.ForwardSetState(SCE_SN_CODE);
+ visibleChars = 0;
+ }
+ } else if (sc.state == SCE_SN_SIGNAL) {
+ if (sc.atLineEnd) {
+ sc.ChangeState(SCE_SN_STRINGEOL);
+ sc.ForwardSetState(SCE_SN_CODE);
+ visibleChars = 0;
+ } else if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\'') {
+ sc.ForwardSetState(SCE_SN_CODE);
+ }
+ } else if (sc.state == SCE_SN_REGEXTAG) {
+ if (!IsADigit(sc.ch)) {
+ sc.SetState(SCE_SN_CODE);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_SN_CODE) {
+ if (sc.ch == '$' && IsADigit(sc.chNext)) {
+ sc.SetState(SCE_SN_REGEXTAG);
+ sc.Forward();
+ } else if (IsADigit(sc.ch)) {
+ sc.SetState(SCE_SN_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_SN_IDENTIFIER);
+ } else if (sc.Match('\'', '>')) {
+ sc.SetState(SCE_SN_DEFAULT);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ if (sc.Match("//!")) // Nice to have a different comment style
+ sc.SetState(SCE_SN_COMMENTLINEBANG);
+ else
+ sc.SetState(SCE_SN_COMMENTLINE);
+ } else if (sc.Match('-', '-')) {
+ if (sc.Match("--!")) // Nice to have a different comment style
+ sc.SetState(SCE_SN_COMMENTLINEBANG);
+ else
+ sc.SetState(SCE_SN_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_SN_STRING);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_SN_SIGNAL);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ // Preprocessor commands are alone on their line
+ sc.SetState(SCE_SN_PREPROCESSOR);
+ // Skip whitespace between # and preprocessor word
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_SN_CODE);
+ }
+ } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@') {
+ sc.SetState(SCE_SN_OPERATOR);
+ }
+ }
+
+ if (sc.atLineEnd) {
+ // Reset states to begining of colourise so no surprises
+ // if different sets of lines lexed.
+ visibleChars = 0;
+ }
+ if (!IsASpace(sc.ch)) {
+ visibleChars++;
+ }
+ }
+ sc.Complete();
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int,
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style;
+ 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 && (style == SCE_SN_COMMENTLINE)) {
+ if (((ch == '/') && (chNext == '/')) ||
+ ((ch == '-') && (chNext == '-'))) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelNext++;
+ } else if (chNext2 == '}') {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_SN_OPERATOR) {
+ if (ch == '{') {
+ // Measure the minimum before a '{' to allow
+ // folding on "} else {"
+ if (levelMinCurrent > levelNext) {
+ levelMinCurrent = levelNext;
+ }
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+}
+
+static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler);
+}
+
+static const char * const specmanWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "Sequence keywords and identifiers",
+ "User defined keywords and identifiers",
+ "Unused",
+ 0,
+ };
+
+static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+ ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+
+
+LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists);
diff --git a/scintilla/src/LexSpice.cxx b/scintilla/src/LexSpice.cxx
new file mode 100644
index 0000000..7a9d5bb
--- /dev/null
+++ b/scintilla/src/LexSpice.cxx
@@ -0,0 +1,226 @@
+// Scintilla source code edit control
+/** @file LexSpice.cxx
+ ** Lexer for Spice
+ **/
+// Copyright 2006 by Fabien Proriol
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "Platform.h"
+
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
+#include "KeyWords.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+/*
+ * Interface
+ */
+
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler);
+
+static const char * const spiceWordListDesc[] = {
+ "Keywords", // SPICE command
+ "Keywords2", // SPICE functions
+ "Keywords3", // SPICE params
+ 0
+};
+
+LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);
+
+/*
+ * Implementation
+ */
+
+static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
+static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);
+
+static inline bool IsDelimiterCharacter(int ch);
+static inline bool IsNumberStartCharacter(int ch);
+static inline bool IsNumberCharacter(int ch);
+static inline bool IsSeparatorOrDelimiterCharacter(int ch);
+static inline bool IsWordStartCharacter(int ch);
+static inline bool IsWordCharacter(int ch);
+
+static void ColouriseComment(StyleContext& sc, bool&) {
+ sc.SetState(SCE_SPICE_COMMENTLINE);
+ while (!sc.atLineEnd) {
+ sc.Forward();
+ }
+}
+
+static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = sc.Match (')');
+ sc.SetState(SCE_SPICE_DELIMITER);
+ sc.ForwardSetState(SCE_SPICE_DEFAULT);
+}
+
+static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+ std::string number;
+ sc.SetState(SCE_SPICE_NUMBER);
+ // Get all characters up to a delimiter or a separator, including points, but excluding
+ // double points (ranges).
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward();
+ }
+ // Special case: exponent with sign
+ if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
+ (sc.ch == '+' || sc.ch == '-')) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward ();
+ while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
+ number += static_cast<char>(sc.ch);
+ sc.Forward();
+ }
+ }
+ sc.SetState(SCE_SPICE_DEFAULT);
+}
+
+static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
+ sc.SetState(SCE_SPICE_DEFAULT);
+ sc.ForwardSetState(SCE_SPICE_DEFAULT);
+}
+
+static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
+ apostropheStartsAttribute = true;
+ sc.SetState(SCE_SPICE_IDENTIFIER);
+ std::string word;
+ while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
+ word += static_cast<char>(tolower(sc.ch));
+ sc.Forward();
+ }
+ if (keywords.InList(word.c_str())) {
+ sc.ChangeState(SCE_SPICE_KEYWORD);
+ if (word != "all") {
+ apostropheStartsAttribute = false;
+ }
+ }
+ else if (keywords2.InList(word.c_str())) {
+ sc.ChangeState(SCE_SPICE_KEYWORD2);
+ if (word != "all") {
+ apostropheStartsAttribute = false;
+ }
+ }
+ else if (keywords3.InList(word.c_str())) {
+ sc.ChangeState(SCE_SPICE_KEYWORD3);
+ if (word != "all") {
+ apostropheStartsAttribute = false;
+ }
+ }
+ sc.SetState(SCE_SPICE_DEFAULT);
+}
+
+//
+// ColouriseDocument
+//
+static void ColouriseDocument(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler) {
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ StyleContext sc(startPos, length, initStyle, styler);
+ int lineCurrent = styler.GetLine(startPos);
+ bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
+ while (sc.More()) {
+ if (sc.atLineEnd) {
+ // Go to the next line
+ sc.Forward();
+ lineCurrent++;
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, apostropheStartsAttribute);
+ // Don't continue any styles on the next line
+ sc.SetState(SCE_SPICE_DEFAULT);
+ }
+ // Comments
+ if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
+ ColouriseComment(sc, apostropheStartsAttribute);
+ // Whitespace
+ } else if (IsASpace(sc.ch)) {
+ ColouriseWhiteSpace(sc, apostropheStartsAttribute);
+ // Delimiters
+ } else if (IsDelimiterCharacter(sc.ch)) {
+ ColouriseDelimiter(sc, apostropheStartsAttribute);
+ // Numbers
+ } else if (IsADigit(sc.ch) || sc.ch == '#') {
+ ColouriseNumber(sc, apostropheStartsAttribute);
+ // Keywords or identifiers
+ } else {
+ ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
+ }
+ }
+ sc.Complete();
+}
+
+static inline bool IsDelimiterCharacter(int ch) {
+ switch (ch) {
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+ case '/':
+ case ':':
+ case ';':
+ case '<':
+ case '=':
+ case '>':
+ case '|':
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool IsNumberCharacter(int ch) {
+ return IsNumberStartCharacter(ch) ||
+ ch == '_' ||
+ ch == '.' ||
+ ch == '#' ||
+ (ch >= 'a' && ch <= 'f') ||
+ (ch >= 'A' && ch <= 'F');
+}
+
+static inline bool IsNumberStartCharacter(int ch) {
+ return IsADigit(ch);
+}
+
+static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
+ return IsASpace(ch) || IsDelimiterCharacter(ch);
+}
+
+static inline bool IsWordCharacter(int ch) {
+ return IsWordStartCharacter(ch) || IsADigit(ch);
+}
+
+static inline bool IsWordStartCharacter(int ch) {
+ return (isascii(ch) && isalpha(ch)) || ch == '_';
+}
diff --git a/scintilla/src/LexTACL.cxx b/scintilla/src/LexTACL.cxx
new file mode 100644
index 0000000..8bcd889
--- /dev/null
+++ b/scintilla/src/LexTACL.cxx
@@ -0,0 +1,397 @@
+// Scintilla source code edit control
+/** @file LexTAL.cxx
+ ** Lexer for TAL
+ ** Based on LexPascal.cxx
+ ** Written by Laurent le Tynevez
+ ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
+ ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
+ ** Updated by Rod Falck, Aug 2006 Converted to TACL
+ **/
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+inline bool isTACLoperator(char ch)
+ {
+ return ch == '\'' || isoperator(ch);
+ }
+
+inline bool isTACLwordchar(char ch)
+ {
+ return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch);
+ }
+
+inline bool isTACLwordstart(char ch)
+ {
+ return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch);
+ }
+
+static void getRange(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_C_COMMENT ||
+ style == SCE_C_COMMENTDOC ||
+ style == SCE_C_COMMENTDOCKEYWORD ||
+ style == SCE_C_COMMENTDOCKEYWORDERROR;
+}
+
+static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
+ if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
+ styler.ColourTo(end, SCE_C_REGEX);
+ } else
+ styler.ColourTo(end, attr);
+}
+
+// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
+static int classifyWordTACL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
+ int ret = 0;
+
+ WordList& keywords = *keywordlists[0];
+ WordList& builtins = *keywordlists[1];
+ WordList& commands = *keywordlists[2];
+
+ char s[100];
+ getRange(start, end, styler, s, sizeof(s));
+
+ char chAttr = SCE_C_IDENTIFIER;
+ if (isdigit(s[0]) || (s[0] == '.')) {
+ chAttr = SCE_C_NUMBER;
+ }
+ else {
+ if (s[0] == '#' || keywords.InList(s)) {
+ chAttr = SCE_C_WORD;
+
+ if (strcmp(s, "asm") == 0) {
+ ret = 2;
+ }
+ else if (strcmp(s, "end") == 0) {
+ ret = -1;
+ }
+ }
+ else if (s[0] == '|' || builtins.InList(s)) {
+ chAttr = SCE_C_WORD2;
+ }
+ else if (commands.InList(s)) {
+ chAttr = SCE_C_UUID;
+ }
+ else if (strcmp(s, "comment") == 0) {
+ chAttr = SCE_C_COMMENTLINE;
+ ret = 3;
+ }
+ }
+ ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
+ return ret;
+}
+
+static int classifyFoldPointTACL(const char* s) {
+ int lev = 0;
+ if (s[0] == '[')
+ lev=1;
+ else if (s[0] == ']')
+ lev=-1;
+ return lev;
+}
+
+static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ styler.StartAt(startPos);
+
+ int state = initStyle;
+ if (state == SCE_C_CHARACTER) // Does not leak onto next line
+ state = SCE_C_DEFAULT;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ unsigned int lengthDoc = startPos + length;
+
+ bool bInClassDefinition;
+
+ int currentLine = styler.GetLine(startPos);
+ if (currentLine > 0) {
+ styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
+ bInClassDefinition = (styler.GetLineState(currentLine) == 1);
+ } else {
+ styler.SetLineState(currentLine, 0);
+ bInClassDefinition = false;
+ }
+
+ bool bInAsm = (state == SCE_C_REGEX);
+ if (bInAsm)
+ state = SCE_C_DEFAULT;
+
+ styler.StartSegment(startPos);
+ int visibleChars = 0;
+ unsigned int i;
+ for (i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
+ // Avoid triggering two times on Dos/Win
+ // End of line
+ if (state == SCE_C_CHARACTER) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ visibleChars = 0;
+ currentLine++;
+ styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
+ }
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (isTACLwordstart(ch)) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_IDENTIFIER;
+ } else if (ch == '{') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENT;
+ } else if (ch == '{' && chNext == '*') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTDOC;
+ } else if (ch == '=' && chNext == '=') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '"') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_STRING;
+ } else if (ch == '?' && visibleChars == 0) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_PREPROCESSOR;
+ } else if (isTACLoperator(ch)) {
+ ColourTo(styler, i-1, state, bInAsm);
+ ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+ }
+ } else if (state == SCE_C_IDENTIFIER) {
+ if (!isTACLwordchar(ch)) {
+ int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
+
+ if(lStateChange == 1) {
+ styler.SetLineState(currentLine, 1);
+ bInClassDefinition = true;
+ } else if(lStateChange == 2) {
+ bInAsm = true;
+ } else if(lStateChange == -1) {
+ styler.SetLineState(currentLine, 0);
+ bInClassDefinition = false;
+ bInAsm = false;
+ }
+
+ if (lStateChange == 3) {
+ state = SCE_C_COMMENTLINE;
+ }
+ else {
+ state = SCE_C_DEFAULT;
+ chNext = styler.SafeGetCharAt(i + 1);
+ if (ch == '{') {
+ state = SCE_C_COMMENT;
+ } else if (ch == '{' && chNext == '*') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTDOC;
+ } else if (ch == '=' && chNext == '=') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '"') {
+ state = SCE_C_STRING;
+ } else if (isTACLoperator(ch)) {
+ ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+ }
+ }
+ }
+ } else {
+ if (state == SCE_C_PREPROCESSOR) {
+ if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENT) {
+ if (ch == '}' || (ch == '\r' || ch == '\n') ) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENTDOC) {
+ if (ch == '}' || (ch == '\r' || ch == '\n')) {
+ if (((i > styler.GetStartSegment() + 2) || (
+ (initStyle == SCE_C_COMMENTDOC) &&
+ (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_STRING) {
+ if (ch == '"' || ch == '\r' || ch == '\n') {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ chPrev = ch;
+ }
+
+ // Process to end of document
+ if (state == SCE_C_IDENTIFIER) {
+ classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
+ }
+ else
+ ColourTo(styler, lengthDoc - 1, state, bInAsm);
+}
+
+static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 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];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ bool section = false;
+
+ int lastStart = 0;
+
+ 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 (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR))
+ {
+ // Store last word start point.
+ lastStart = i;
+ }
+
+ if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) {
+ if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) {
+ char s[100];
+ getRange(lastStart, i, styler, s, sizeof(s));
+ if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
+ {
+ section = true;
+ levelCurrent = 1;
+ levelPrev = 0;
+ }
+ else if (stylePrev == SCE_C_WORD)
+ levelCurrent += classifyFoldPointTACL(s);
+ }
+ }
+
+ if (style == SCE_C_OPERATOR) {
+ if (ch == '[') {
+ levelCurrent++;
+ } else if (ch == ']') {
+ levelCurrent--;
+ }
+ }
+ if (foldComment && (style == SCE_C_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelCurrent++;
+ } else if (chNext2 == '}') {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
+ if (ch == '{' && chNext == '$') {
+ unsigned int j=i+2; // skip {$
+ while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ j++;
+ }
+ if (styler.Match(j, "region") || styler.Match(j, "if")) {
+ levelCurrent++;
+ } else if (styler.Match(j, "end")) {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (foldComment && IsStreamCommentStyle(style)) {
+ if (!IsStreamCommentStyle(stylePrev)) {
+ levelCurrent++;
+ } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+ if (atEOL) {
+ int lev = levelPrev | SC_FOLDLEVELBASE;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelPrev = levelCurrent;
+ visibleChars = 0;
+ section = false;
+ }
+
+ 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 TACLWordListDesc[] = {
+ "Builtins",
+ "Labels",
+ "Commands",
+ 0
+};
+
+LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc);
diff --git a/scintilla/src/LexTADS3.cxx b/scintilla/src/LexTADS3.cxx
new file mode 100644
index 0000000..d1c3a4f
--- /dev/null
+++ b/scintilla/src/LexTADS3.cxx
@@ -0,0 +1,904 @@
+// Scintilla source code edit control
+/** @file LexTADS3.cxx
+ ** Lexer for TADS3.
+ **/
+// Copyright 1998-2006 by Neil Hodgson <neilh@scintilla.org>
+// 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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static const int T3_SINGLE_QUOTE = 1;
+static const int T3_INT_EXPRESSION = 2;
+static const int T3_INT_EXPRESSION_IN_TAG = 4;
+static const int T3_HTML_SQUOTE = 8;
+
+static inline bool IsEOL(const int ch, const int chNext) {
+ return (ch == '\r' && chNext != '\n') || (ch == '\n');
+}
+
+/*
+ * Test the current character to see if it's the START of an EOL sequence;
+ * if so, skip ahead to the last character of the sequence and return true,
+ * and if not just return false. There are a few places where we want to
+ * check to see if a newline sequence occurs at a particular point, but
+ * where a caller expects a subroutine to stop only upon reaching the END
+ * of a newline sequence (in particular, CR-LF on Windows). That's why
+ * IsEOL() above only returns true on CR if the CR isn't followed by an LF
+ * - it doesn't want to admit that there's a newline until reaching the END
+ * of the sequence. We meet both needs by saying that there's a newline
+ * when we see the CR in a CR-LF, but skipping the CR before returning so
+ * that the caller's caller will see that we've stopped at the LF.
+ */
+static inline bool IsEOLSkip(StyleContext &sc)
+{
+ /* test for CR-LF */
+ if (sc.ch == '\r' && sc.chNext == '\n')
+ {
+ /* got CR-LF - skip the CR and indicate that we're at a newline */
+ sc.Forward();
+ return true;
+ }
+
+ /*
+ * in other cases, we have at most a 1-character newline, so do the
+ * normal IsEOL test
+ */
+ return IsEOL(sc.ch, sc.chNext);
+}
+
+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 == '_';
+}
+
+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;
+ int c = sc.ch;
+ sc.SetState(c == '{' || c == '}' ? SCE_T3_BRACE : SCE_T3_OPERATOR);
+ sc.ForwardSetState(initState);
+}
+
+static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) {
+ int endState = sc.state;
+ int chQuote = sc.ch;
+ int chString = (lineState & T3_SINGLE_QUOTE) ? '\'' : '"';
+ if (endState == SCE_T3_HTML_STRING) {
+ if (lineState&T3_SINGLE_QUOTE) {
+ endState = SCE_T3_S_STRING;
+ chString = '\'';
+ } else if (lineState&T3_INT_EXPRESSION) {
+ endState = SCE_T3_X_STRING;
+ chString = '"';
+ } else {
+ endState = SCE_T3_HTML_DEFAULT;
+ chString = '"';
+ }
+ chQuote = (lineState & T3_HTML_SQUOTE) ? '\'' : '"';
+ } else {
+ sc.SetState(SCE_T3_HTML_STRING);
+ sc.Forward();
+ }
+ if (chQuote == '"')
+ lineState &= ~T3_HTML_SQUOTE;
+ else
+ lineState |= T3_HTML_SQUOTE;
+
+ while (sc.More()) {
+ if (IsEOL(sc.ch, sc.chNext)) {
+ return;
+ }
+ if (sc.ch == chQuote) {
+ sc.ForwardSetState(endState);
+ return;
+ }
+ if (sc.Match('\\', static_cast<char>(chQuote))) {
+ sc.Forward(2);
+ sc.SetState(endState);
+ return;
+ }
+ if (sc.ch == chString) {
+ sc.SetState(SCE_T3_DEFAULT);
+ return;
+ }
+
+ if (sc.Match('<', '<')) {
+ lineState |= T3_INT_EXPRESSION | T3_INT_EXPRESSION_IN_TAG;
+ sc.SetState(SCE_T3_X_DEFAULT);
+ sc.Forward(2);
+ return;
+ }
+
+ if (sc.Match('\\', static_cast<char>(chQuote))
+ || sc.Match('\\', static_cast<char>(chString))
+ || sc.Match('\\', '\\')) {
+ 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.Match('\\', static_cast<char>(chQuote))) {
+ sc.Forward();
+ ColouriseTADSHTMLString(sc, lineState);
+ if (sc.state == SCE_T3_X_DEFAULT)
+ break;
+ } else 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.Match('\\', '\\')) {
+ sc.Forward(2);
+ } else if (sc.ch == '{') {
+ ColouriseTADS3MsgParam(sc, lineState);
+ } else if (sc.Match('<', '.')) {
+ ColouriseTADS3LibDirective(sc, lineState);
+ } else if (sc.ch == '<') {
+ ColouriseTADS3HTMLTag(sc, lineState);
+ if (sc.state == SCE_T3_X_DEFAULT)
+ return;
+ } 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 (IsEOLSkip(sc)) {
+ 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);
+ if (lineState & T3_INT_EXPRESSION_IN_TAG)
+ sc.SetState(SCE_T3_HTML_STRING);
+ lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION
+ |T3_INT_EXPRESSION_IN_TAG);
+ } else if (IsATADS3Operator(sc.ch)) {
+ if (sc.state == SCE_T3_X_DEFAULT) {
+ if (sc.ch == '(') {
+ bracketLevel++;
+ } else if (sc.ch == ')' && bracketLevel > 0) {
+ 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 IsAnOperator(const int style) {
+ return style == SCE_T3_OPERATOR || SCE_T3_BRACE;
+}
+
+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 == ';' && IsAnOperator(style)) {
+ 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 (IsAnOperator(style)) {
+ 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);
diff --git a/scintilla/src/LexTAL.cxx b/scintilla/src/LexTAL.cxx
new file mode 100644
index 0000000..c4dfa8e
--- /dev/null
+++ b/scintilla/src/LexTAL.cxx
@@ -0,0 +1,396 @@
+// Scintilla source code edit control
+/** @file LexTAL.cxx
+ ** Lexer for TAL
+ ** Based on LexPascal.cxx
+ ** Written by Laurent le Tynevez
+ ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
+ ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
+ ** Updated by Rod Falck, Aug 2006 Converted to TAL
+ **/
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+inline bool isTALoperator(char ch)
+ {
+ return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch);
+ }
+
+inline bool isTALwordchar(char ch)
+ {
+ return ch == '$' || ch == '^' || iswordchar(ch);
+ }
+
+inline bool isTALwordstart(char ch)
+ {
+ return ch == '$' || ch == '^' || iswordstart(ch);
+ }
+
+static void getRange(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_C_COMMENT ||
+ style == SCE_C_COMMENTDOC ||
+ style == SCE_C_COMMENTDOCKEYWORD ||
+ style == SCE_C_COMMENTDOCKEYWORDERROR;
+}
+
+static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
+ if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
+ styler.ColourTo(end, SCE_C_REGEX);
+ } else
+ styler.ColourTo(end, attr);
+}
+
+// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
+static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
+ int ret = 0;
+
+ WordList& keywords = *keywordlists[0];
+ WordList& builtins = *keywordlists[1];
+ WordList& nonreserved_keywords = *keywordlists[2];
+
+ char s[100];
+ getRange(start, end, styler, s, sizeof(s));
+
+ char chAttr = SCE_C_IDENTIFIER;
+ if (isdigit(s[0]) || (s[0] == '.')) {
+ chAttr = SCE_C_NUMBER;
+ }
+ else {
+ if (keywords.InList(s)) {
+ chAttr = SCE_C_WORD;
+
+ if (strcmp(s, "asm") == 0) {
+ ret = 2;
+ }
+ else if (strcmp(s, "end") == 0) {
+ ret = -1;
+ }
+ }
+ else if (s[0] == '$' || builtins.InList(s)) {
+ chAttr = SCE_C_WORD2;
+ }
+ else if (nonreserved_keywords.InList(s)) {
+ chAttr = SCE_C_UUID;
+ }
+ }
+ ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
+ return ret;
+}
+
+static int classifyFoldPointTAL(const char* s) {
+ int lev = 0;
+ if (!(isdigit(s[0]) || (s[0] == '.'))) {
+ if (strcmp(s, "begin") == 0 ||
+ strcmp(s, "block") == 0) {
+ lev=1;
+ } else if (strcmp(s, "end") == 0) {
+ lev=-1;
+ }
+ }
+ return lev;
+}
+
+static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ styler.StartAt(startPos);
+
+ int state = initStyle;
+ if (state == SCE_C_CHARACTER) // Does not leak onto next line
+ state = SCE_C_DEFAULT;
+ char chPrev = ' ';
+ char chNext = styler[startPos];
+ unsigned int lengthDoc = startPos + length;
+
+ bool bInClassDefinition;
+
+ int currentLine = styler.GetLine(startPos);
+ if (currentLine > 0) {
+ styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
+ bInClassDefinition = (styler.GetLineState(currentLine) == 1);
+ } else {
+ styler.SetLineState(currentLine, 0);
+ bInClassDefinition = false;
+ }
+
+ bool bInAsm = (state == SCE_C_REGEX);
+ if (bInAsm)
+ state = SCE_C_DEFAULT;
+
+ styler.StartSegment(startPos);
+ int visibleChars = 0;
+ for (unsigned int i = startPos; i < lengthDoc; i++) {
+ char ch = chNext;
+
+ chNext = styler.SafeGetCharAt(i + 1);
+
+ if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
+ // Avoid triggering two times on Dos/Win
+ // End of line
+ if (state == SCE_C_CHARACTER) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ visibleChars = 0;
+ currentLine++;
+ styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
+ }
+
+ if (styler.IsLeadByte(ch)) {
+ chNext = styler.SafeGetCharAt(i + 2);
+ chPrev = ' ';
+ i += 1;
+ continue;
+ }
+
+ if (state == SCE_C_DEFAULT) {
+ if (isTALwordstart(ch)) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_IDENTIFIER;
+ } else if (ch == '!' && chNext != '*') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENT;
+ } else if (ch == '!' && chNext == '*') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTDOC;
+ } else if (ch == '-' && chNext == '-') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '"') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_STRING;
+ } else if (ch == '?' && visibleChars == 0) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_PREPROCESSOR;
+ } else if (isTALoperator(ch)) {
+ ColourTo(styler, i-1, state, bInAsm);
+ ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+ }
+ } else if (state == SCE_C_IDENTIFIER) {
+ if (!isTALwordchar(ch)) {
+ int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
+
+ if(lStateChange == 1) {
+ styler.SetLineState(currentLine, 1);
+ bInClassDefinition = true;
+ } else if(lStateChange == 2) {
+ bInAsm = true;
+ } else if(lStateChange == -1) {
+ styler.SetLineState(currentLine, 0);
+ bInClassDefinition = false;
+ bInAsm = false;
+ }
+
+ state = SCE_C_DEFAULT;
+ chNext = styler.SafeGetCharAt(i + 1);
+ if (ch == '!' && chNext != '*') {
+ state = SCE_C_COMMENT;
+ } else if (ch == '!' && chNext == '*') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_COMMENTDOC;
+ } else if (ch == '-' && chNext == '-') {
+ state = SCE_C_COMMENTLINE;
+ } else if (ch == '"') {
+ state = SCE_C_STRING;
+ } else if (isTALoperator(ch)) {
+ ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+ }
+ }
+ } else {
+ if (state == SCE_C_PREPROCESSOR) {
+ if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENT) {
+ if (ch == '!' || (ch == '\r' || ch == '\n') ) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_COMMENTDOC) {
+ if (ch == '!' || (ch == '\r' || ch == '\n')) {
+ if (((i > styler.GetStartSegment() + 2) || (
+ (initStyle == SCE_C_COMMENTDOC) &&
+ (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ } else if (state == SCE_C_COMMENTLINE) {
+ if (ch == '\r' || ch == '\n') {
+ ColourTo(styler, i-1, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ } else if (state == SCE_C_STRING) {
+ if (ch == '"') {
+ ColourTo(styler, i, state, bInAsm);
+ state = SCE_C_DEFAULT;
+ }
+ }
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ chPrev = ch;
+ }
+ ColourTo(styler, lengthDoc - 1, state, bInAsm);
+}
+
+static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 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];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ bool was_end = false;
+ bool section = false;
+
+ int lastStart = 0;
+
+ 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 (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR))
+ {
+ // Store last word start point.
+ lastStart = i;
+ }
+
+ if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) {
+ if(isTALwordchar(ch) && !isTALwordchar(chNext)) {
+ char s[100];
+ getRange(lastStart, i, styler, s, sizeof(s));
+ if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
+ {
+ section = true;
+ levelCurrent = 1;
+ levelPrev = 0;
+ }
+ else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID)
+ {
+ if (strcmp(s, "block") == 0)
+ {
+ // block keyword is ignored immediately after end keyword
+ if (!was_end)
+ levelCurrent++;
+ }
+ else
+ levelCurrent += classifyFoldPointTAL(s);
+ if (strcmp(s, "end") == 0)
+ {
+ was_end = true;
+ }
+ else
+ {
+ was_end = false;
+ }
+ }
+ }
+ }
+
+ if (foldComment && (style == SCE_C_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelCurrent++;
+ } else if (chNext2 == '}') {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
+ if (ch == '{' && chNext == '$') {
+ unsigned int j=i+2; // skip {$
+ while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ j++;
+ }
+ if (styler.Match(j, "region") || styler.Match(j, "if")) {
+ levelCurrent++;
+ } else if (styler.Match(j, "end")) {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (foldComment && IsStreamCommentStyle(style)) {
+ if (!IsStreamCommentStyle(stylePrev)) {
+ levelCurrent++;
+ } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+ // Comments don't end at end of line and the next character may be unstyled.
+ levelCurrent--;
+ }
+ }
+
+ if (atEOL) {
+ int lev = levelPrev | SC_FOLDLEVELBASE;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelPrev = levelCurrent;
+ visibleChars = 0;
+ section = false;
+ }
+
+ 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 TALWordListDesc[] = {
+ "Keywords",
+ "Builtins",
+ 0
+};
+
+LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc);
diff --git a/scintilla/src/LexTCL.cxx b/scintilla/src/LexTCL.cxx
new file mode 100644
index 0000000..916890d
--- /dev/null
+++ b/scintilla/src/LexTCL.cxx
@@ -0,0 +1,366 @@
+// Scintilla source code edit control
+/** @file LexTCL.cxx
+ ** Lexer for TCL language.
+ **/
+// Copyright 1998-2001 by Andre Arpin <arpin@kingston.net>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+ return ch >= 0x80 ||
+ (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator
+}
+
+static inline bool IsAWordStart(int ch) {
+ return ch >= 0x80 || (ch ==':' || isalpha(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) &&
+ (IsADigit(ch, 0x10) || toupper(ch) == 'E' ||
+ ch == '.' || ch == '-' || ch == '+');
+}
+
+static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *keywordlists[], Accessor &styler) {
+#define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT)
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool commentLevel = false;
+ bool subBrace = false; // substitution begin with a brace ${.....}
+ enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf,
+ LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT;
+ bool prevSlash = false;
+ int currentLevel = 0;
+ bool expected = 0;
+ bool subParen = 0;
+
+ int currentLine = styler.GetLine(startPos);
+ if (currentLine > 0)
+ currentLine--;
+ length += startPos - styler.LineStart(currentLine);
+ // make sure lines overlap
+ startPos = styler.LineStart(currentLine);
+
+ 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];
+ WordList &keywords9 = *keywordlists[8];
+
+ if (currentLine > 0) {
+ int ls = styler.GetLineState(currentLine - 1);
+ lineState = tLineState(ls & LS_MASK_STATE);
+ expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED);
+ subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY);
+ currentLevel = styler.LevelAt(currentLine - 1) >> 17;
+ commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1;
+ } else
+ styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG);
+ bool visibleChars = false;
+
+ int previousLevel = currentLevel;
+ StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler);
+ for (; ; sc.Forward()) {
+next:
+ if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac
+ continue;
+ bool atEnd = !sc.More(); // make sure we coloured the last word
+ if (lineState != LS_DEFAULT) {
+ sc.SetState(SCE_TCL_DEFAULT);
+ if (lineState == LS_OPEN_COMMENT)
+ sc.SetState(SCE_TCL_COMMENTLINE);
+ else if (lineState == LS_OPEN_DOUBLE_QUOTE)
+ sc.SetState(SCE_TCL_IN_QUOTE);
+ else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#')))
+ sc.SetState(SCE_TCL_COMMENT_BOX);
+ lineState = LS_DEFAULT;
+ }
+ if (subBrace) { // ${ overrides every thing even \ except }
+ if (sc.ch == '}') {
+ subBrace = false;
+ sc.SetState(SCE_TCL_OPERATOR);
+ sc.ForwardSetState(SCE_TCL_DEFAULT);
+ goto next;
+ }
+ else
+ sc.SetState(SCE_TCL_SUB_BRACE);
+ if (!sc.atLineEnd)
+ continue;
+ } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) {
+ expected &= isspacechar(static_cast<unsigned char>(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#';
+ } else if (sc.state == SCE_TCL_SUBSTITUTION) {
+ switch(sc.ch) {
+ case '(':
+ subParen=true;
+ sc.SetState(SCE_TCL_OPERATOR);
+ sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
+ continue;
+ case ')':
+ sc.SetState(SCE_TCL_OPERATOR);
+ subParen=false;
+ continue;
+ case '$':
+ continue;
+ case ',':
+ sc.SetState(SCE_TCL_OPERATOR);
+ if (subParen)
+ sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
+ continue;
+ default :
+ // maybe spaces should be allowed ???
+ if (!IsAWordChar(sc.ch)) { // probably the code is wrong
+ sc.SetState(SCE_TCL_DEFAULT);
+ subParen = 0;
+ }
+ break;
+ }
+ } else if (isComment(sc.state)) {
+ } else if (!IsAWordChar(sc.ch)) {
+ if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) {
+ char w[100];
+ char *s=w;
+ sc.GetCurrent(w, sizeof(w));
+ if (w[strlen(w)-1]=='\r')
+ w[strlen(w)-1]=0;
+ while(*s == ':') // ignore leading : like in ::set a 10
+ ++s;
+ bool quote = sc.state == SCE_TCL_IN_QUOTE;
+ if (commentLevel || expected) {
+ if (keywords.InList(s)) {
+ sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4);
+ } else if (sc.GetRelative(-static_cast<int>(strlen(s))-1) == '{' &&
+ keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces
+ sc.ChangeState(SCE_TCL_EXPAND);
+ }
+ if (keywords6.InList(s)) {
+ sc.ChangeState(SCE_TCL_WORD5);
+ } else if (keywords7.InList(s)) {
+ sc.ChangeState(SCE_TCL_WORD6);
+ } else if (keywords8.InList(s)) {
+ sc.ChangeState(SCE_TCL_WORD7);
+ } else if (keywords9.InList(s)) {
+ sc.ChangeState(SCE_TCL_WORD8);
+ }
+ }
+ expected = false;
+ sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT);
+ } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) {
+ sc.SetState(SCE_TCL_DEFAULT);
+ }
+ }
+ if (atEnd)
+ break;
+ if (sc.atLineEnd) {
+ lineState = LS_DEFAULT;
+ currentLine = styler.GetLine(sc.currentPos);
+ if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) {
+ if (currentLevel == 0) {
+ ++currentLevel;
+ commentLevel = true;
+ }
+ } else {
+ if (visibleChars && commentLevel) {
+ --currentLevel;
+ --previousLevel;
+ commentLevel = false;
+ }
+ }
+ int flag = 0;
+ if (!visibleChars)
+ flag = SC_FOLDLEVELWHITEFLAG;
+ if (currentLevel > previousLevel)
+ flag = SC_FOLDLEVELHEADERFLAG;
+ styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16));
+
+ // Update the line state, so it can be seen by next line
+ if (sc.state == SCE_TCL_IN_QUOTE)
+ lineState = LS_OPEN_DOUBLE_QUOTE;
+ else {
+ if (prevSlash) {
+ if (isComment(sc.state))
+ lineState = LS_OPEN_COMMENT;
+ } else if (sc.state == SCE_TCL_COMMENT_BOX)
+ lineState = LS_COMMENT_BOX;
+ }
+ styler.SetLineState(currentLine,
+ (subBrace ? LS_BRACE_ONLY : 0) |
+ (expected ? LS_COMMAND_EXPECTED : 0) | lineState);
+ if (lineState == LS_COMMENT_BOX)
+ sc.ForwardSetState(SCE_TCL_COMMENT_BOX);
+ else if (lineState == LS_OPEN_DOUBLE_QUOTE)
+ sc.ForwardSetState(SCE_TCL_IN_QUOTE);
+ else
+ sc.ForwardSetState(SCE_TCL_DEFAULT);
+ prevSlash = false;
+ previousLevel = currentLevel;
+ goto next;
+ }
+
+ if (prevSlash) {
+ prevSlash = false;
+ if (sc.ch == '#' && IsANumberChar(sc.chNext))
+ sc.ForwardSetState(SCE_TCL_NUMBER);
+ continue;
+ }
+ prevSlash = sc.ch == '\\';
+ if (isComment(sc.state))
+ continue;
+ if (sc.atLineStart) {
+ visibleChars = false;
+ if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state))
+ {
+ sc.SetState(SCE_TCL_DEFAULT);
+ expected = IsAWordStart(sc.ch)|| isspacechar(static_cast<unsigned char>(sc.ch));
+ }
+ }
+
+ switch (sc.state) {
+ case SCE_TCL_NUMBER:
+ if (!IsANumberChar(sc.ch))
+ sc.SetState(SCE_TCL_DEFAULT);
+ break;
+ case SCE_TCL_IN_QUOTE:
+ if (sc.ch == '"') {
+ sc.ForwardSetState(SCE_TCL_DEFAULT);
+ visibleChars = true; // necessary if a " is the first and only character on a line
+ goto next;
+ } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') {
+ sc.SetState(SCE_TCL_OPERATOR);
+ expected = sc.ch == '[';
+ sc.ForwardSetState(SCE_TCL_IN_QUOTE);
+ goto next;
+ }
+ continue;
+ case SCE_TCL_OPERATOR:
+ sc.SetState(SCE_TCL_DEFAULT);
+ break;
+ }
+
+ if (sc.ch == '#') {
+ if (visibleChars) {
+ if (sc.state != SCE_TCL_IN_QUOTE && expected)
+ sc.SetState(SCE_TCL_COMMENT);
+ } else {
+ sc.SetState(SCE_TCL_COMMENTLINE);
+ if (sc.chNext == '~')
+ sc.SetState(SCE_TCL_BLOCK_COMMENT);
+ if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-'))
+ sc.SetState(SCE_TCL_COMMENT_BOX);
+ }
+ }
+
+ if (!isspacechar(static_cast<unsigned char>(sc.ch))) {
+ visibleChars = true;
+ }
+
+ if (sc.ch == '\\') {
+ prevSlash = true;
+ continue;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_TCL_DEFAULT) {
+ if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_TCL_IDENTIFIER);
+ } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) {
+ sc.SetState(SCE_TCL_NUMBER);
+ } else {
+ switch (sc.ch) {
+ case '\"':
+ sc.SetState(SCE_TCL_IN_QUOTE);
+ break;
+ case '{':
+ sc.SetState(SCE_TCL_OPERATOR);
+ expected = true;
+ ++currentLevel;
+ break;
+ case '}':
+ sc.SetState(SCE_TCL_OPERATOR);
+ --currentLevel;
+ break;
+ case '[':
+ expected = true;
+ case ']':
+ case '(':
+ case ')':
+ sc.SetState(SCE_TCL_OPERATOR);
+ break;
+ case ';':
+ expected = true;
+ break;
+ case '$':
+ subParen = 0;
+ if (sc.chNext != '{') {
+ sc.SetState(SCE_TCL_SUBSTITUTION);
+ }
+ else {
+ sc.SetState(SCE_TCL_OPERATOR); // $
+ sc.Forward(); // {
+ sc.ForwardSetState(SCE_TCL_SUB_BRACE);
+ subBrace = true;
+ }
+ break;
+ case '#':
+ if ((isspacechar(static_cast<unsigned char>(sc.chPrev))||
+ isoperator(static_cast<char>(sc.chPrev))) && IsADigit(sc.chNext,0x10))
+ sc.SetState(SCE_TCL_NUMBER);
+ break;
+ case '-':
+ sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER);
+ break;
+ default:
+ if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_TCL_OPERATOR);
+ }
+ }
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static const char * const tclWordListDesc[] = {
+ "TCL Keywords",
+ "TK Keywords",
+ "iTCL Keywords",
+ "tkCommands",
+ "expand"
+ "user1",
+ "user2",
+ "user3",
+ "user4",
+ 0
+ };
+
+// this code supports folding in the colourizer
+LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc);
diff --git a/scintilla/src/LexTeX.cxx b/scintilla/src/LexTeX.cxx
new file mode 100644
index 0000000..220cbc6
--- /dev/null
+++ b/scintilla/src/LexTeX.cxx
@@ -0,0 +1,494 @@
+// Scintilla source code edit control
+
+// File: LexTeX.cxx - general context conformant tex coloring scheme
+// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
+// Version: September 28, 2003
+
+// Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// This lexer is derived from the one written for the texwork environment (1999++) which in
+// turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
+
+// If you run into strange boundary cases, just tell me and I'll look into it.
+
+
+// TeX Folding code added by instanton (soft_share@126.com) with borrowed code from VisualTeX source by Alex Romanenko.
+// Version: June 22, 2007
+
+#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"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// val SCE_TEX_DEFAULT = 0
+// val SCE_TEX_SPECIAL = 1
+// val SCE_TEX_GROUP = 2
+// val SCE_TEX_SYMBOL = 3
+// val SCE_TEX_COMMAND = 4
+// val SCE_TEX_TEXT = 5
+
+// Definitions in SciTEGlobal.properties:
+//
+// TeX Highlighting
+//
+// # Default
+// style.tex.0=fore:#7F7F00
+// # Special
+// style.tex.1=fore:#007F7F
+// # Group
+// style.tex.2=fore:#880000
+// # Symbol
+// style.tex.3=fore:#7F7F00
+// # Command
+// style.tex.4=fore:#008800
+// # Text
+// style.tex.5=fore:#000000
+
+// lexer.tex.interface.default=0
+// lexer.tex.comment.process=0
+
+// todo: lexer.tex.auto.if
+
+// Auxiliary functions:
+
+static inline bool endOfLine(Accessor &styler, unsigned int i) {
+ return
+ (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
+}
+
+static inline bool isTeXzero(int ch) {
+ return
+ (ch == '%') ;
+}
+
+static inline bool isTeXone(int ch) {
+ return
+ (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') ||
+ (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') ||
+ (ch == '"') ;
+}
+
+static inline bool isTeXtwo(int ch) {
+ return
+ (ch == '{') || (ch == '}') || (ch == '$') ;
+}
+
+static inline bool isTeXthree(int ch) {
+ return
+ (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') ||
+ (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') ||
+ (ch == '/') || (ch == '|') || (ch == '%') ;
+}
+
+static inline bool isTeXfour(int ch) {
+ return
+ (ch == '\\') ;
+}
+
+static inline bool isTeXfive(int ch) {
+ return
+ ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
+ (ch == '@') || (ch == '!') || (ch == '?') ;
+}
+
+static inline bool isTeXsix(int ch) {
+ return
+ (ch == ' ') ;
+}
+
+static inline bool isTeXseven(int ch) {
+ return
+ (ch == '^') ;
+}
+
+// Interface determination
+
+static int CheckTeXInterface(
+ unsigned int startPos,
+ int length,
+ Accessor &styler,
+ int defaultInterface) {
+
+ char lineBuffer[1024] ;
+ unsigned int linePos = 0 ;
+
+ // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)...
+
+ if (styler.SafeGetCharAt(0) == '%') {
+ for (unsigned int i = 0; i < startPos + length; i++) {
+ lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
+ if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ lineBuffer[linePos] = '\0';
+ if (strstr(lineBuffer, "interface=all")) {
+ return 0 ;
+ } else if (strstr(lineBuffer, "interface=tex")) {
+ return 1 ;
+ } else if (strstr(lineBuffer, "interface=nl")) {
+ return 2 ;
+ } else if (strstr(lineBuffer, "interface=en")) {
+ return 3 ;
+ } else if (strstr(lineBuffer, "interface=de")) {
+ return 4 ;
+ } else if (strstr(lineBuffer, "interface=cz")) {
+ return 5 ;
+ } else if (strstr(lineBuffer, "interface=it")) {
+ return 6 ;
+ } else if (strstr(lineBuffer, "interface=ro")) {
+ return 7 ;
+ } else if (strstr(lineBuffer, "interface=latex")) {
+ // we will move latex cum suis up to 91+ when more keyword lists are supported
+ return 8 ;
+ } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
+ // better would be to limit the search to just one line
+ return 3 ;
+ } else {
+ return defaultInterface ;
+ }
+ }
+ }
+ }
+
+ return defaultInterface ;
+}
+
+static void ColouriseTeXDoc(
+ unsigned int startPos,
+ int length,
+ int,
+ WordList *keywordlists[],
+ Accessor &styler) {
+
+ styler.StartAt(startPos) ;
+ styler.StartSegment(startPos) ;
+
+ bool processComment = styler.GetPropertyInt("lexer.tex.comment.process", 0) == 1 ;
+ bool useKeywords = styler.GetPropertyInt("lexer.tex.use.keywords", 1) == 1 ;
+ bool autoIf = styler.GetPropertyInt("lexer.tex.auto.if", 1) == 1 ;
+ int defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ;
+
+ char key[100] ;
+ int k ;
+ bool newifDone = false ;
+ bool inComment = false ;
+
+ int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ;
+
+ if (currentInterface == 0) {
+ useKeywords = false ;
+ currentInterface = 1 ;
+ }
+
+ WordList &keywords = *keywordlists[currentInterface-1] ;
+
+ StyleContext sc(startPos, length, SCE_TEX_TEXT, styler);
+
+ bool going = sc.More() ; // needed because of a fuzzy end of file state
+
+ for (; going; sc.Forward()) {
+
+ if (! sc.More()) { going = false ; } // we need to go one behind the end of text
+
+ if (inComment) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_TEX_TEXT) ;
+ newifDone = false ;
+ inComment = false ;
+ }
+ } else {
+ if (! isTeXfive(sc.ch)) {
+ if (sc.state == SCE_TEX_COMMAND) {
+ if (sc.LengthCurrent() == 1) { // \<noncstoken>
+ if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) {
+ sc.Forward(2) ; // \^^ and \^^<token>
+ }
+ sc.ForwardSetState(SCE_TEX_TEXT) ;
+ } else {
+ sc.GetCurrent(key, sizeof(key)-1) ;
+ k = strlen(key) ;
+ memmove(key,key+1,k) ; // shift left over escape token
+ key[k] = '\0' ;
+ k-- ;
+ if (! keywords || ! useKeywords) {
+ sc.SetState(SCE_TEX_COMMAND) ;
+ newifDone = false ;
+ } else if (k == 1) { //\<cstoken>
+ sc.SetState(SCE_TEX_COMMAND) ;
+ newifDone = false ;
+ } else if (keywords.InList(key)) {
+ sc.SetState(SCE_TEX_COMMAND) ;
+ newifDone = autoIf && (strcmp(key,"newif") == 0) ;
+ } else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) {
+ sc.SetState(SCE_TEX_COMMAND) ;
+ } else {
+ sc.ChangeState(SCE_TEX_TEXT) ;
+ sc.SetState(SCE_TEX_TEXT) ;
+ newifDone = false ;
+ }
+ }
+ }
+ if (isTeXzero(sc.ch)) {
+ sc.SetState(SCE_TEX_SYMBOL);
+
+ if (!endOfLine(styler,sc.currentPos + 1))
+ sc.ForwardSetState(SCE_TEX_DEFAULT) ;
+
+ inComment = ! processComment ;
+ newifDone = false ;
+ } else if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) {
+ sc.SetState(SCE_TEX_TEXT) ;
+ sc.ForwardSetState(SCE_TEX_TEXT) ;
+ } else if (isTeXone(sc.ch)) {
+ sc.SetState(SCE_TEX_SPECIAL) ;
+ newifDone = false ;
+ } else if (isTeXtwo(sc.ch)) {
+ sc.SetState(SCE_TEX_GROUP) ;
+ newifDone = false ;
+ } else if (isTeXthree(sc.ch)) {
+ sc.SetState(SCE_TEX_SYMBOL) ;
+ newifDone = false ;
+ } else if (isTeXfour(sc.ch)) {
+ sc.SetState(SCE_TEX_COMMAND) ;
+ } else if (isTeXsix(sc.ch)) {
+ sc.SetState(SCE_TEX_TEXT) ;
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_TEX_TEXT) ;
+ newifDone = false ;
+ inComment = false ;
+ } else {
+ sc.SetState(SCE_TEX_TEXT) ;
+ }
+ } else if (sc.state != SCE_TEX_COMMAND) {
+ sc.SetState(SCE_TEX_TEXT) ;
+ }
+ }
+ }
+ sc.ChangeState(SCE_TEX_TEXT) ;
+ sc.Complete();
+
+}
+
+
+static inline bool isNumber(int ch) {
+ return
+ (ch == '0') || (ch == '1') || (ch == '2') ||
+ (ch == '3') || (ch == '4') || (ch == '5') ||
+ (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9');
+}
+
+static inline bool isWordChar(int ch) {
+ return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'));
+}
+
+static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command)
+{
+ int length=0;
+ char ch=styler.SafeGetCharAt(pos+1);
+
+ if(ch==',' || ch==':' || ch==';' || ch=='%'){
+ command[0]=ch;
+ command[1]=0;
+ return 1;
+ }
+
+ // find end
+ while(isWordChar(ch) && !isNumber(ch) && ch!='_' && ch!='.' && length<100){
+ command[length]=ch;
+ length++;
+ ch=styler.SafeGetCharAt(pos+length+1);
+ }
+
+ command[length]='\0';
+ if(!length) return 0;
+ return length+1;
+}
+
+static int classifyFoldPointTeXPaired(const char* s) {
+ int lev=0;
+ if (!(isdigit(s[0]) || (s[0] == '.'))){
+ if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0||
+ strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0||
+ strcmp(s,"title")==0||strncmp(s,"start",5)==0||strncmp(s,"Start",5)==0||
+ strcmp(s,"documentclass")==0||strncmp(s,"if",2)==0
+ )
+ lev=1;
+ if (strcmp(s, "end")==0||strcmp(s,"FoldStop")==0||
+ strcmp(s,"maketitle")==0||strcmp(s,"protect")==0||
+ strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0||
+ strcmp(s,"fi")==0
+ )
+ lev=-1;
+ }
+ return lev;
+}
+
+static int classifyFoldPointTeXUnpaired(const char* s) {
+ int lev=0;
+ if (!(isdigit(s[0]) || (s[0] == '.'))){
+ if (strcmp(s,"part")==0||
+ strcmp(s,"chapter")==0||
+ strcmp(s,"section")==0||
+ strcmp(s,"subsection")==0||
+ strcmp(s,"subsubsection")==0||
+ strcmp(s,"CJKfamily")==0||
+ strcmp(s,"appendix")==0||
+ strcmp(s,"Topic")==0||strcmp(s,"topic")==0||
+ strcmp(s,"subject")==0||strcmp(s,"subsubject")==0||
+ strcmp(s,"def")==0||strcmp(s,"gdef")==0||strcmp(s,"edef")==0||
+ strcmp(s,"xdef")==0||strcmp(s,"framed")==0||
+ strcmp(s,"frame")==0||
+ strcmp(s,"foilhead")==0||strcmp(s,"overlays")==0||strcmp(s,"slide")==0
+ ){
+ lev=1;
+ }
+ }
+ return lev;
+}
+
+static bool IsTeXCommentLine(int line, Accessor &styler) {
+ int pos = styler.LineStart(line);
+ int eol_pos = styler.LineStart(line + 1) - 1;
+
+ int startpos = pos;
+
+ while (startpos<eol_pos){
+ char ch = styler[startpos];
+ if (ch!='%' && ch!=' ') return false;
+ else if (ch=='%') return true;
+ startpos++;
+ }
+
+ return false;
+}
+
+// FoldTeXDoc: borrowed from VisualTeX with modifications
+
+static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ 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];
+ char buffer[100]="";
+
+ for (unsigned int i=startPos; i < endPos; i++) {
+ char ch=chNext;
+ chNext=styler.SafeGetCharAt(i+1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if(ch=='\\') {
+ ParseTeXCommand(i, styler, buffer);
+ levelCurrent += classifyFoldPointTeXPaired(buffer)+classifyFoldPointTeXUnpaired(buffer);
+ }
+
+ if (levelCurrent > SC_FOLDLEVELBASE && ((ch == '\r' || ch=='\n') && (chNext == '\\'))) {
+ ParseTeXCommand(i+1, styler, buffer);
+ levelCurrent -= classifyFoldPointTeXUnpaired(buffer);
+ }
+
+ char chNext2;
+ char chNext3;
+ char chNext4;
+ char chNext5;
+ chNext2=styler.SafeGetCharAt(i+2);
+ chNext3=styler.SafeGetCharAt(i+3);
+ chNext4=styler.SafeGetCharAt(i+4);
+ chNext5=styler.SafeGetCharAt(i+5);
+
+ bool atEOfold = (ch == '%') &&
+ (chNext == '%') && (chNext2=='}') &&
+ (chNext3=='}')&& (chNext4=='-')&& (chNext5=='-');
+
+ bool atBOfold = (ch == '%') &&
+ (chNext == '%') && (chNext2=='-') &&
+ (chNext3=='-')&& (chNext4=='{')&& (chNext5=='{');
+
+ if(atBOfold){
+ levelCurrent+=1;
+ }
+
+ if(atEOfold){
+ levelCurrent-=1;
+ }
+
+ if(ch=='\\' && chNext=='['){
+ levelCurrent+=1;
+ }
+
+ if(ch=='\\' && chNext==']'){
+ levelCurrent-=1;
+ }
+
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+
+ if (foldComment && atEOL && IsTeXCommentLine(lineCurrent, styler))
+ {
+ if (lineCurrent==0 && IsTeXCommentLine(lineCurrent + 1, styler)
+ )
+ levelCurrent++;
+ else if (lineCurrent!=0 && !IsTeXCommentLine(lineCurrent - 1, styler)
+ && IsTeXCommentLine(lineCurrent + 1, styler)
+ )
+ levelCurrent++;
+ else if (lineCurrent!=0 && IsTeXCommentLine(lineCurrent - 1, styler) &&
+ !IsTeXCommentLine(lineCurrent+1, styler))
+ 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 texWordListDesc[] = {
+ "TeX, eTeX, pdfTeX, Omega",
+ "ConTeXt Dutch",
+ "ConTeXt English",
+ "ConTeXt German",
+ "ConTeXt Czech",
+ "ConTeXt Italian",
+ "ConTeXt Romanian",
+ 0,
+} ;
+
+LexerModule lmTeX(SCLEX_TEX, ColouriseTeXDoc, "tex", FoldTexDoc, texWordListDesc);
diff --git a/scintilla/src/LexVB.cxx b/scintilla/src/LexVB.cxx
new file mode 100644
index 0000000..511d244
--- /dev/null
+++ b/scintilla/src/LexVB.cxx
@@ -0,0 +1,316 @@
+// Scintilla source code edit control
+/** @file LexVB.cxx
+ ** Lexer for Visual Basic and VBScript.
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// 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] == '\'';
+}
+
+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 ||
+ (isalpha(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 == '+');
+}
+
+static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler, bool vbScriptSyntax) {
+
+ WordList &keywords = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
+ WordList &keywords3 = *keywordlists[2];
+ WordList &keywords4 = *keywordlists[3];
+
+ 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);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.state == SCE_B_OPERATOR) {
+ sc.SetState(SCE_B_DEFAULT);
+ } else if (sc.state == SCE_B_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch)) {
+ // In Basic (except VBScript), a variable name or a function name
+ // can end with a special character indicating the type of the value
+ // held or returned.
+ bool skipType = false;
+ if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) {
+ sc.Forward(); // Skip it
+ skipType = true;
+ }
+ if (sc.ch == ']') {
+ sc.Forward();
+ }
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (skipType) {
+ s[strlen(s) - 1] = '\0';
+ }
+ if (strcmp(s, "rem") == 0) {
+ sc.ChangeState(SCE_B_COMMENT);
+ } else {
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD4);
+ } // Else, it is really an identifier...
+ sc.SetState(SCE_B_DEFAULT);
+ }
+ }
+ } else if (sc.state == SCE_B_NUMBER) {
+ // 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) {
+ // VB doubles quotes to preserve them, so just end this string
+ // state now as a following quote will start again
+ if (sc.ch == '\"') {
+ if (sc.chNext == '\"') {
+ sc.Forward();
+ } else {
+ if (tolower(sc.chNext) == 'c') {
+ sc.Forward();
+ }
+ sc.ForwardSetState(SCE_B_DEFAULT);
+ }
+ } else if (sc.atLineEnd) {
+ visibleChars = 0;
+ sc.ChangeState(SCE_B_STRINGEOL);
+ sc.ForwardSetState(SCE_B_DEFAULT);
+ }
+ } else if (sc.state == SCE_B_COMMENT) {
+ if (sc.atLineEnd) {
+ visibleChars = 0;
+ sc.ForwardSetState(SCE_B_DEFAULT);
+ }
+ } else if (sc.state == SCE_B_PREPROCESSOR) {
+ if (sc.atLineEnd) {
+ visibleChars = 0;
+ 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.atLineEnd) {
+ visibleChars = 0;
+ sc.ChangeState(SCE_B_STRINGEOL);
+ sc.ForwardSetState(SCE_B_DEFAULT);
+ } else if (sc.ch == '#') {
+ sc.ForwardSetState(SCE_B_DEFAULT);
+ }
+ }
+
+ if (sc.state == SCE_B_DEFAULT) {
+ if (sc.ch == '\'') {
+ sc.SetState(SCE_B_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_B_STRING);
+ } else if (sc.ch == '#' && visibleChars == 0) {
+ // Preprocessor commands are alone on their line
+ sc.SetState(SCE_B_PREPROCESSOR);
+ } else if (sc.ch == '#') {
+ // 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 == '\\')) { // Integer division
+ sc.SetState(SCE_B_OPERATOR);
+ }
+ }
+
+ if (sc.atLineEnd) {
+ visibleChars = 0;
+ }
+ if (!IsASpace(sc.ch)) {
+ visibleChars++;
+ }
+ }
+
+ if (sc.state == SCE_B_IDENTIFIER && !IsAWordChar(sc.ch)) {
+ // In Basic (except VBScript), a variable name or a function name
+ // can end with a special character indicating the type of the value
+ // held or returned.
+ bool skipType = false;
+ if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) {
+ sc.Forward(); // Skip it
+ skipType = true;
+ }
+ if (sc.ch == ']') {
+ sc.Forward();
+ }
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (skipType) {
+ s[strlen(s) - 1] = '\0';
+ }
+ if (strcmp(s, "rem") == 0) {
+ sc.ChangeState(SCE_B_COMMENT);
+ } else {
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_B_KEYWORD4);
+ } // Else, it is really an identifier...
+ sc.SetState(SCE_B_DEFAULT);
+ }
+ }
+
+ sc.Complete();
+}
+
+static void FoldVBDoc(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, IsVBComment);
+ 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, IsVBComment);
+ 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, IsVBComment);
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+ }
+ }
+ indentCurrent = indentNext;
+ styler.SetLevel(lineCurrent, lev);
+ lineCurrent++;
+ }
+ }
+}
+
+static void ColouriseVBNetDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, false);
+}
+
+static void ColouriseVBScriptDoc(unsigned int startPos, int length, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, true);
+}
+
+static const char * const vbWordListDesc[] = {
+ "Keywords",
+ "user1",
+ "user2",
+ "user3",
+ 0
+};
+
+LexerModule lmVB(SCLEX_VB, ColouriseVBNetDoc, "vb", FoldVBDoc, vbWordListDesc);
+LexerModule lmVBScript(SCLEX_VBSCRIPT, ColouriseVBScriptDoc, "vbscript", FoldVBDoc, vbWordListDesc);
+
diff --git a/scintilla/src/LexVHDL.cxx b/scintilla/src/LexVHDL.cxx
new file mode 100644
index 0000000..ff13857
--- /dev/null
+++ b/scintilla/src/LexVHDL.cxx
@@ -0,0 +1,476 @@
+// Scintilla source code edit control
+/** @file LexVHDL.cxx
+ ** Lexer for VHDL
+ ** Written by Phil Reid,
+ ** Based on:
+ ** - The Verilog Lexer by Avi Yegudin
+ ** - The Fortran Lexer by Chuan-jian Shen
+ ** - The C++ lexer by Neil Hodgson
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void ColouriseVHDLDoc(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler);
+
+
+/***************************************/
+static inline bool IsAWordChar(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' );
+}
+
+/***************************************/
+static inline bool IsAWordStart(const int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+/***************************************/
+inline bool IsABlank(unsigned int ch) {
+ return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ;
+}
+
+/***************************************/
+static void ColouriseVHDLDoc(
+ unsigned int startPos,
+ int length,
+ int initStyle,
+ WordList *keywordlists[],
+ Accessor &styler)
+{
+ WordList &Keywords = *keywordlists[0];
+ WordList &Operators = *keywordlists[1];
+ WordList &Attributes = *keywordlists[2];
+ WordList &Functions = *keywordlists[3];
+ WordList &Packages = *keywordlists[4];
+ WordList &Types = *keywordlists[5];
+ WordList &User = *keywordlists[6];
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward())
+ {
+
+ // Determine if the current state should terminate.
+ if (sc.state == SCE_VHDL_OPERATOR) {
+ sc.SetState(SCE_VHDL_DEFAULT);
+ } else if (sc.state == SCE_VHDL_NUMBER) {
+ if (!IsAWordChar(sc.ch) && (sc.ch != '#')) {
+ sc.SetState(SCE_VHDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_VHDL_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (Keywords.InList(s)) {
+ sc.ChangeState(SCE_VHDL_KEYWORD);
+ } else if (Operators.InList(s)) {
+ sc.ChangeState(SCE_VHDL_STDOPERATOR);
+ } else if (Attributes.InList(s)) {
+ sc.ChangeState(SCE_VHDL_ATTRIBUTE);
+ } else if (Functions.InList(s)) {
+ sc.ChangeState(SCE_VHDL_STDFUNCTION);
+ } else if (Packages.InList(s)) {
+ sc.ChangeState(SCE_VHDL_STDPACKAGE);
+ } else if (Types.InList(s)) {
+ sc.ChangeState(SCE_VHDL_STDTYPE);
+ } else if (User.InList(s)) {
+ sc.ChangeState(SCE_VHDL_USERWORD);
+ }
+ sc.SetState(SCE_VHDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_V_COMMENTLINEBANG) {
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_VHDL_DEFAULT);
+ }
+ } else if (sc.state == SCE_VHDL_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_VHDL_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_V_STRINGEOL);
+ sc.ForwardSetState(SCE_VHDL_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_VHDL_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_VHDL_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_VHDL_IDENTIFIER);
+ } else if (sc.Match('-', '-')) {
+ sc.SetState(SCE_VHDL_COMMENT);
+ sc.Forward();
+ } else if (sc.Match('-', '-')) {
+ if (sc.Match("--!")) // Nice to have a different comment style
+ sc.SetState(SCE_VHDL_COMMENTLINEBANG);
+ else
+ sc.SetState(SCE_VHDL_COMMENT);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_VHDL_STRING);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_VHDL_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+//=============================================================================
+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];
+ char chNext = styler[i+1];
+ if ((ch == '-') && (chNext == '-'))
+ return true;
+ else if (ch != ' ' && ch != '\t')
+ return false;
+ }
+ return false;
+}
+
+//=============================================================================
+// Folding the code
+static void FoldNoBoxVHDLDoc(
+ unsigned int startPos,
+ int length,
+ int,
+ Accessor &styler)
+{
+ // Decided it would be smarter to have the lexer have all keywords included. Therefore I
+ // don't check if the style for the keywords that I use to adjust the levels.
+ char words[] =
+ "architecture begin case component else elsif end entity generate loop package process record then "
+ "procedure function when";
+ WordList keywords;
+ keywords.Set(words);
+
+ bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 1) != 0;
+ bool foldAtBegin = styler.GetPropertyInt("fold.at.Begin", 1) != 0;
+ bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0;
+ //bool foldAtWhen = styler.GetPropertyInt("fold.at.When", 1) != 0; //< fold at when in case statements
+
+ int visibleChars = 0;
+ unsigned int endPos = startPos + length;
+
+ int lineCurrent = styler.GetLine(startPos);
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if(lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ //int levelMinCurrent = levelCurrent;
+ int levelMinCurrentElse = levelCurrent; //< Used for folding at 'else'
+ int levelMinCurrentBegin = levelCurrent; //< Used for folding at 'begin'
+ int levelNext = levelCurrent;
+
+ /***************************************/
+ int lastStart = 0;
+ char prevWord[32] = "";
+
+ /***************************************/
+ // Find prev word
+ // The logic for going up or down a level depends on a the previous keyword
+ // This code could be cleaned up.
+ int end = 0;
+ unsigned int j;
+ for(j = startPos; j>0; j--)
+ {
+ char ch = styler.SafeGetCharAt(j);
+ char chPrev = styler.SafeGetCharAt(j-1);
+ int style = styler.StyleAt(j);
+ int stylePrev = styler.StyleAt(j-1);
+ if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING))
+ {
+ if(IsAWordChar(chPrev) && !IsAWordChar(ch))
+ {
+ end = j-1;
+ }
+ }
+ if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
+ {
+ if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0))
+ {
+ char s[32];
+ unsigned int k;
+ for(k=0; (k<31 ) && (k<end-j+1 ); k++) {
+ s[k] = static_cast<char>(tolower(styler[j+k]));
+ }
+ s[k] = '\0';
+
+ if(keywords.InList(s)) {
+ strcpy(prevWord, s);
+ break;
+ }
+ }
+ }
+ }
+ for(j=j+strlen(prevWord); j<endPos; j++)
+ {
+ char ch = styler.SafeGetCharAt(j);
+ int style = styler.StyleAt(j);
+ if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
+ {
+ if((ch == ';') && (strcmp(prevWord, "end") == 0))
+ {
+ strcpy(prevWord, ";");
+ }
+ }
+ }
+
+ char chNext = styler[startPos];
+ char chPrev = '\0';
+ char chNextNonBlank;
+ int styleNext = styler.StyleAt(startPos);
+ //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent);
+
+ /***************************************/
+ for (unsigned int i = startPos; i < endPos; i++)
+ {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ chPrev = styler.SafeGetCharAt(i - 1);
+ chNextNonBlank = chNext;
+ unsigned int j = i+1;
+ while(IsABlank(chNextNonBlank) && j<endPos)
+ {
+ j ++ ;
+ chNextNonBlank = styler.SafeGetCharAt(j);
+ }
+ int style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+ {
+ if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler))
+ {
+ levelNext++;
+ }
+ else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler))
+ {
+ levelNext--;
+ }
+ }
+
+ if ((style == SCE_VHDL_OPERATOR) && foldAtParenthese)
+ {
+ if(ch == '(') {
+ levelNext++;
+ } else if (ch == ')') {
+ levelNext--;
+ }
+ }
+
+ if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
+ {
+ if((ch == ';') && (strcmp(prevWord, "end") == 0))
+ {
+ strcpy(prevWord, ";");
+ }
+
+ if(!IsAWordChar(chPrev) && IsAWordStart(ch))
+ {
+ lastStart = i;
+ }
+
+ if(iswordchar(ch) && !iswordchar(chNext)) {
+ char s[32];
+ unsigned int k;
+ for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) {
+ s[k] = static_cast<char>(tolower(styler[lastStart+k]));
+ }
+ s[k] = '\0';
+
+ if(keywords.InList(s))
+ {
+ if (
+ strcmp(s, "architecture") == 0 ||
+ strcmp(s, "case") == 0 ||
+ strcmp(s, "component") == 0 ||
+ strcmp(s, "entity") == 0 ||
+ strcmp(s, "generate") == 0 ||
+ strcmp(s, "loop") == 0 ||
+ strcmp(s, "package") ==0 ||
+ strcmp(s, "process") == 0 ||
+ strcmp(s, "record") == 0 ||
+ strcmp(s, "then") == 0)
+ {
+ if (strcmp(prevWord, "end") != 0)
+ {
+ if (levelMinCurrentElse > levelNext) {
+ levelMinCurrentElse = levelNext;
+ }
+ levelNext++;
+ }
+ } else if (
+ strcmp(s, "procedure") == 0 ||
+ strcmp(s, "function") == 0)
+ {
+ if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc.
+ { // This code checks to see if the procedure / function is a definition within a "package"
+ // rather than the actual code in the body.
+ int BracketLevel = 0;
+ for(int j=i+1; j<styler.Length(); j++)
+ {
+ int LocalStyle = styler.StyleAt(j);
+ char LocalCh = styler.SafeGetCharAt(j);
+ if(LocalCh == '(') BracketLevel++;
+ if(LocalCh == ')') BracketLevel--;
+ if(
+ (BracketLevel == 0) &&
+ (LocalStyle != SCE_VHDL_COMMENT) &&
+ (LocalStyle != SCE_VHDL_STRING) &&
+ !iswordchar(styler.SafeGetCharAt(j-1)) &&
+ styler.Match(j, "is") &&
+ !iswordchar(styler.SafeGetCharAt(j+2)))
+ {
+ if (levelMinCurrentElse > levelNext) {
+ levelMinCurrentElse = levelNext;
+ }
+ levelNext++;
+ break;
+ }
+ if((BracketLevel == 0) && (LocalCh == ';'))
+ {
+ break;
+ }
+ }
+ }
+
+ } else if (strcmp(s, "end") == 0) {
+ levelNext--;
+ } else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly
+ levelNext--;
+ } else if (strcmp(s, "else") == 0) {
+ if(strcmp(prevWord, "when") != 0) // ignore a <= x when y else z;
+ {
+ levelMinCurrentElse = levelNext - 1; // VHDL else is all on its own so just dec. the min level
+ }
+ } else if(
+ ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) ||
+ ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) ||
+ ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0)))
+ {
+ levelMinCurrentBegin = levelNext - 1;
+ }
+ //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent);
+ strcpy(prevWord, s);
+ }
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+
+ if (foldAtElse && (levelMinCurrentElse < levelUse)) {
+ levelUse = levelMinCurrentElse;
+ }
+ if (foldAtBegin && (levelMinCurrentBegin < levelUse)) {
+ levelUse = levelMinCurrentBegin;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
+ lineCurrent++;
+ levelCurrent = levelNext;
+ //levelMinCurrent = levelCurrent;
+ levelMinCurrentElse = levelCurrent;
+ levelMinCurrentBegin = levelCurrent;
+ visibleChars = 0;
+ }
+ /***************************************/
+ if (!isspacechar(ch)) visibleChars++;
+ }
+
+ /***************************************/
+// Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
+}
+
+//=============================================================================
+static void FoldVHDLDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ FoldNoBoxVHDLDoc(startPos, length, initStyle, styler);
+}
+
+//=============================================================================
+static const char * const VHDLWordLists[] = {
+ "Keywords",
+ "Operators",
+ "Attributes",
+ "Standard Functions",
+ "Standard Packages",
+ "Standard Types",
+ "User Words",
+ 0,
+ };
+
+
+LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLists);
+
+
+// Keyword:
+// access after alias all architecture array assert attribute begin block body buffer bus case component
+// configuration constant disconnect downto else elsif end entity exit file for function generate generic
+// group guarded if impure in inertial inout is label library linkage literal loop map new next null of
+// on open others out package port postponed procedure process pure range record register reject report
+// return select severity shared signal subtype then to transport type unaffected units until use variable
+// wait when while with
+//
+// Operators:
+// abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor
+//
+// Attributes:
+// left right low high ascending image value pos val succ pred leftof rightof base range reverse_range
+// length delayed stable quiet transaction event active last_event last_active last_value driving
+// driving_value simple_name path_name instance_name
+//
+// Std Functions:
+// now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector
+// to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left
+// rotate_right resize to_integer to_unsigned to_signed std_match to_01
+//
+// Std Packages:
+// std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed
+// std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives
+// vital_timing
+//
+// Std Types:
+// boolean bit character severity_level integer real time delay_length natural positive string bit_vector
+// file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic
+// std_logic_vector X01 X01Z UX01 UX01Z unsigned signed
+//
+
diff --git a/scintilla/src/LexVerilog.cxx b/scintilla/src/LexVerilog.cxx
new file mode 100644
index 0000000..4a94acc
--- /dev/null
+++ b/scintilla/src/LexVerilog.cxx
@@ -0,0 +1,330 @@
+// Scintilla source code edit control
+/** @file LexVerilog.cxx
+ ** Lexer for Verilog.
+ ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
+ **/
+// 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 <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 SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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 == '$');
+}
+
+static void ColouriseVerilogDoc(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];
+
+ // Do not leak onto next line
+ if (initStyle == SCE_V_STRINGEOL)
+ initStyle = SCE_V_DEFAULT;
+
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ for (; sc.More(); sc.Forward()) {
+
+ if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
+ // Prevent SCE_V_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_V_STRING);
+ }
+
+ // 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_V_OPERATOR) {
+ sc.SetState(SCE_V_DEFAULT);
+ } else if (sc.state == SCE_V_NUMBER) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_V_DEFAULT);
+ }
+ } else if (sc.state == SCE_V_IDENTIFIER) {
+ if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords.InList(s)) {
+ sc.ChangeState(SCE_V_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_V_WORD2);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_V_WORD3);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_V_USER);
+ }
+ sc.SetState(SCE_V_DEFAULT);
+ }
+ } else if (sc.state == SCE_V_PREPROCESSOR) {
+ if (!IsAWordChar(sc.ch)) {
+ sc.SetState(SCE_V_DEFAULT);
+ }
+ } else if (sc.state == SCE_V_COMMENT) {
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_V_DEFAULT);
+ }
+ } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
+ if (sc.atLineStart) {
+ sc.SetState(SCE_V_DEFAULT);
+ }
+ } else if (sc.state == SCE_V_STRING) {
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_V_DEFAULT);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_V_STRINGEOL);
+ sc.ForwardSetState(SCE_V_DEFAULT);
+ }
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_V_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_V_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_V_IDENTIFIER);
+ } else if (sc.Match('/', '*')) {
+ sc.SetState(SCE_V_COMMENT);
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('/', '/')) {
+ if (sc.Match("//!")) // Nice to have a different comment style
+ sc.SetState(SCE_V_COMMENTLINEBANG);
+ else
+ sc.SetState(SCE_V_COMMENTLINE);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_V_STRING);
+ } else if (sc.ch == '`') {
+ sc.SetState(SCE_V_PREPROCESSOR);
+ // Skip whitespace between ` and preprocessor word
+ do {
+ sc.Forward();
+ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
+ if (sc.atLineEnd) {
+ sc.SetState(SCE_V_DEFAULT);
+ }
+ } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
+ sc.SetState(SCE_V_OPERATOR);
+ }
+ }
+ }
+ sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+ return style == SCE_V_COMMENT;
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+ int pos = styler.LineStart(line);
+ int eolPos = styler.LineStart(line + 1) - 1;
+ for (int i = pos; i < eolPos; i++) {
+ char ch = styler[i];
+ char chNext = styler.SafeGetCharAt(i + 1);
+ int style = styler.StyleAt(i);
+ if (ch == '/' && chNext == '/' &&
+ (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) {
+ return true;
+ } else if (!IsASpaceOrTab(ch)) {
+ return false;
+ }
+ }
+ return false;
+}
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment
+// and to make it possible to fiddle the current level for "} else {".
+static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
+ Accessor &styler) {
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
+ // Verilog specific folding options:
+ // fold_at_module -
+ // Generally used methodology in verilog code is
+ // one module per file, so folding at module definition is useless.
+ // fold_at_brace/parenthese -
+ // Folding of long port lists can be convenient.
+ bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
+ bool foldAtBrace = 1;
+ bool foldAtParenthese = 1;
+
+ 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) >> 16;
+ int levelMinCurrent = levelCurrent;
+ int levelNext = levelCurrent;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+ 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 && atEOL && IsCommentLine(lineCurrent, styler))
+ {
+ if (!IsCommentLine(lineCurrent - 1, styler)
+ && IsCommentLine(lineCurrent + 1, styler))
+ levelNext++;
+ else if (IsCommentLine(lineCurrent - 1, styler)
+ && !IsCommentLine(lineCurrent+1, styler))
+ levelNext--;
+ }
+ if (foldComment && (style == SCE_V_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelNext++;
+ } else if (chNext2 == '}') {
+ levelNext--;
+ }
+ }
+ }
+ if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
+ if (ch == '`') {
+ unsigned int j = i + 1;
+ while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ j++;
+ }
+ if (styler.Match(j, "if")) {
+ levelNext++;
+ } else if (styler.Match(j, "end")) {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_V_OPERATOR) {
+ if (foldAtParenthese) {
+ if (ch == '(') {
+ levelNext++;
+ } else if (ch == ')') {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_V_OPERATOR) {
+ if (foldAtBrace) {
+ if (ch == '{') {
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
+ unsigned int j = i;
+ if (styler.Match(j, "case") ||
+ styler.Match(j, "casex") ||
+ styler.Match(j, "casez") ||
+ styler.Match(j, "function") ||
+ styler.Match(j, "fork") ||
+ styler.Match(j, "table") ||
+ styler.Match(j, "task") ||
+ styler.Match(j, "generate") ||
+ styler.Match(j, "specify") ||
+ styler.Match(j, "primitive") ||
+ (styler.Match(j, "module") && foldAtModule) ||
+ styler.Match(j, "begin")) {
+ levelNext++;
+ } else if (styler.Match(j, "endcase") ||
+ styler.Match(j, "endfunction") ||
+ styler.Match(j, "join") ||
+ styler.Match(j, "endtask") ||
+ styler.Match(j, "endgenerate") ||
+ styler.Match(j, "endtable") ||
+ styler.Match(j, "endspecify") ||
+ styler.Match(j, "endprimitive") ||
+ (styler.Match(j, "endmodule") && foldAtModule) ||
+ (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
+ levelNext--;
+ }
+ }
+ if (atEOL) {
+ int levelUse = levelCurrent;
+ if (foldAtElse) {
+ levelUse = levelMinCurrent;
+ }
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+ lineCurrent++;
+ levelCurrent = levelNext;
+ levelMinCurrent = levelCurrent;
+ visibleChars = 0;
+ }
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+}
+
+static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+ Accessor &styler) {
+ FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
+}
+
+static const char * const verilogWordLists[] = {
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "System Tasks",
+ "User defined tasks and identifiers",
+ "Unused",
+ 0,
+ };
+
+
+LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);
diff --git a/scintilla/src/LexYAML.cxx b/scintilla/src/LexYAML.cxx
new file mode 100644
index 0000000..9f1e746
--- /dev/null
+++ b/scintilla/src/LexYAML.cxx
@@ -0,0 +1,314 @@
+// Scintilla source code edit control
+/** @file LexYAML.cxx
+ ** Lexer for YAML.
+ **/
+// Copyright 2003- by Sean O'Dell <sean@celsoft.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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static const char * const yamlWordListDesc[] = {
+ "Keywords",
+ 0
+};
+
+static inline bool AtEOL(Accessor &styler, unsigned int i) {
+ return (styler[i] == '\n') ||
+ ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+}
+
+static unsigned int SpaceCount(char* lineBuffer) {
+ if (lineBuffer == NULL)
+ return 0;
+
+ char* headBuffer = lineBuffer;
+
+ while (*headBuffer == ' ')
+ headBuffer++;
+
+ return headBuffer - lineBuffer;
+}
+
+#define YAML_STATE_BITSIZE 16
+#define YAML_STATE_MASK (0xFFFF0000)
+#define YAML_STATE_DOCUMENT (1 << YAML_STATE_BITSIZE)
+#define YAML_STATE_VALUE (2 << YAML_STATE_BITSIZE)
+#define YAML_STATE_COMMENT (3 << YAML_STATE_BITSIZE)
+#define YAML_STATE_TEXT_PARENT (4 << YAML_STATE_BITSIZE)
+#define YAML_STATE_TEXT (5 << YAML_STATE_BITSIZE)
+
+static void ColouriseYAMLLine(
+ char *lineBuffer,
+ unsigned int currentLine,
+ unsigned int lengthLine,
+ unsigned int startLine,
+ unsigned int endPos,
+ WordList &keywords,
+ Accessor &styler) {
+
+ unsigned int i = 0;
+ bool bInQuotes = false;
+ unsigned int indentAmount = SpaceCount(lineBuffer);
+
+ if (currentLine > 0) {
+ int parentLineState = styler.GetLineState(currentLine - 1);
+
+ if ((parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT || (parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT_PARENT) {
+ unsigned int parentIndentAmount = parentLineState&(~YAML_STATE_MASK);
+ if (indentAmount > parentIndentAmount) {
+ styler.SetLineState(currentLine, YAML_STATE_TEXT | parentIndentAmount);
+ styler.ColourTo(endPos, SCE_YAML_TEXT);
+ return;
+ }
+ }
+ }
+ styler.SetLineState(currentLine, 0);
+ if (strncmp(lineBuffer, "---", 3) == 0) { // Document marker
+ styler.SetLineState(currentLine, YAML_STATE_DOCUMENT);
+ styler.ColourTo(endPos, SCE_YAML_DOCUMENT);
+ return;
+ }
+ // Skip initial spaces
+ while ((i < lengthLine) && lineBuffer[i] == ' ') { // YAML always uses space, never TABS or anything else
+ i++;
+ }
+ if (lineBuffer[i] == '\t') { // if we skipped all spaces, and we are NOT inside a text block, this is wrong
+ styler.ColourTo(endPos, SCE_YAML_ERROR);
+ return;
+ }
+ if (lineBuffer[i] == '#') { // Comment
+ styler.SetLineState(currentLine, YAML_STATE_COMMENT);
+ styler.ColourTo(endPos, SCE_YAML_COMMENT);
+ return;
+ }
+ while (i < lengthLine) {
+ if (lineBuffer[i] == '\'' || lineBuffer[i] == '\"') {
+ bInQuotes = !bInQuotes;
+ } else if (lineBuffer[i] == ':' && !bInQuotes) {
+ styler.ColourTo(startLine + i - 1, SCE_YAML_IDENTIFIER);
+ styler.ColourTo(startLine + i, SCE_YAML_OPERATOR);
+ // Non-folding scalar
+ i++;
+ while ((i < lengthLine) && isspacechar(lineBuffer[i]))
+ i++;
+ unsigned int endValue = lengthLine - 1;
+ while ((endValue >= i) && isspacechar(lineBuffer[endValue]))
+ endValue--;
+ lineBuffer[endValue + 1] = '\0';
+ if (lineBuffer[i] == '|' || lineBuffer[i] == '>') {
+ i++;
+ if (lineBuffer[i] == '+' || lineBuffer[i] == '-')
+ i++;
+ while ((i < lengthLine) && isspacechar(lineBuffer[i]))
+ i++;
+ if (lineBuffer[i] == '\0') {
+ styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
+ styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+ return;
+ } else if (lineBuffer[i] == '#') {
+ styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
+ styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
+ styler.ColourTo(endPos, SCE_YAML_COMMENT);
+ return;
+ } else {
+ styler.ColourTo(endPos, SCE_YAML_ERROR);
+ return;
+ }
+ } else if (lineBuffer[i] == '#') {
+ styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
+ styler.ColourTo(endPos, SCE_YAML_COMMENT);
+ return;
+ }
+ styler.SetLineState(currentLine, YAML_STATE_VALUE);
+ if (lineBuffer[i] == '&' || lineBuffer[i] == '*') {
+ styler.ColourTo(endPos, SCE_YAML_REFERENCE);
+ return;
+ }
+ if (keywords.InList(&lineBuffer[i])) { // Convertible value (true/false, etc.)
+ styler.ColourTo(endPos, SCE_YAML_KEYWORD);
+ return;
+ } else {
+ unsigned int i2 = i;
+ while ((i < lengthLine) && lineBuffer[i]) {
+ if (!(isascii(lineBuffer[i]) && isdigit(lineBuffer[i])) && lineBuffer[i] != '-' && lineBuffer[i] != '.' && lineBuffer[i] != ',') {
+ styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+ return;
+ }
+ i++;
+ }
+ if (i > i2) {
+ styler.ColourTo(endPos, SCE_YAML_NUMBER);
+ return;
+ }
+ }
+ break; // shouldn't get here, but just in case, the rest of the line is coloured the default
+ }
+ i++;
+ }
+ styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+}
+
+static void ColouriseYAMLDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
+ char lineBuffer[1024];
+ styler.StartAt(startPos);
+ styler.StartSegment(startPos);
+ unsigned int linePos = 0;
+ unsigned int startLine = startPos;
+ unsigned int endPos = startPos + length;
+ unsigned int maxPos = styler.Length();
+ unsigned int lineCurrent = styler.GetLine(startPos);
+
+ for (unsigned int i = startPos; i < maxPos && i < endPos; i++) {
+ lineBuffer[linePos++] = styler[i];
+ if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+ // End of line (or of line buffer) met, colourise it
+ lineBuffer[linePos] = '\0';
+ ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, i, *keywordLists[0], styler);
+ linePos = 0;
+ startLine = i + 1;
+ lineCurrent++;
+ }
+ }
+ if (linePos > 0) { // Last line does not have ending characters
+ ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, startPos + length - 1, *keywordLists[0], styler);
+ }
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+ int pos = styler.LineStart(line);
+ if (styler[pos] == '#')
+ return true;
+ return false;
+}
+
+static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unused*/,
+ WordList *[], Accessor &styler) {
+ const int maxPos = startPos + length;
+ const int maxLines = styler.GetLine(maxPos - 1); // Requested last line
+ const int docLines = styler.GetLine(styler.Length() - 1); // Available last line
+ const bool foldComment = styler.GetPropertyInt("fold.comment.yaml") != 0;
+
+ // Backtrack to previous non-blank line so we can determine indent level
+ // for any white space lines
+ // and so we can fix any preceding fold level (which is why we go back
+ // at least one line in all cases)
+ int spaceFlags = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ while (lineCurrent > 0) {
+ lineCurrent--;
+ indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+ if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
+ (!IsCommentLine(lineCurrent, styler)))
+ break;
+ }
+ int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+ // Set up initial loop state
+ int prevComment = 0;
+ if (lineCurrent >= 1)
+ prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
+
+ // Process all characters to end of requested range
+ // or comment that hangs over the end of the range. Cap processing in all cases
+ // to end of document (in case of unclosed comment at end).
+ while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) {
+
+ // Gather info
+ int lev = indentCurrent;
+ int lineNext = lineCurrent + 1;
+ int indentNext = indentCurrent;
+ if (lineNext <= docLines) {
+ // Information about next line is only available if not at end of document
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ }
+ const int comment = foldComment && IsCommentLine(lineCurrent, styler);
+ const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
+ IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
+ const int comment_continue = (comment && prevComment);
+ if (!comment)
+ indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+ if (indentNext & SC_FOLDLEVELWHITEFLAG)
+ indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+ if (comment_start) {
+ // Place fold point at start of a block of comments
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ } else if (comment_continue) {
+ // Add level to rest of lines in the block
+ lev = lev + 1;
+ }
+
+ // Skip past any blank lines for next indent level info; we skip also
+ // comments (all comments, not just those starting in column 0)
+ // which effectively folds them into surrounding code rather
+ // than screwing up folding.
+
+ while ((lineNext < docLines) &&
+ ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
+ (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+
+ lineNext++;
+ indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+ }
+
+ const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
+ const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);
+
+ // Now set all the indent levels on the lines we skipped
+ // Do this from end to start. Once we encounter one line
+ // which is indented more than the line after the end of
+ // the comment-block, use the level of the block before
+
+ int skipLine = lineNext;
+ int skipLevel = levelAfterComments;
+
+ while (--skipLine > lineCurrent) {
+ int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+ if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
+ skipLevel = levelBeforeComments;
+
+ int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+ styler.SetLevel(skipLine, skipLevel | whiteFlag);
+ }
+
+ // Set fold header on non-comment line
+ if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
+ if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ }
+
+ // Keep track of block comment state of previous line
+ prevComment = comment_start || comment_continue;
+
+ // Set fold level for this line and move to next line
+ styler.SetLevel(lineCurrent, lev);
+ indentCurrent = indentNext;
+ lineCurrent = lineNext;
+ }
+
+ // NOTE: Cannot set level of last line here because indentCurrent doesn't have
+ // header flag set; the loop above is crafted to take care of this case!
+ //styler.SetLevel(lineCurrent, indentCurrent);
+}
+
+LexerModule lmYAML(SCLEX_YAML, ColouriseYAMLDoc, "yaml", FoldYAMLDoc, yamlWordListDesc);
diff --git a/scintilla/src/LineMarker.cxx b/scintilla/src/LineMarker.cxx
new file mode 100644
index 0000000..6f4b0a9
--- /dev/null
+++ b/scintilla/src/LineMarker.cxx
@@ -0,0 +1,310 @@
+// Scintilla source code edit control
+/** @file LineMarker.cxx
+ ** Defines the look of a line marker in the margin .
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "XPM.h"
+#include "LineMarker.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+void LineMarker::RefreshColourPalette(Palette &pal, bool want) {
+ pal.WantFind(fore, want);
+ pal.WantFind(back, want);
+ if (pxpm) {
+ pxpm->RefreshColourPalette(pal, want);
+ }
+}
+
+void LineMarker::SetXPM(const char *textForm) {
+ delete pxpm;
+ pxpm = new XPM(textForm);
+ markType = SC_MARK_PIXMAP;
+}
+
+void LineMarker::SetXPM(const char *const *linesForm) {
+ delete pxpm;
+ pxpm = new XPM(linesForm);
+ markType = SC_MARK_PIXMAP;
+}
+
+static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
+ PRectangle rc;
+ rc.left = centreX - armSize;
+ rc.top = centreY - armSize;
+ rc.right = centreX + armSize + 1;
+ rc.bottom = centreY + armSize + 1;
+ surface->RectangleDraw(rc, back, fore);
+}
+
+static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
+ PRectangle rcCircle;
+ rcCircle.left = centreX - armSize;
+ rcCircle.top = centreY - armSize;
+ rcCircle.right = centreX + armSize + 1;
+ rcCircle.bottom = centreY + armSize + 1;
+ surface->Ellipse(rcCircle, back, fore);
+}
+
+static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
+ PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
+ surface->FillRectangle(rcV, fore);
+ PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
+ surface->FillRectangle(rcH, fore);
+}
+
+static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
+ PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
+ surface->FillRectangle(rcH, fore);
+}
+
+void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) {
+ if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
+ pxpm->Draw(surface, rcWhole);
+ return;
+ }
+ // Restrict most shapes a bit
+ PRectangle rc = rcWhole;
+ rc.top++;
+ rc.bottom--;
+ int minDim = Platform::Minimum(rc.Width(), rc.Height());
+ minDim--; // Ensure does not go beyond edge
+ int centreX = (rc.right + rc.left) / 2;
+ int centreY = (rc.bottom + rc.top) / 2;
+ int dimOn2 = minDim / 2;
+ int dimOn4 = minDim / 4;
+ int blobSize = dimOn2-1;
+ int armSize = dimOn2-2;
+ if (rc.Width() > (rc.Height() * 2)) {
+ // Wide column is line number so move to left to try to avoid overlapping number
+ centreX = rc.left + dimOn2 + 1;
+ }
+ if (markType == SC_MARK_ROUNDRECT) {
+ PRectangle rcRounded = rc;
+ rcRounded.left = rc.left + 1;
+ rcRounded.right = rc.right - 1;
+ surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_CIRCLE) {
+ PRectangle rcCircle;
+ rcCircle.left = centreX - dimOn2;
+ rcCircle.top = centreY - dimOn2;
+ rcCircle.right = centreX + dimOn2;
+ rcCircle.bottom = centreY + dimOn2;
+ surface->Ellipse(rcCircle, fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_ARROW) {
+ Point pts[] = {
+ Point(centreX - dimOn4, centreY - dimOn2),
+ Point(centreX - dimOn4, centreY + dimOn2),
+ Point(centreX + dimOn2 - dimOn4, centreY),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_ARROWDOWN) {
+ Point pts[] = {
+ Point(centreX - dimOn2, centreY - dimOn4),
+ Point(centreX + dimOn2, centreY - dimOn4),
+ Point(centreX, centreY + dimOn2 - dimOn4),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_PLUS) {
+ Point pts[] = {
+ Point(centreX - armSize, centreY - 1),
+ Point(centreX - 1, centreY - 1),
+ Point(centreX - 1, centreY - armSize),
+ Point(centreX + 1, centreY - armSize),
+ Point(centreX + 1, centreY - 1),
+ Point(centreX + armSize, centreY -1),
+ Point(centreX + armSize, centreY +1),
+ Point(centreX + 1, centreY + 1),
+ Point(centreX + 1, centreY + armSize),
+ Point(centreX - 1, centreY + armSize),
+ Point(centreX - 1, centreY + 1),
+ Point(centreX - armSize, centreY + 1),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_MINUS) {
+ Point pts[] = {
+ Point(centreX - armSize, centreY - 1),
+ Point(centreX + armSize, centreY -1),
+ Point(centreX + armSize, centreY +1),
+ Point(centreX - armSize, centreY + 1),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_SMALLRECT) {
+ PRectangle rcSmall;
+ rcSmall.left = rc.left + 1;
+ rcSmall.top = rc.top + 2;
+ rcSmall.right = rc.right - 1;
+ rcSmall.bottom = rc.bottom - 2;
+ surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
+ markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
+ // An invisible marker so don't draw anything
+
+ } else if (markType == SC_MARK_VLINE) {
+ surface->PenColour(back.allocated);
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ } else if (markType == SC_MARK_LCORNER) {
+ surface->PenColour(back.allocated);
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, rc.top + dimOn2);
+ surface->LineTo(rc.right - 2, rc.top + dimOn2);
+
+ } else if (markType == SC_MARK_TCORNER) {
+ surface->PenColour(back.allocated);
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, rcWhole.bottom);
+ surface->MoveTo(centreX, rc.top + dimOn2);
+ surface->LineTo(rc.right - 2, rc.top + dimOn2);
+
+ } else if (markType == SC_MARK_LCORNERCURVE) {
+ surface->PenColour(back.allocated);
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, rc.top + dimOn2-3);
+ surface->LineTo(centreX+3, rc.top + dimOn2);
+ surface->LineTo(rc.right - 1, rc.top + dimOn2);
+
+ } else if (markType == SC_MARK_TCORNERCURVE) {
+ surface->PenColour(back.allocated);
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ surface->MoveTo(centreX, rc.top + dimOn2-3);
+ surface->LineTo(centreX+3, rc.top + dimOn2);
+ surface->LineTo(rc.right - 1, rc.top + dimOn2);
+
+ } else if (markType == SC_MARK_BOXPLUS) {
+ surface->PenColour(back.allocated);
+ DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
+
+ } else if (markType == SC_MARK_BOXPLUSCONNECTED) {
+ surface->PenColour(back.allocated);
+ DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, centreY - blobSize);
+
+ } else if (markType == SC_MARK_BOXMINUS) {
+ surface->PenColour(back.allocated);
+ DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ } else if (markType == SC_MARK_BOXMINUSCONNECTED) {
+ surface->PenColour(back.allocated);
+ DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, centreY - blobSize);
+
+ } else if (markType == SC_MARK_CIRCLEPLUS) {
+ DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ surface->PenColour(back.allocated);
+ DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
+
+ } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
+ DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ surface->PenColour(back.allocated);
+ DrawPlus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, centreY - blobSize);
+
+ } else if (markType == SC_MARK_CIRCLEMINUS) {
+ DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ surface->PenColour(back.allocated);
+ DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
+ DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
+ surface->PenColour(back.allocated);
+ DrawMinus(surface, centreX, centreY, blobSize, back.allocated);
+
+ surface->MoveTo(centreX, centreY + blobSize);
+ surface->LineTo(centreX, rcWhole.bottom);
+
+ surface->MoveTo(centreX, rcWhole.top);
+ surface->LineTo(centreX, centreY - blobSize);
+
+ } else if (markType >= SC_MARK_CHARACTER) {
+ char character[1];
+ character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
+ int width = surface->WidthText(fontForCharacter, character, 1);
+ rc.left += (rc.Width() - width) / 2;
+ rc.right = rc.left + width;
+ surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
+ character, 1, fore.allocated, back.allocated);
+
+ } else if (markType == SC_MARK_DOTDOTDOT) {
+ int right = centreX - 6;
+ for (int b=0; b<3; b++) {
+ PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
+ surface->FillRectangle(rcBlob, fore.allocated);
+ right += 5;
+ }
+ } else if (markType == SC_MARK_ARROWS) {
+ surface->PenColour(fore.allocated);
+ int right = centreX - 2;
+ for (int b=0; b<3; b++) {
+ surface->MoveTo(right - 4, centreY - 4);
+ surface->LineTo(right, centreY);
+ surface->LineTo(right - 5, centreY + 5);
+ right += 4;
+ }
+ } else if (markType == SC_MARK_SHORTARROW) {
+ Point pts[] = {
+ Point(centreX, centreY + dimOn2),
+ Point(centreX + dimOn2, centreY),
+ Point(centreX, centreY - dimOn2),
+ Point(centreX, centreY - dimOn4),
+ Point(centreX - dimOn4, centreY - dimOn4),
+ Point(centreX - dimOn4, centreY + dimOn4),
+ Point(centreX, centreY + dimOn4),
+ Point(centreX, centreY + dimOn2),
+ };
+ surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
+ fore.allocated, back.allocated);
+ } else if (markType == SC_MARK_LEFTRECT) {
+ PRectangle rcLeft = rcWhole;
+ rcLeft.right = rcLeft.left + 4;
+ surface->FillRectangle(rcLeft, back.allocated);
+ } else { // SC_MARK_FULLRECT
+ surface->FillRectangle(rcWhole, back.allocated);
+ }
+}
diff --git a/scintilla/src/LineMarker.h b/scintilla/src/LineMarker.h
new file mode 100644
index 0000000..fa0f29f
--- /dev/null
+++ b/scintilla/src/LineMarker.h
@@ -0,0 +1,62 @@
+// Scintilla source code edit control
+/** @file LineMarker.h
+ ** Defines the look of a line marker in the margin .
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef LINEMARKER_H
+#define LINEMARKER_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class LineMarker {
+public:
+ int markType;
+ ColourPair fore;
+ ColourPair back;
+ int alpha;
+ XPM *pxpm;
+ LineMarker() {
+ markType = SC_MARK_CIRCLE;
+ fore = ColourDesired(0,0,0);
+ back = ColourDesired(0xff,0xff,0xff);
+ alpha = SC_ALPHA_NOALPHA;
+ pxpm = NULL;
+ }
+ LineMarker(const LineMarker &) {
+ // Defined to avoid pxpm being blindly copied, not as real copy constructor
+ markType = SC_MARK_CIRCLE;
+ fore = ColourDesired(0,0,0);
+ back = ColourDesired(0xff,0xff,0xff);
+ alpha = SC_ALPHA_NOALPHA;
+ pxpm = NULL;
+ }
+ ~LineMarker() {
+ delete pxpm;
+ }
+ LineMarker &operator=(const LineMarker &) {
+ // Defined to avoid pxpm being blindly copied, not as real assignment operator
+ markType = SC_MARK_CIRCLE;
+ fore = ColourDesired(0,0,0);
+ back = ColourDesired(0xff,0xff,0xff);
+ alpha = SC_ALPHA_NOALPHA;
+ delete pxpm;
+ pxpm = NULL;
+ return *this;
+ }
+ void RefreshColourPalette(Palette &pal, bool want);
+ void SetXPM(const char *textForm);
+ void SetXPM(const char *const *linesForm);
+ void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/Partitioning.h b/scintilla/src/Partitioning.h
new file mode 100644
index 0000000..d5b392a
--- /dev/null
+++ b/scintilla/src/Partitioning.h
@@ -0,0 +1,184 @@
+// Scintilla source code edit control
+/** @file Partitioning.h
+ ** Data structure used to partition an interval. Used for holding line start/end positions.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PARTITIONING_H
+#define PARTITIONING_H
+
+/// A split vector of integers with a method for adding a value to all elements
+/// in a range.
+/// Used by the Partitioning class.
+
+class SplitVectorWithRangeAdd : public SplitVector<int> {
+public:
+ SplitVectorWithRangeAdd(int growSize_) {
+ SetGrowSize(growSize_);
+ ReAllocate(growSize_);
+ }
+ ~SplitVectorWithRangeAdd() {
+ }
+ void RangeAddDelta(int start, int end, int delta) {
+ // end is 1 past end, so end-start is number of elements to change
+ int i = 0;
+ int rangeLength = end - start;
+ int range1Length = rangeLength;
+ int part1Left = part1Length - start;
+ if (range1Length > part1Left)
+ range1Length = part1Left;
+ while (i < range1Length) {
+ body[start++] += delta;
+ i++;
+ }
+ start += gapLength;
+ while (i < rangeLength) {
+ body[start++] += delta;
+ i++;
+ }
+ }
+};
+
+/// Divide an interval into multiple partitions.
+/// Useful for breaking a document down into sections such as lines.
+
+class Partitioning {
+private:
+ // To avoid calculating all the partition positions whenever any text is inserted
+ // there may be a step somewhere in the list.
+ int stepPartition;
+ int stepLength;
+ SplitVectorWithRangeAdd *body;
+
+ // Move step forward
+ void ApplyStep(int partitionUpTo) {
+ if (stepLength != 0) {
+ body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength);
+ }
+ stepPartition = partitionUpTo;
+ if (stepPartition >= body->Length()-1) {
+ stepPartition = body->Length()-1;
+ stepLength = 0;
+ }
+ }
+
+ // Move step backward
+ void BackStep(int partitionDownTo) {
+ if (stepLength != 0) {
+ body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength);
+ }
+ stepPartition = partitionDownTo;
+ }
+
+ void Allocate(int growSize) {
+ body = new SplitVectorWithRangeAdd(growSize);
+ stepPartition = 0;
+ stepLength = 0;
+ body->Insert(0, 0); // This value stays 0 for ever
+ body->Insert(1, 0); // This is the end of the first partition and will be the start of the second
+ }
+
+public:
+ Partitioning(int growSize) {
+ Allocate(growSize);
+ }
+
+ ~Partitioning() {
+ delete body;
+ body = 0;
+ }
+
+ int Partitions() const {
+ return body->Length()-1;
+ }
+
+ void InsertPartition(int partition, int pos) {
+ if (stepPartition < partition) {
+ ApplyStep(partition);
+ }
+ body->Insert(partition, pos);
+ stepPartition++;
+ }
+
+ void SetPartitionStartPosition(int partition, int pos) {
+ ApplyStep(partition+1);
+ if ((partition < 0) || (partition > body->Length())) {
+ return;
+ }
+ body->SetValueAt(partition, pos);
+ }
+
+ void InsertText(int partitionInsert, int delta) {
+ // Point all the partitions after the insertion point further along in the buffer
+ if (stepLength != 0) {
+ if (partitionInsert >= stepPartition) {
+ // Fill in up to the new insertion point
+ ApplyStep(partitionInsert);
+ stepLength += delta;
+ } else if (partitionInsert >= (stepPartition - body->Length() / 10)) {
+ // Close to step but before so move step back
+ BackStep(partitionInsert);
+ stepLength += delta;
+ } else {
+ ApplyStep(body->Length()-1);
+ stepPartition = partitionInsert;
+ stepLength = delta;
+ }
+ } else {
+ stepPartition = partitionInsert;
+ stepLength = delta;
+ }
+ }
+
+ void RemovePartition(int partition) {
+ if (partition > stepPartition) {
+ ApplyStep(partition);
+ stepPartition--;
+ } else {
+ stepPartition--;
+ }
+ body->Delete(partition);
+ }
+
+ int PositionFromPartition(int partition) const {
+ PLATFORM_ASSERT(partition >= 0);
+ PLATFORM_ASSERT(partition < body->Length());
+ if ((partition < 0) || (partition >= body->Length())) {
+ return 0;
+ }
+ int pos = body->ValueAt(partition);
+ if (partition > stepPartition)
+ pos += stepLength;
+ return pos;
+ }
+
+ int PartitionFromPosition(int pos) const {
+ if (body->Length() <= 1)
+ return 0;
+ if (pos >= (PositionFromPartition(body->Length()-1)))
+ return body->Length() - 1 - 1;
+ int lower = 0;
+ int upper = body->Length()-1;
+ do {
+ int middle = (upper + lower + 1) / 2; // Round high
+ int posMiddle = body->ValueAt(middle);
+ if (middle > stepPartition)
+ posMiddle += stepLength;
+ if (pos < posMiddle) {
+ upper = middle - 1;
+ } else {
+ lower = middle;
+ }
+ } while (lower < upper);
+ return lower;
+ }
+
+ void DeleteAll() {
+ int growSize = body->GetGrowSize();
+ delete body;
+ Allocate(growSize);
+ }
+};
+
+#endif
diff --git a/scintilla/src/PerLine.cxx b/scintilla/src/PerLine.cxx
new file mode 100644
index 0000000..1de3245
--- /dev/null
+++ b/scintilla/src/PerLine.cxx
@@ -0,0 +1,486 @@
+// Scintilla source code edit control
+/** @file PerLine.cxx
+ ** Manages data associated with each line of the document
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "CellBuffer.h"
+#include "PerLine.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+MarkerHandleSet::MarkerHandleSet() {
+ root = 0;
+}
+
+MarkerHandleSet::~MarkerHandleSet() {
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ MarkerHandleNumber *mhnToFree = mhn;
+ mhn = mhn->next;
+ delete mhnToFree;
+ }
+ root = 0;
+}
+
+int MarkerHandleSet::Length() const {
+ int c = 0;
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ c++;
+ mhn = mhn->next;
+ }
+ return c;
+}
+
+int MarkerHandleSet::NumberFromHandle(int handle) const {
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ if (mhn->handle == handle) {
+ return mhn->number;
+ }
+ mhn = mhn->next;
+ }
+ return - 1;
+}
+
+int MarkerHandleSet::MarkValue() const {
+ unsigned int m = 0;
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ m |= (1 << mhn->number);
+ mhn = mhn->next;
+ }
+ return m;
+}
+
+bool MarkerHandleSet::Contains(int handle) const {
+ MarkerHandleNumber *mhn = root;
+ while (mhn) {
+ if (mhn->handle == handle) {
+ return true;
+ }
+ mhn = mhn->next;
+ }
+ return false;
+}
+
+bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
+ MarkerHandleNumber *mhn = new MarkerHandleNumber;
+ if (!mhn)
+ return false;
+ mhn->handle = handle;
+ mhn->number = markerNum;
+ mhn->next = root;
+ root = mhn;
+ return true;
+}
+
+void MarkerHandleSet::RemoveHandle(int handle) {
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ MarkerHandleNumber *mhn = *pmhn;
+ if (mhn->handle == handle) {
+ *pmhn = mhn->next;
+ delete mhn;
+ return;
+ }
+ pmhn = &((*pmhn)->next);
+ }
+}
+
+bool MarkerHandleSet::RemoveNumber(int markerNum) {
+ bool performedDeletion = false;
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ MarkerHandleNumber *mhn = *pmhn;
+ if (mhn->number == markerNum) {
+ *pmhn = mhn->next;
+ delete mhn;
+ performedDeletion = true;
+ } else {
+ pmhn = &((*pmhn)->next);
+ }
+ }
+ return performedDeletion;
+}
+
+void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
+ MarkerHandleNumber **pmhn = &root;
+ while (*pmhn) {
+ pmhn = &((*pmhn)->next);
+ }
+ *pmhn = other->root;
+ other->root = 0;
+}
+
+LineMarkers::~LineMarkers() {
+ Init();
+}
+
+void LineMarkers::Init() {
+ for (int line = 0; line < markers.Length(); line++) {
+ delete markers[line];
+ markers[line] = 0;
+ }
+ markers.DeleteAll();
+}
+
+void LineMarkers::InsertLine(int line) {
+ if (markers.Length()) {
+ markers.Insert(line, 0);
+ }
+}
+
+void LineMarkers::RemoveLine(int line) {
+ // Retain the markers from the deleted line by oring them into the previous line
+ if (markers.Length()) {
+ if (line > 0) {
+ MergeMarkers(line - 1);
+ }
+ markers.Delete(line);
+ }
+}
+
+int LineMarkers::LineFromHandle(int markerHandle) {
+ if (markers.Length()) {
+ for (int line = 0; line < markers.Length(); line++) {
+ if (markers[line]) {
+ if (markers[line]->Contains(markerHandle)) {
+ return line;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+void LineMarkers::MergeMarkers(int pos) {
+ if (markers[pos + 1] != NULL) {
+ if (markers[pos] == NULL)
+ markers[pos] = new MarkerHandleSet;
+ markers[pos]->CombineWith(markers[pos + 1]);
+ delete markers[pos + 1];
+ markers[pos + 1] = NULL;
+ }
+}
+
+int LineMarkers::MarkValue(int line) {
+ if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
+ return markers[line]->MarkValue();
+ else
+ return 0;
+}
+
+int LineMarkers::AddMark(int line, int markerNum, int lines) {
+ handleCurrent++;
+ if (!markers.Length()) {
+ // No existing markers so allocate one element per line
+ markers.InsertValue(0, lines, 0);
+ }
+ if (line >= markers.Length()) {
+ return -1;
+ }
+ if (!markers[line]) {
+ // Need new structure to hold marker handle
+ markers[line] = new MarkerHandleSet();
+ if (!markers[line])
+ return -1;
+ }
+ markers[line]->InsertHandle(handleCurrent, markerNum);
+
+ return handleCurrent;
+}
+
+void LineMarkers::DeleteMark(int line, int markerNum, bool all) {
+ if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
+ if (markerNum == -1) {
+ delete markers[line];
+ markers[line] = NULL;
+ } else {
+ bool performedDeletion = markers[line]->RemoveNumber(markerNum);
+ while (all && performedDeletion) {
+ performedDeletion = markers[line]->RemoveNumber(markerNum);
+ }
+ if (markers[line]->Length() == 0) {
+ delete markers[line];
+ markers[line] = NULL;
+ }
+ }
+ }
+}
+
+void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
+ int line = LineFromHandle(markerHandle);
+ if (line >= 0) {
+ markers[line]->RemoveHandle(markerHandle);
+ if (markers[line]->Length() == 0) {
+ delete markers[line];
+ markers[line] = NULL;
+ }
+ }
+}
+
+LineLevels::~LineLevels() {
+}
+
+void LineLevels::Init() {
+ levels.DeleteAll();
+}
+
+void LineLevels::InsertLine(int line) {
+ if (levels.Length()) {
+ int level = SC_FOLDLEVELBASE;
+ if ((line > 0) && (line < levels.Length())) {
+ level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
+ }
+ levels.InsertValue(line, 1, level);
+ }
+}
+
+void LineLevels::RemoveLine(int line) {
+ if (levels.Length()) {
+ // Move up following lines but merge header flag from this line
+ // to line before to avoid a temporary disappearence causing expansion.
+ int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
+ levels.Delete(line);
+ if (line == levels.Length()-1) // Last line loses the header flag
+ levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
+ else if (line > 0)
+ levels[line-1] |= firstHeader;
+ }
+}
+
+void LineLevels::ExpandLevels(int sizeNew) {
+ levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
+}
+
+void LineLevels::ClearLevels() {
+ levels.DeleteAll();
+}
+
+int LineLevels::SetLevel(int line, int level, int lines) {
+ int prev = 0;
+ if ((line >= 0) && (line < lines)) {
+ if (!levels.Length()) {
+ ExpandLevels(lines + 1);
+ }
+ prev = levels[line];
+ if (prev != level) {
+ levels[line] = level;
+ }
+ }
+ return prev;
+}
+
+int LineLevels::GetLevel(int line) {
+ if (levels.Length() && (line >= 0) && (line < levels.Length())) {
+ return levels[line];
+ } else {
+ return SC_FOLDLEVELBASE;
+ }
+}
+
+LineState::~LineState() {
+}
+
+void LineState::Init() {
+ lineStates.DeleteAll();
+}
+
+void LineState::InsertLine(int line) {
+ if (lineStates.Length()) {
+ lineStates.EnsureLength(line);
+ lineStates.Insert(line, 0);
+ }
+}
+
+void LineState::RemoveLine(int line) {
+ if (lineStates.Length() > line) {
+ lineStates.Delete(line);
+ }
+}
+
+int LineState::SetLineState(int line, int state) {
+ lineStates.EnsureLength(line + 1);
+ int stateOld = lineStates[line];
+ lineStates[line] = state;
+ return stateOld;
+}
+
+int LineState::GetLineState(int line) {
+ lineStates.EnsureLength(line + 1);
+ return lineStates[line];
+}
+
+int LineState::GetMaxLineState() {
+ return lineStates.Length();
+}
+
+static int NumberLines(const char *text) {
+ if (text) {
+ int newLines = 0;
+ while (*text) {
+ if (*text == '\n')
+ newLines++;
+ text++;
+ }
+ return newLines+1;
+ } else {
+ return 0;
+ }
+}
+
+// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
+// and then has text and optional styles.
+
+static const int IndividualStyles = 0x100;
+
+struct AnnotationHeader {
+ short style; // Style IndividualStyles implies array of styles
+ short lines;
+ int length;
+};
+
+LineAnnotation::~LineAnnotation() {
+ ClearAll();
+}
+
+void LineAnnotation::Init() {
+ ClearAll();
+}
+
+void LineAnnotation::InsertLine(int line) {
+ if (annotations.Length()) {
+ annotations.EnsureLength(line);
+ annotations.Insert(line, 0);
+ }
+}
+
+void LineAnnotation::RemoveLine(int line) {
+ if (annotations.Length() && (line < annotations.Length())) {
+ delete []annotations[line];
+ annotations.Delete(line);
+ }
+}
+
+bool LineAnnotation::AnySet() const {
+ return annotations.Length() > 0;
+}
+
+bool LineAnnotation::MultipleStyles(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
+ else
+ return 0;
+}
+
+int LineAnnotation::Style(int line) {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
+ else
+ return 0;
+}
+
+const char *LineAnnotation::Text(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return annotations[line]+sizeof(AnnotationHeader);
+ else
+ return 0;
+}
+
+const unsigned char *LineAnnotation::Styles(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
+ return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
+ else
+ return 0;
+}
+
+static char *AllocateAnnotation(int length, int style) {
+ size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
+ char *ret = new char[len];
+ memset(ret, 0, len);
+ return ret;
+}
+
+void LineAnnotation::SetText(int line, const char *text) {
+ if (text) {
+ annotations.EnsureLength(line+1);
+ int style = Style(line);
+ if (annotations[line]) {
+ delete []annotations[line];
+ }
+ annotations[line] = AllocateAnnotation(strlen(text), style);
+ AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
+ pah->style = static_cast<short>(style);
+ pah->length = strlen(text);
+ pah->lines = static_cast<short>(NumberLines(text));
+ memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
+ } else {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line]) {
+ delete []annotations[line];
+ annotations[line] = 0;
+ }
+ }
+}
+
+void LineAnnotation::ClearAll() {
+ for (int line = 0; line < annotations.Length(); line++) {
+ delete []annotations[line];
+ annotations[line] = 0;
+ }
+ annotations.DeleteAll();
+}
+
+void LineAnnotation::SetStyle(int line, int style) {
+ annotations.EnsureLength(line+1);
+ if (!annotations[line]) {
+ annotations[line] = AllocateAnnotation(0, style);
+ }
+ reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
+}
+
+void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
+ annotations.EnsureLength(line+1);
+ if (!annotations[line]) {
+ annotations[line] = AllocateAnnotation(0, IndividualStyles);
+ } else {
+ AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
+ if (pahSource->style != IndividualStyles) {
+ char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
+ AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
+ pahAlloc->length = pahSource->length;
+ pahAlloc->lines = pahSource->lines;
+ memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
+ delete []annotations[line];
+ annotations[line] = allocation;
+ }
+ }
+ AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
+ pah->style = IndividualStyles;
+ memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
+}
+
+int LineAnnotation::Length(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
+ else
+ return 0;
+}
+
+int LineAnnotation::Lines(int line) const {
+ if (annotations.Length() && (line < annotations.Length()) && annotations[line])
+ return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
+ else
+ return 0;
+}
diff --git a/scintilla/src/PerLine.h b/scintilla/src/PerLine.h
new file mode 100644
index 0000000..f189508
--- /dev/null
+++ b/scintilla/src/PerLine.h
@@ -0,0 +1,120 @@
+// Scintilla source code edit control
+/** @file PerLine.h
+ ** Manages data associated with each line of the document
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PERLINE_H
+#define PERLINE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ * This holds the marker identifier and the marker type to display.
+ * MarkerHandleNumbers are members of lists.
+ */
+struct MarkerHandleNumber {
+ int handle;
+ int number;
+ MarkerHandleNumber *next;
+};
+
+/**
+ * A marker handle set contains any number of MarkerHandleNumbers.
+ */
+class MarkerHandleSet {
+ MarkerHandleNumber *root;
+
+public:
+ MarkerHandleSet();
+ ~MarkerHandleSet();
+ int Length() const;
+ int NumberFromHandle(int handle) const;
+ int MarkValue() const; ///< Bit set of marker numbers.
+ bool Contains(int handle) const;
+ bool InsertHandle(int handle, int markerNum);
+ void RemoveHandle(int handle);
+ bool RemoveNumber(int markerNum);
+ void CombineWith(MarkerHandleSet *other);
+};
+
+class LineMarkers : public PerLine {
+ SplitVector<MarkerHandleSet *> markers;
+ /// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
+ int handleCurrent;
+public:
+ LineMarkers() : handleCurrent(0) {
+ }
+ virtual ~LineMarkers();
+ virtual void Init();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ int MarkValue(int line);
+ int AddMark(int line, int marker, int lines);
+ void MergeMarkers(int pos);
+ void DeleteMark(int line, int markerNum, bool all);
+ void DeleteMarkFromHandle(int markerHandle);
+ int LineFromHandle(int markerHandle);
+};
+
+class LineLevels : public PerLine {
+ SplitVector<int> levels;
+public:
+ virtual ~LineLevels();
+ virtual void Init();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ void ExpandLevels(int sizeNew=-1);
+ void ClearLevels();
+ int SetLevel(int line, int level, int lines);
+ int GetLevel(int line);
+};
+
+class LineState : public PerLine {
+ SplitVector<int> lineStates;
+public:
+ LineState() {
+ }
+ virtual ~LineState();
+ virtual void Init();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ int SetLineState(int line, int state);
+ int GetLineState(int line);
+ int GetMaxLineState();
+};
+
+class LineAnnotation : public PerLine {
+ SplitVector<char *> annotations;
+public:
+ LineAnnotation() {
+ }
+ virtual ~LineAnnotation();
+ virtual void Init();
+ virtual void InsertLine(int line);
+ virtual void RemoveLine(int line);
+
+ bool AnySet() const;
+ bool MultipleStyles(int line) const;
+ int Style(int line);
+ const char *Text(int line) const;
+ const unsigned char *Styles(int line) const;
+ void SetText(int line, const char *text);
+ void ClearAll();
+ void SetStyle(int line, int style);
+ void SetStyles(int line, const unsigned char *styles);
+ int Length(int line) const;
+ int Lines(int line) const;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/PositionCache.cxx b/scintilla/src/PositionCache.cxx
new file mode 100644
index 0000000..1aa6654
--- /dev/null
+++ b/scintilla/src/PositionCache.cxx
@@ -0,0 +1,659 @@
+// Scintilla source code edit control
+/** @file PositionCache.cxx
+ ** Classes for caching layout information.
+ **/
+// Copyright 1998-2007 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 <stdio.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsControlCharacter(int ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+LineLayout::LineLayout(int maxLineLength_) :
+ lineStarts(0),
+ lenLineStarts(0),
+ lineNumber(-1),
+ inCache(false),
+ maxLineLength(-1),
+ numCharsInLine(0),
+ numCharsBeforeEOL(0),
+ validity(llInvalid),
+ xHighlightGuide(0),
+ highlightColumn(0),
+ psel(NULL),
+ containsCaret(false),
+ edgeColumn(0),
+ chars(0),
+ styles(0),
+ styleBitsSet(0),
+ indicators(0),
+ positions(0),
+ hsStart(0),
+ hsEnd(0),
+ widthLine(wrapWidthInfinite),
+ lines(1),
+ wrapIndent(0) {
+ Resize(maxLineLength_);
+}
+
+LineLayout::~LineLayout() {
+ Free();
+}
+
+void LineLayout::Resize(int maxLineLength_) {
+ if (maxLineLength_ > maxLineLength) {
+ Free();
+ chars = new char[maxLineLength_ + 1];
+ styles = new unsigned char[maxLineLength_ + 1];
+ indicators = new char[maxLineLength_ + 1];
+ // Extra position allocated as sometimes the Windows
+ // GetTextExtentExPoint API writes an extra element.
+ positions = new int[maxLineLength_ + 1 + 1];
+ maxLineLength = maxLineLength_;
+ }
+}
+
+void LineLayout::Free() {
+ delete []chars;
+ chars = 0;
+ delete []styles;
+ styles = 0;
+ delete []indicators;
+ indicators = 0;
+ delete []positions;
+ positions = 0;
+ delete []lineStarts;
+ lineStarts = 0;
+}
+
+void LineLayout::Invalidate(validLevel validity_) {
+ if (validity > validity_)
+ validity = validity_;
+}
+
+int LineLayout::LineStart(int line) const {
+ if (line <= 0) {
+ return 0;
+ } else if ((line >= lines) || !lineStarts) {
+ return numCharsInLine;
+ } else {
+ return lineStarts[line];
+ }
+}
+
+int LineLayout::LineLastVisible(int line) const {
+ if (line < 0) {
+ return 0;
+ } else if ((line >= lines-1) || !lineStarts) {
+ return numCharsBeforeEOL;
+ } else {
+ return lineStarts[line+1];
+ }
+}
+
+bool LineLayout::InLine(int offset, int line) const {
+ return ((offset >= LineStart(line)) && (offset < LineStart(line + 1))) ||
+ ((offset == numCharsInLine) && (line == (lines-1)));
+}
+
+void LineLayout::SetLineStart(int line, int start) {
+ if ((line >= lenLineStarts) && (line != 0)) {
+ int newMaxLines = line + 20;
+ int *newLineStarts = new int[newMaxLines];
+ for (int i = 0; i < newMaxLines; i++) {
+ if (i < lenLineStarts)
+ newLineStarts[i] = lineStarts[i];
+ else
+ newLineStarts[i] = 0;
+ }
+ delete []lineStarts;
+ lineStarts = newLineStarts;
+ lenLineStarts = newMaxLines;
+ }
+ lineStarts[line] = start;
+}
+
+void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[],
+ char bracesMatchStyle, int xHighlight) {
+ if (rangeLine.ContainsCharacter(braces[0])) {
+ int braceOffset = braces[0] - rangeLine.start;
+ if (braceOffset < numCharsInLine) {
+ bracePreviousStyles[0] = styles[braceOffset];
+ styles[braceOffset] = bracesMatchStyle;
+ }
+ }
+ if (rangeLine.ContainsCharacter(braces[1])) {
+ int braceOffset = braces[1] - rangeLine.start;
+ if (braceOffset < numCharsInLine) {
+ bracePreviousStyles[1] = styles[braceOffset];
+ styles[braceOffset] = bracesMatchStyle;
+ }
+ }
+ if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) ||
+ (braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) {
+ xHighlightGuide = xHighlight;
+ }
+}
+
+void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) {
+ if (rangeLine.ContainsCharacter(braces[0])) {
+ int braceOffset = braces[0] - rangeLine.start;
+ if (braceOffset < numCharsInLine) {
+ styles[braceOffset] = bracePreviousStyles[0];
+ }
+ }
+ if (rangeLine.ContainsCharacter(braces[1])) {
+ int braceOffset = braces[1] - rangeLine.start;
+ if (braceOffset < numCharsInLine) {
+ styles[braceOffset] = bracePreviousStyles[1];
+ }
+ }
+ xHighlightGuide = 0;
+}
+
+int LineLayout::FindBefore(int x, int lower, int upper) const {
+ do {
+ int middle = (upper + lower + 1) / 2; // Round high
+ int posMiddle = positions[middle];
+ if (x < posMiddle) {
+ upper = middle - 1;
+ } else {
+ lower = middle;
+ }
+ } while (lower < upper);
+ return lower;
+}
+
+int LineLayout::EndLineStyle() const {
+ return styles[numCharsBeforeEOL > 0 ? numCharsBeforeEOL-1 : 0];
+}
+
+LineLayoutCache::LineLayoutCache() :
+ level(0), length(0), size(0), cache(0),
+ allInvalidated(false), styleClock(-1), useCount(0) {
+ Allocate(0);
+}
+
+LineLayoutCache::~LineLayoutCache() {
+ Deallocate();
+}
+
+void LineLayoutCache::Allocate(int length_) {
+ PLATFORM_ASSERT(cache == NULL);
+ allInvalidated = false;
+ length = length_;
+ size = length;
+ if (size > 1) {
+ size = (size / 16 + 1) * 16;
+ }
+ if (size > 0) {
+ cache = new LineLayout * [size];
+ }
+ for (int i = 0; i < size; i++)
+ cache[i] = 0;
+}
+
+void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
+ PLATFORM_ASSERT(useCount == 0);
+ int lengthForLevel = 0;
+ if (level == llcCaret) {
+ lengthForLevel = 1;
+ } else if (level == llcPage) {
+ lengthForLevel = linesOnScreen + 1;
+ } else if (level == llcDocument) {
+ lengthForLevel = linesInDoc;
+ }
+ if (lengthForLevel > size) {
+ Deallocate();
+ 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_) {
+ if (cache && !allInvalidated) {
+ for (int i = 0; i < length; i++) {
+ if (cache[i]) {
+ cache[i]->Invalidate(validity_);
+ }
+ }
+ if (validity_ == LineLayout::llInvalid) {
+ allInvalidated = true;
+ }
+ }
+}
+
+void LineLayoutCache::SetLevel(int level_) {
+ allInvalidated = false;
+ if ((level_ != -1) && (level != level_)) {
+ level = level_;
+ Deallocate();
+ }
+}
+
+LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
+ int linesOnScreen, int linesInDoc) {
+ AllocateForLevel(linesOnScreen, linesInDoc);
+ if (styleClock != styleClock_) {
+ Invalidate(LineLayout::llCheckTextAndStyle);
+ styleClock = styleClock_;
+ }
+ allInvalidated = false;
+ int pos = -1;
+ LineLayout *ret = 0;
+ if (level == llcCaret) {
+ pos = 0;
+ } else if (level == llcPage) {
+ if (lineNumber == lineCaret) {
+ pos = 0;
+ } else if (length > 1) {
+ 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) ||
+ (cache[pos]->maxLineLength < maxChars)) {
+ delete cache[pos];
+ cache[pos] = 0;
+ }
+ }
+ if (!cache[pos]) {
+ cache[pos] = new LineLayout(maxChars);
+ }
+ if (cache[pos]) {
+ cache[pos]->lineNumber = lineNumber;
+ cache[pos]->inCache = true;
+ ret = cache[pos];
+ useCount++;
+ }
+ }
+ }
+
+ if (!ret) {
+ ret = new LineLayout(maxChars);
+ ret->lineNumber = lineNumber;
+ }
+
+ return ret;
+}
+
+void LineLayoutCache::Dispose(LineLayout *ll) {
+ allInvalidated = false;
+ if (ll) {
+ if (!ll->inCache) {
+ delete ll;
+ } else {
+ useCount--;
+ }
+ }
+}
+
+void BreakFinder::Insert(int val) {
+ // Expand if needed
+ if (saeLen >= saeSize) {
+ saeSize *= 2;
+ int *selAndEdgeNew = new int[saeSize];
+ for (unsigned int j = 0; j<saeLen; j++) {
+ selAndEdgeNew[j] = selAndEdge[j];
+ }
+ delete []selAndEdge;
+ selAndEdge = selAndEdgeNew;
+ }
+
+ if (val >= nextBreak) {
+ for (unsigned int j = 0; j<saeLen; j++) {
+ if (val == selAndEdge[j]) {
+ return;
+ }
+ if (val < selAndEdge[j]) {
+ for (unsigned int k = saeLen; k>j; k--) {
+ selAndEdge[k] = selAndEdge[k-1];
+ }
+ saeLen++;
+ selAndEdge[j] = val;
+ return;
+ }
+ }
+ // Not less than any so append
+ selAndEdge[saeLen++] = val;
+ }
+}
+
+extern bool BadUTF(const char *s, int len, int &trailBytes);
+
+static int NextBadU(const char *s, int p, int len, int &trailBytes) {
+ while (p < len) {
+ p++;
+ if (BadUTF(s + p, len - p, trailBytes))
+ return p;
+ }
+ return -1;
+}
+
+BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart, bool breakForSelection) :
+ ll(ll_),
+ lineStart(lineStart_),
+ lineEnd(lineEnd_),
+ posLineStart(posLineStart_),
+ utf8(utf8_),
+ nextBreak(lineStart_),
+ saeSize(0),
+ saeLen(0),
+ saeCurrentPos(0),
+ saeNext(0),
+ subBreak(-1) {
+ saeSize = 8;
+ selAndEdge = new int[saeSize];
+ for (unsigned int j=0; j < saeSize; j++) {
+ selAndEdge[j] = 0;
+ }
+
+ // Search for first visible break
+ // First find the first visible character
+ nextBreak = ll->FindBefore(xStart, lineStart, lineEnd);
+ // Now back to a style break
+ while ((nextBreak > lineStart) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) {
+ nextBreak--;
+ }
+
+ if (breakForSelection) {
+ SelectionPosition posStart(posLineStart);
+ SelectionPosition posEnd(posLineStart + lineEnd);
+ SelectionSegment segmentLine(posStart, posEnd);
+ for (size_t r=0; r<ll->psel->Count(); r++) {
+ SelectionSegment portion = ll->psel->Range(r).Intersect(segmentLine);
+ if (!(portion.start == portion.end)) {
+ if (portion.start.IsValid())
+ Insert(portion.start.Position() - posLineStart - 1);
+ if (portion.end.IsValid())
+ Insert(portion.end.Position() - posLineStart - 1);
+ }
+ }
+ }
+
+ Insert(ll->edgeColumn - 1);
+ Insert(lineEnd - 1);
+
+ if (utf8) {
+ int trailBytes=0;
+ for (int pos = -1;;) {
+ pos = NextBadU(ll->chars, pos, lineEnd, trailBytes);
+ if (pos < 0)
+ break;
+ Insert(pos-1);
+ Insert(pos);
+ }
+ }
+ saeNext = (saeLen > 0) ? selAndEdge[0] : -1;
+}
+
+BreakFinder::~BreakFinder() {
+ delete []selAndEdge;
+}
+
+int BreakFinder::First() const {
+ return nextBreak;
+}
+
+static bool IsTrailByte(int ch) {
+ return (ch >= 0x80) && (ch < (0x80 + 0x40));
+}
+
+int BreakFinder::Next() {
+ if (subBreak == -1) {
+ int prev = nextBreak;
+ while (nextBreak < lineEnd) {
+ if ((ll->styles[nextBreak] != ll->styles[nextBreak + 1]) ||
+ (nextBreak == saeNext) ||
+ IsControlCharacter(ll->chars[nextBreak]) || IsControlCharacter(ll->chars[nextBreak + 1])) {
+ if (nextBreak == saeNext) {
+ saeCurrentPos++;
+ saeNext = (saeLen > saeCurrentPos) ? selAndEdge[saeCurrentPos] : -1;
+ }
+ nextBreak++;
+ if ((nextBreak - prev) < lengthStartSubdivision) {
+ return nextBreak;
+ }
+ break;
+ }
+ nextBreak++;
+ }
+ if ((nextBreak - prev) < lengthStartSubdivision) {
+ return nextBreak;
+ }
+ subBreak = prev;
+ }
+ // Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision.
+ // For very long runs add extra breaks after spaces or if no spaces before low punctuation.
+ if ((nextBreak - subBreak) <= lengthEachSubdivision) {
+ subBreak = -1;
+ return nextBreak;
+ } else {
+ int lastGoodBreak = -1;
+ int lastOKBreak = -1;
+ int lastUTF8Break = -1;
+ int j;
+ for (j = subBreak + 1; j <= nextBreak; j++) {
+ if (IsSpaceOrTab(ll->chars[j - 1]) && !IsSpaceOrTab(ll->chars[j])) {
+ lastGoodBreak = j;
+ }
+ if (static_cast<unsigned char>(ll->chars[j]) < 'A') {
+ lastOKBreak = j;
+ }
+ if (utf8 && !IsTrailByte(static_cast<unsigned char>(ll->chars[j]))) {
+ lastUTF8Break = j;
+ }
+ if (((j - subBreak) >= lengthEachSubdivision) &&
+ ((lastGoodBreak >= 0) || (lastOKBreak >= 0) || (lastUTF8Break >= 0))) {
+ break;
+ }
+ }
+ if (lastGoodBreak >= 0) {
+ subBreak = lastGoodBreak;
+ } else if (lastOKBreak >= 0) {
+ subBreak = lastOKBreak;
+ } else if (lastUTF8Break >= 0) {
+ subBreak = lastUTF8Break;
+ } else {
+ subBreak = nextBreak;
+ }
+ if (subBreak >= nextBreak) {
+ subBreak = -1;
+ return nextBreak;
+ } else {
+ return subBreak;
+ }
+ }
+}
+
+PositionCacheEntry::PositionCacheEntry() :
+ styleNumber(0), len(0), clock(0), positions(0) {
+}
+
+void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
+ unsigned int len_, int *positions_, unsigned int clock_) {
+ Clear();
+ styleNumber = styleNumber_;
+ len = len_;
+ clock = clock_;
+ if (s_ && positions_) {
+ positions = new short[len + (len + 1) / 2];
+ for (unsigned int i=0; i<len; i++) {
+ positions[i] = static_cast<short>(positions_[i]);
+ }
+ memcpy(reinterpret_cast<char *>(positions + len), s_, len);
+ }
+}
+
+PositionCacheEntry::~PositionCacheEntry() {
+ Clear();
+}
+
+void PositionCacheEntry::Clear() {
+ delete []positions;
+ positions = 0;
+ styleNumber = 0;
+ len = 0;
+ clock = 0;
+}
+
+bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_,
+ unsigned int len_, int *positions_) const {
+ if ((styleNumber == styleNumber_) && (len == len_) &&
+ (memcmp(reinterpret_cast<char *>(positions + len), s_, len)== 0)) {
+ for (unsigned int i=0; i<len; i++) {
+ positions_[i] = positions[i];
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int PositionCacheEntry::Hash(unsigned int styleNumber, const char *s, unsigned int len) {
+ unsigned int ret = s[0] << 7;
+ for (unsigned int i=0; i<len; i++) {
+ ret *= 1000003;
+ ret ^= s[i];
+ }
+ ret *= 1000003;
+ ret ^= len;
+ ret *= 1000003;
+ ret ^= styleNumber;
+ return ret;
+}
+
+bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) const {
+ return clock > other.clock;
+}
+
+void PositionCacheEntry::ResetClock() {
+ if (clock > 0) {
+ clock = 1;
+ }
+}
+
+PositionCache::PositionCache() {
+ size = 0x400;
+ clock = 1;
+ pces = new PositionCacheEntry[size];
+ allClear = true;
+}
+
+PositionCache::~PositionCache() {
+ Clear();
+ delete []pces;
+}
+
+void PositionCache::Clear() {
+ if (!allClear) {
+ for (size_t i=0; i<size; i++) {
+ pces[i].Clear();
+ }
+ }
+ clock = 1;
+ allClear = true;
+}
+
+void PositionCache::SetSize(size_t size_) {
+ Clear();
+ delete []pces;
+ size = size_;
+ pces = new PositionCacheEntry[size];
+}
+
+void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
+ const char *s, unsigned int len, int *positions) {
+ allClear = false;
+ int probe = -1;
+ if ((size > 0) && (len < 30)) {
+ // Only store short strings in the cache so it doesn't churn with
+ // long comments with only a single comment.
+
+ // Two way associative: try two probe positions.
+ int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
+ probe = hashValue % size;
+ if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
+ return;
+ }
+ int probe2 = (hashValue * 37) % size;
+ if (pces[probe2].Retrieve(styleNumber, s, len, positions)) {
+ return;
+ }
+ // Not found. Choose the oldest of the two slots to replace
+ if (pces[probe].NewerThan(pces[probe2])) {
+ probe = probe2;
+ }
+ }
+ surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions);
+ if (probe >= 0) {
+ clock++;
+ if (clock > 60000) {
+ // Since there are only 16 bits for the clock, wrap it round and
+ // reset all cache entries so none get stuck with a high clock.
+ for (size_t i=0; i<size; i++) {
+ pces[i].ResetClock();
+ }
+ clock = 2;
+ }
+ pces[probe].Set(styleNumber, s, len, positions, clock);
+ }
+}
diff --git a/scintilla/src/PositionCache.h b/scintilla/src/PositionCache.h
new file mode 100644
index 0000000..12273f5
--- /dev/null
+++ b/scintilla/src/PositionCache.h
@@ -0,0 +1,168 @@
+// Scintilla source code edit control
+/** @file PositionCache.h
+ ** Classes for caching layout information.
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef POSITIONCACHE_H
+#define POSITIONCACHE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+static inline bool IsEOLChar(char ch) {
+ return (ch == '\r') || (ch == '\n');
+}
+
+/**
+ */
+class LineLayout {
+private:
+ friend class LineLayoutCache;
+ int *lineStarts;
+ int lenLineStarts;
+ /// Drawing is only performed for @a maxLineLength characters on each line.
+ int lineNumber;
+ bool inCache;
+public:
+ enum { wrapWidthInfinite = 0x7ffffff };
+ int maxLineLength;
+ int numCharsInLine;
+ int numCharsBeforeEOL;
+ enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
+ int xHighlightGuide;
+ bool highlightColumn;
+ Selection *psel;
+ bool containsCaret;
+ int edgeColumn;
+ char *chars;
+ unsigned char *styles;
+ int styleBitsSet;
+ char *indicators;
+ int *positions;
+ char bracePreviousStyles[2];
+
+ // Hotspot support
+ int hsStart;
+ int hsEnd;
+
+ // Wrapped line support
+ int widthLine;
+ int lines;
+ int wrapIndent; // In pixels
+
+ LineLayout(int maxLineLength_);
+ virtual ~LineLayout();
+ void Resize(int maxLineLength_);
+ void Free();
+ void Invalidate(validLevel validity_);
+ int LineStart(int line) const;
+ int LineLastVisible(int line) const;
+ bool InLine(int offset, int line) const;
+ void SetLineStart(int line, int start);
+ void SetBracesHighlight(Range rangeLine, Position braces[],
+ char bracesMatchStyle, int xHighlight);
+ void RestoreBracesHighlight(Range rangeLine, Position braces[]);
+ int FindBefore(int x, int lower, int upper) const;
+ int EndLineStyle() const;
+};
+
+/**
+ */
+class LineLayoutCache {
+ int level;
+ int length;
+ int size;
+ LineLayout **cache;
+ bool allInvalidated;
+ int styleClock;
+ int useCount;
+ void Allocate(int length_);
+ void AllocateForLevel(int linesOnScreen, int linesInDoc);
+public:
+ LineLayoutCache();
+ virtual ~LineLayoutCache();
+ void Deallocate();
+ enum {
+ llcNone=SC_CACHE_NONE,
+ llcCaret=SC_CACHE_CARET,
+ llcPage=SC_CACHE_PAGE,
+ llcDocument=SC_CACHE_DOCUMENT
+ };
+ void Invalidate(LineLayout::validLevel validity_);
+ void SetLevel(int level_);
+ int GetLevel() const { return level; }
+ LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
+ int linesOnScreen, int linesInDoc);
+ void Dispose(LineLayout *ll);
+};
+
+class PositionCacheEntry {
+ unsigned int styleNumber:8;
+ unsigned int len:8;
+ unsigned int clock:16;
+ short *positions;
+public:
+ PositionCacheEntry();
+ ~PositionCacheEntry();
+ void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_, unsigned int clock);
+ void Clear();
+ bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_) const;
+ static int Hash(unsigned int styleNumber, const char *s, unsigned int len);
+ bool NewerThan(const PositionCacheEntry &other) const;
+ void ResetClock();
+};
+
+// Class to break a line of text into shorter runs at sensible places.
+class BreakFinder {
+ // If a whole run is longer than lengthStartSubdivision then subdivide
+ // into smaller runs at spaces or punctuation.
+ enum { lengthStartSubdivision = 300 };
+ // Try to make each subdivided run lengthEachSubdivision or shorter.
+ enum { lengthEachSubdivision = 100 };
+ LineLayout *ll;
+ int lineStart;
+ int lineEnd;
+ int posLineStart;
+ bool utf8;
+ int nextBreak;
+ int *selAndEdge;
+ unsigned int saeSize;
+ unsigned int saeLen;
+ unsigned int saeCurrentPos;
+ int saeNext;
+ int subBreak;
+ void Insert(int val);
+public:
+ BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart, bool breakForSelection);
+ ~BreakFinder();
+ int First() const;
+ int Next();
+};
+
+class PositionCache {
+ PositionCacheEntry *pces;
+ size_t size;
+ unsigned int clock;
+ bool allClear;
+public:
+ PositionCache();
+ ~PositionCache();
+ void Clear();
+ void SetSize(size_t size_);
+ int GetSize() const { return size; }
+ void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
+ const char *s, unsigned int len, int *positions);
+};
+
+inline bool IsSpaceOrTab(int ch) {
+ return ch == ' ' || ch == '\t';
+}
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/PropSet.cxx b/scintilla/src/PropSet.cxx
new file mode 100644
index 0000000..709cbd4
--- /dev/null
+++ b/scintilla/src/PropSet.cxx
@@ -0,0 +1,176 @@
+// SciTE - Scintilla based Text Editor
+/** @file PropSet.cxx
+ ** A Java style properties file module.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// Maintain a dictionary of properties
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef _MSC_VER
+// Visual C++ doesn't like unreachable code or long decorated names in its own headers.
+#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702 4786)
+#endif
+
+#include <string>
+#include <map>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "PropSetSimple.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+typedef std::map<std::string, std::string> mapss;
+
+PropSetSimple::PropSetSimple() {
+ mapss *props = new mapss;
+ impl = static_cast<void *>(props);
+}
+
+PropSetSimple::~PropSetSimple() {
+ mapss *props = static_cast<mapss *>(impl);
+ delete props;
+ impl = 0;
+}
+
+void PropSetSimple::Set(const char *key, const char *val, int lenKey, int lenVal) {
+ mapss *props = static_cast<mapss *>(impl);
+ if (!*key) // Empty keys are not supported
+ return;
+ if (lenKey == -1)
+ lenKey = static_cast<int>(strlen(key));
+ if (lenVal == -1)
+ lenVal = static_cast<int>(strlen(val));
+ (*props)[std::string(key, lenKey)] = std::string(val, lenVal);
+}
+
+static bool IsASpaceCharacter(unsigned int ch) {
+ return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+void PropSetSimple::Set(const char *keyVal) {
+ while (IsASpaceCharacter(*keyVal))
+ keyVal++;
+ const char *endVal = keyVal;
+ while (*endVal && (*endVal != '\n'))
+ endVal++;
+ const char *eqAt = strchr(keyVal, '=');
+ if (eqAt) {
+ Set(keyVal, eqAt + 1, eqAt-keyVal, endVal - eqAt - 1);
+ } else if (*keyVal) { // No '=' so assume '=1'
+ Set(keyVal, "1", endVal-keyVal, 1);
+ }
+}
+
+void PropSetSimple::SetMultiple(const char *s) {
+ const char *eol = strchr(s, '\n');
+ while (eol) {
+ Set(s);
+ s = eol + 1;
+ eol = strchr(s, '\n');
+ }
+ Set(s);
+}
+
+const char *PropSetSimple::Get(const char *key) const {
+ mapss *props = static_cast<mapss *>(impl);
+ mapss::const_iterator keyPos = props->find(std::string(key));
+ if (keyPos != props->end()) {
+ return keyPos->second.c_str();
+ } else {
+ return "";
+ }
+}
+
+// There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
+// A solution is to keep a stack of variables that have been expanded, so that
+// recursive expansions can be skipped. For now I'll just use the C++ stack
+// for that, through a recursive function and a simple chain of pointers.
+
+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)))
+ || (link && link->contains(testVar));
+ }
+
+ const char *var;
+ const VarChain *link;
+};
+
+static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, int maxExpands, const VarChain &blankVars) {
+ size_t varStart = withVars.find("$(");
+ while ((varStart != std::string::npos) && (maxExpands > 0)) {
+ size_t varEnd = withVars.find(")", varStart+2);
+ if (varEnd == std::string::npos) {
+ break;
+ }
+
+ // For consistency, when we see '$(ab$(cde))', expand the inner variable first,
+ // regardless whether there is actually a degenerate variable named 'ab$(cde'.
+ size_t innerVarStart = withVars.find("$(", varStart+2);
+ while ((innerVarStart != std::string::npos) && (innerVarStart > varStart) && (innerVarStart < varEnd)) {
+ varStart = innerVarStart;
+ innerVarStart = withVars.find("$(", varStart+2);
+ }
+
+ std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
+ std::string val = props.Get(var.c_str());
+
+ if (blankVars.contains(var.c_str())) {
+ val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
+ }
+
+ if (--maxExpands >= 0) {
+ maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
+ }
+
+ withVars.erase(varStart, varEnd-varStart+1);
+ withVars.insert(varStart, val.c_str(), val.length());
+
+ varStart = withVars.find("$(");
+ }
+
+ return maxExpands;
+}
+
+char *PropSetSimple::Expanded(const char *key) const {
+ std::string val = Get(key);
+ ExpandAllInPlace(*this, val, 100, VarChain(key));
+ char *ret = new char [val.size() + 1];
+ strcpy(ret, val.c_str());
+ return ret;
+}
+
+char *PropSetSimple::ToString() const {
+ mapss *props = static_cast<mapss *>(impl);
+ std::string sval;
+ for (mapss::const_iterator it=props->begin(); it != props->end(); it++) {
+ sval += it->first;
+ sval += "=";
+ sval += it->second;
+ sval += "\n";
+ }
+ char *ret = new char [sval.size() + 1];
+ strcpy(ret, sval.c_str());
+ return ret;
+}
+
+int PropSetSimple::GetInt(const char *key, int defaultValue) const {
+ char *val = Expanded(key);
+ if (val) {
+ int retVal = val[0] ? atoi(val) : defaultValue;
+ delete []val;
+ return retVal;
+ }
+ return defaultValue;
+}
diff --git a/scintilla/src/PropSetSimple.h b/scintilla/src/PropSetSimple.h
new file mode 100644
index 0000000..057e7e6
--- /dev/null
+++ b/scintilla/src/PropSetSimple.h
@@ -0,0 +1,33 @@
+// Scintilla source code edit control
+/** @file PropSetSimple.h
+ ** A basic string to string map.
+ **/
+// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PROPSETSIMPLE_H
+#define PROPSETSIMPLE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class PropSetSimple : public PropertyGet {
+ void *impl;
+ void Set(const char *keyVal);
+public:
+ PropSetSimple();
+ virtual ~PropSetSimple();
+ void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1);
+ void SetMultiple(const char *);
+ const char *Get(const char *key) const;
+ char *Expanded(const char *key) const;
+ char *ToString() const;
+ int GetInt(const char *key, int defaultValue=0) const;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/RESearch.cxx b/scintilla/src/RESearch.cxx
new file mode 100644
index 0000000..e00cdfe
--- /dev/null
+++ b/scintilla/src/RESearch.cxx
@@ -0,0 +1,987 @@
+// Scintilla source code edit control
+/** @file RESearch.cxx
+ ** Regular expression search library.
+ **/
+
+/*
+ * regex - Regular expression pattern matching and replacement
+ *
+ * By: Ozan S. Yigit (oz)
+ * Dept. of Computer Science
+ * York University
+ *
+ * Original code available from http://www.cs.yorku.ca/~oz/
+ * Translation to C++ by Neil Hodgson neilh@scintilla.org
+ * Removed all use of register.
+ * Converted to modern function prototypes.
+ * Put all global/static variables into an object so this code can be
+ * used from multiple threads, etc.
+ * Some extensions by Philippe Lhoste PhiLho(a)GMX.net
+ *
+ * These routines are the PUBLIC DOMAIN equivalents of regex
+ * routines as found in 4.nBSD UN*X, with minor extensions.
+ *
+ * These routines are derived from various implementations found
+ * in software tools books, and Conroy's grep. They are NOT derived
+ * from licensed/restricted software.
+ * For more interesting/academic/complicated implementations,
+ * see Henry Spencer's regexp routines, or GNU Emacs pattern
+ * matching module.
+ *
+ * Modification history removed.
+ *
+ * Interfaces:
+ * RESearch::Compile: compile a regular expression into a NFA.
+ *
+ * const char *RESearch::Compile(const char *pattern, int length,
+ * bool caseSensitive, bool posix)
+ *
+ * Returns a short error string if they fail.
+ *
+ * RESearch::Execute: execute the NFA to match a pattern.
+ *
+ * int RESearch::Execute(characterIndexer &ci, int lp, int endp)
+ *
+ * RESearch::Substitute: substitute the matched portions in a new string.
+ *
+ * int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst)
+ *
+ * re_fail: failure routine for RESearch::Execute. (no longer used)
+ *
+ * void re_fail(char *msg, char op)
+ *
+ * Regular Expressions:
+ *
+ * [1] char matches itself, unless it is a special
+ * character (metachar): . \ [ ] * + ^ $
+ * and ( ) if posix option.
+ *
+ * [2] . matches any character.
+ *
+ * [3] \ matches the character following it, except:
+ * - \a, \b, \f, \n, \r, \t, \v match the corresponding C
+ * escape char, respectively BEL, BS, FF, LF, CR, TAB and VT;
+ * Note that \r and \n are never matched because Scintilla
+ * regex searches are made line per line
+ * (stripped of end-of-line chars).
+ * - if not in posix mode, when followed by a
+ * left or right round bracket (see [7]);
+ * - when followed by a digit 1 to 9 (see [8]);
+ * - when followed by a left or right angle bracket
+ * (see [9]);
+ * - when followed by d, D, s, S, w or W (see [10]);
+ * - when followed by x and two hexa digits (see [11].
+ * Backslash is used as an escape character for all
+ * other meta-characters, and itself.
+ *
+ * [4] [set] matches one of the characters in the set.
+ * If the first character in the set is "^",
+ * it matches the characters NOT in the set, i.e.
+ * complements the set. A shorthand S-E (start dash end)
+ * is used to specify a set of characters S up to
+ * E, inclusive. S and E must be characters, otherwise
+ * the dash is taken literally (eg. in expression [\d-a]).
+ * The special characters "]" and "-" have no special
+ * meaning if they appear as the first chars in the set.
+ * To include both, put - first: [-]A-Z]
+ * (or just backslash them).
+ * examples: match:
+ *
+ * [-]|] matches these 3 chars,
+ *
+ * []-|] matches from ] to | chars
+ *
+ * [a-z] any lowercase alpha
+ *
+ * [^-]] any char except - and ]
+ *
+ * [^A-Z] any char except uppercase
+ * alpha
+ *
+ * [a-zA-Z] any alpha
+ *
+ * [5] * any regular expression form [1] to [4]
+ * (except [7], [8] and [9] forms of [3]),
+ * followed by closure char (*)
+ * matches zero or more matches of that form.
+ *
+ * [6] + same as [5], except it matches one or more.
+ * Both [5] and [6] are greedy (they match as much as possible).
+ *
+ * [7] a regular expression in the form [1] to [12], enclosed
+ * as \(form\) (or (form) with posix flag) matches what
+ * form matches. The enclosure creates a set of tags,
+ * used for [8] and for pattern substitution.
+ * The tagged forms are numbered starting from 1.
+ *
+ * [8] a \ followed by a digit 1 to 9 matches whatever a
+ * previously tagged regular expression ([7]) matched.
+ *
+ * [9] \< a regular expression starting with a \< construct
+ * \> and/or ending with a \> construct, restricts the
+ * pattern matching to the beginning of a word, and/or
+ * the end of a word. A word is defined to be a character
+ * string beginning and/or ending with the characters
+ * A-Z a-z 0-9 and _. Scintilla extends this definition
+ * by user setting. The word must also be preceded and/or
+ * followed by any character outside those mentioned.
+ *
+ * [10] \l a backslash followed by d, D, s, S, w or W,
+ * becomes a character class (both inside and
+ * outside sets []).
+ * d: decimal digits
+ * D: any char except decimal digits
+ * s: whitespace (space, \t \n \r \f \v)
+ * S: any char except whitespace (see above)
+ * w: alphanumeric & underscore (changed by user setting)
+ * W: any char except alphanumeric & underscore (see above)
+ *
+ * [11] \xHH a backslash followed by x and two hexa digits,
+ * becomes the character whose Ascii code is equal
+ * to these digits. If not followed by two digits,
+ * it is 'x' char itself.
+ *
+ * [12] a composite regular expression xy where x and y
+ * are in the form [1] to [11] matches the longest
+ * match of x followed by a match for y.
+ *
+ * [13] ^ a regular expression starting with a ^ character
+ * $ and/or ending with a $ character, restricts the
+ * pattern matching to the beginning of the line,
+ * or the end of line. [anchors] Elsewhere in the
+ * pattern, ^ and $ are treated as ordinary characters.
+ *
+ *
+ * Acknowledgements:
+ *
+ * HCR's Hugh Redelmeier has been most helpful in various
+ * stages of development. He convinced me to include BOW
+ * and EOW constructs, originally invented by Rob Pike at
+ * the University of Toronto.
+ *
+ * References:
+ * Software tools Kernighan & Plauger
+ * Software tools in Pascal Kernighan & Plauger
+ * Grep [rsx-11 C dist] David Conroy
+ * ed - text editor Un*x Programmer's Manual
+ * Advanced editing on Un*x B. W. Kernighan
+ * RegExp routines Henry Spencer
+ *
+ * Notes:
+ *
+ * This implementation uses a bit-set representation for character
+ * classes for speed and compactness. Each character is represented
+ * by one bit in a 256-bit block. Thus, CCL always takes a
+ * constant 32 bytes in the internal nfa, and RESearch::Execute does a single
+ * bit comparison to locate the character in the set.
+ *
+ * Examples:
+ *
+ * pattern: foo*.*
+ * compile: CHR f CHR o CLO CHR o END CLO ANY END END
+ * matches: fo foo fooo foobar fobar foxx ...
+ *
+ * pattern: fo[ob]a[rz]
+ * compile: CHR f CHR o CCL bitset CHR a CCL bitset END
+ * matches: fobar fooar fobaz fooaz
+ *
+ * pattern: foo\\+
+ * compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
+ * matches: foo\ foo\\ foo\\\ ...
+ *
+ * pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
+ * compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
+ * matches: foo1foo foo2foo foo3foo
+ *
+ * pattern: \(fo.*\)-\1
+ * compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
+ * matches: foo-foo fo-fo fob-fob foobar-foobar ...
+ */
+
+#include <stdlib.h>
+
+#include "CharClassify.h"
+#include "RESearch.h"
+
+// Shut up annoying Visual C++ warnings:
+#ifdef _MSC_VER
+#pragma warning(disable: 4514)
+#endif
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+#define OKP 1
+#define NOP 0
+
+#define CHR 1
+#define ANY 2
+#define CCL 3
+#define BOL 4
+#define EOL 5
+#define BOT 6
+#define EOT 7
+#define BOW 8
+#define EOW 9
+#define REF 10
+#define CLO 11
+
+#define END 0
+
+/*
+ * The following defines are not meant to be changeable.
+ * They are for readability only.
+ */
+#define BLKIND 0370
+#define BITIND 07
+
+const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, '\200' };
+
+#define badpat(x) (*nfa = END, x)
+
+/*
+ * Character classification table for word boundary operators BOW
+ * and EOW is passed in by the creator of this object (Scintilla
+ * Document). The Document default state is that word chars are:
+ * 0-9, a-z, A-Z and _
+ */
+
+RESearch::RESearch(CharClassify *charClassTable) {
+ failure = 0;
+ charClass = charClassTable;
+ Init();
+}
+
+RESearch::~RESearch() {
+ Clear();
+}
+
+void RESearch::Init() {
+ sta = NOP; /* status of lastpat */
+ bol = 0;
+ for (int i = 0; i < MAXTAG; i++)
+ pat[i] = 0;
+ for (int j = 0; j < BITBLK; j++)
+ bittab[j] = 0;
+}
+
+void RESearch::Clear() {
+ for (int i = 0; i < MAXTAG; i++) {
+ delete []pat[i];
+ pat[i] = 0;
+ bopat[i] = NOTFOUND;
+ eopat[i] = NOTFOUND;
+ }
+}
+
+bool RESearch::GrabMatches(CharacterIndexer &ci) {
+ bool success = true;
+ for (unsigned int i = 0; i < MAXTAG; i++) {
+ if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
+ unsigned int len = eopat[i] - bopat[i];
+ pat[i] = new char[len + 1];
+ if (pat[i]) {
+ for (unsigned int j = 0; j < len; j++)
+ pat[i][j] = ci.CharAt(bopat[i] + j);
+ pat[i][len] = '\0';
+ } else {
+ success = false;
+ }
+ }
+ }
+ return success;
+}
+
+void RESearch::ChSet(unsigned char c) {
+ bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
+}
+
+void RESearch::ChSetWithCase(unsigned char c, bool caseSensitive) {
+ if (caseSensitive) {
+ ChSet(c);
+ } else {
+ if ((c >= 'a') && (c <= 'z')) {
+ ChSet(c);
+ ChSet(static_cast<unsigned char>(c - 'a' + 'A'));
+ } else if ((c >= 'A') && (c <= 'Z')) {
+ ChSet(c);
+ ChSet(static_cast<unsigned char>(c - 'A' + 'a'));
+ } else {
+ ChSet(c);
+ }
+ }
+}
+
+const unsigned char escapeValue(unsigned char ch) {
+ switch (ch) {
+ case 'a': return '\a';
+ case 'b': return '\b';
+ case 'f': return '\f';
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 'v': return '\v';
+ }
+ return 0;
+}
+
+static int GetHexaChar(unsigned char hd1, unsigned char hd2) {
+ int hexValue = 0;
+ if (hd1 >= '0' && hd1 <= '9') {
+ hexValue += 16 * (hd1 - '0');
+ } else if (hd1 >= 'A' && hd1 <= 'F') {
+ hexValue += 16 * (hd1 - 'A' + 10);
+ } else if (hd1 >= 'a' && hd1 <= 'f') {
+ hexValue += 16 * (hd1 - 'a' + 10);
+ } else
+ return -1;
+ if (hd2 >= '0' && hd2 <= '9') {
+ hexValue += hd2 - '0';
+ } else if (hd2 >= 'A' && hd2 <= 'F') {
+ hexValue += hd2 - 'A' + 10;
+ } else if (hd2 >= 'a' && hd2 <= 'f') {
+ hexValue += hd2 - 'a' + 10;
+ } else
+ return -1;
+ return hexValue;
+}
+
+/**
+ * Called when the parser finds a backslash not followed
+ * by a valid expression (like \( in non-Posix mode).
+ * @param pattern: pointer on the char after the backslash.
+ * @param incr: (out) number of chars to skip after expression evaluation.
+ * @return the char if it resolves to a simple char,
+ * or -1 for a char class. In this case, bittab is changed.
+ */
+int RESearch::GetBackslashExpression(
+ const char *pattern,
+ int &incr) {
+ // Since error reporting is primitive and messages are not used anyway,
+ // I choose to interpret unexpected syntax in a logical way instead
+ // of reporting errors. Otherwise, we can stick on, eg., PCRE behavior.
+ incr = 0; // Most of the time, will skip the char "naturally".
+ int c;
+ int result = -1;
+ unsigned char bsc = *pattern;
+ if (!bsc) {
+ // Avoid overrun
+ result = '\\'; // \ at end of pattern, take it literally
+ return result;
+ }
+
+ switch (bsc) {
+ case 'a':
+ case 'b':
+ case 'n':
+ case 'f':
+ case 'r':
+ case 't':
+ case 'v':
+ result = escapeValue(bsc);
+ break;
+ case 'x': {
+ unsigned char hd1 = *(pattern + 1);
+ unsigned char hd2 = *(pattern + 2);
+ int hexValue = GetHexaChar(hd1, hd2);
+ if (hexValue >= 0) {
+ result = hexValue;
+ incr = 2; // Must skip the digits
+ } else {
+ result = 'x'; // \x without 2 digits: see it as 'x'
+ }
+ }
+ break;
+ case 'd':
+ for (c = '0'; c <= '9'; c++) {
+ ChSet(static_cast<unsigned char>(c));
+ }
+ break;
+ case 'D':
+ for (c = 0; c < MAXCHR; c++) {
+ if (c < '0' || c > '9') {
+ ChSet(static_cast<unsigned char>(c));
+ }
+ }
+ break;
+ case 's':
+ ChSet(' ');
+ ChSet('\t');
+ ChSet('\n');
+ ChSet('\r');
+ ChSet('\f');
+ ChSet('\v');
+ break;
+ case 'S':
+ for (c = 0; c < MAXCHR; c++) {
+ if (c != ' ' && !(c >= 0x09 && c <= 0x0D)) {
+ ChSet(static_cast<unsigned char>(c));
+ }
+ }
+ break;
+ case 'w':
+ for (c = 0; c < MAXCHR; c++) {
+ if (iswordc(static_cast<unsigned char>(c))) {
+ ChSet(static_cast<unsigned char>(c));
+ }
+ }
+ break;
+ case 'W':
+ for (c = 0; c < MAXCHR; c++) {
+ if (!iswordc(static_cast<unsigned char>(c))) {
+ ChSet(static_cast<unsigned char>(c));
+ }
+ }
+ break;
+ default:
+ result = bsc;
+ }
+ return result;
+}
+
+const char *RESearch::Compile(const char *pattern, int length, bool caseSensitive, bool posix) {
+ char *mp=nfa; /* nfa pointer */
+ char *lp; /* saved pointer */
+ char *sp=nfa; /* another one */
+ char *mpMax = mp + MAXNFA - BITBLK - 10;
+
+ int tagi = 0; /* tag stack index */
+ int tagc = 1; /* actual tag count */
+
+ int n;
+ char mask; /* xor mask -CCL/NCL */
+ int c1, c2, prevChar;
+
+ if (!pattern || !length) {
+ if (sta)
+ return 0;
+ else
+ return badpat("No previous regular expression");
+ }
+ sta = NOP;
+
+ const char *p=pattern; /* pattern pointer */
+ for (int i=0; i<length; i++, p++) {
+ if (mp > mpMax)
+ return badpat("Pattern too long");
+ lp = mp;
+ switch (*p) {
+
+ case '.': /* match any char */
+ *mp++ = ANY;
+ break;
+
+ case '^': /* match beginning */
+ if (p == pattern)
+ *mp++ = BOL;
+ else {
+ *mp++ = CHR;
+ *mp++ = *p;
+ }
+ break;
+
+ case '$': /* match endofline */
+ if (!*(p+1))
+ *mp++ = EOL;
+ else {
+ *mp++ = CHR;
+ *mp++ = *p;
+ }
+ break;
+
+ case '[': /* match char class */
+ *mp++ = CCL;
+ prevChar = 0;
+
+ i++;
+ if (*++p == '^') {
+ mask = '\377';
+ i++;
+ p++;
+ } else
+ mask = 0;
+
+ if (*p == '-') { /* real dash */
+ i++;
+ prevChar = *p;
+ ChSet(*p++);
+ }
+ if (*p == ']') { /* real brace */
+ i++;
+ prevChar = *p;
+ ChSet(*p++);
+ }
+ while (*p && *p != ']') {
+ if (*p == '-') {
+ if (prevChar < 0) {
+ // Previous def. was a char class like \d, take dash literally
+ prevChar = *p;
+ ChSet(*p);
+ } else if (*(p+1)) {
+ if (*(p+1) != ']') {
+ c1 = prevChar + 1;
+ i++;
+ c2 = *++p;
+ if (c2 == '\\') {
+ if (!*(p+1)) // End of RE
+ return badpat("Missing ]");
+ else {
+ i++;
+ p++;
+ int incr;
+ c2 = GetBackslashExpression(p, incr);
+ i += incr;
+ p += incr;
+ if (c2 >= 0) {
+ // Convention: \c (c is any char) is case sensitive, whatever the option
+ ChSet(static_cast<unsigned char>(c2));
+ prevChar = c2;
+ } else {
+ // bittab is already changed
+ prevChar = -1;
+ }
+ }
+ }
+ if (prevChar < 0) {
+ // Char after dash is char class like \d, take dash literally
+ prevChar = '-';
+ ChSet('-');
+ } else {
+ // Put all chars between c1 and c2 included in the char set
+ while (c1 <= c2) {
+ ChSetWithCase(static_cast<unsigned char>(c1++), caseSensitive);
+ }
+ }
+ } else {
+ // Dash before the ], take it literally
+ prevChar = *p;
+ ChSet(*p);
+ }
+ } else {
+ return badpat("Missing ]");
+ }
+ } else if (*p == '\\' && *(p+1)) {
+ i++;
+ p++;
+ int incr;
+ int c = GetBackslashExpression(p, incr);
+ i += incr;
+ p += incr;
+ if (c >= 0) {
+ // Convention: \c (c is any char) is case sensitive, whatever the option
+ ChSet(static_cast<unsigned char>(c));
+ prevChar = c;
+ } else {
+ // bittab is already changed
+ prevChar = -1;
+ }
+ } else {
+ prevChar = *p;
+ ChSetWithCase(*p, caseSensitive);
+ }
+ i++;
+ p++;
+ }
+ if (!*p)
+ return badpat("Missing ]");
+
+ for (n = 0; n < BITBLK; bittab[n++] = 0)
+ *mp++ = static_cast<char>(mask ^ bittab[n]);
+
+ break;
+
+ case '*': /* match 0 or more... */
+ case '+': /* match 1 or more... */
+ if (p == pattern)
+ return badpat("Empty closure");
+ lp = sp; /* previous opcode */
+ if (*lp == CLO) /* equivalence... */
+ break;
+ switch (*lp) {
+
+ case BOL:
+ case BOT:
+ case EOT:
+ case BOW:
+ case EOW:
+ case REF:
+ return badpat("Illegal closure");
+ default:
+ break;
+ }
+
+ if (*p == '+')
+ for (sp = mp; lp < sp; lp++)
+ *mp++ = *lp;
+
+ *mp++ = END;
+ *mp++ = END;
+ sp = mp;
+ while (--mp > lp)
+ *mp = mp[-1];
+ *mp = CLO;
+ mp = sp;
+ break;
+
+ case '\\': /* tags, backrefs... */
+ i++;
+ switch (*++p) {
+ case '<':
+ *mp++ = BOW;
+ break;
+ case '>':
+ if (*sp == BOW)
+ return badpat("Null pattern inside \\<\\>");
+ *mp++ = EOW;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = *p-'0';
+ if (tagi > 0 && tagstk[tagi] == n)
+ return badpat("Cyclical reference");
+ if (tagc > n) {
+ *mp++ = static_cast<char>(REF);
+ *mp++ = static_cast<char>(n);
+ } else
+ return badpat("Undetermined reference");
+ break;
+ default:
+ if (!posix && *p == '(') {
+ if (tagc < MAXTAG) {
+ tagstk[++tagi] = tagc;
+ *mp++ = BOT;
+ *mp++ = static_cast<char>(tagc++);
+ } else
+ return badpat("Too many \\(\\) pairs");
+ } else if (!posix && *p == ')') {
+ if (*sp == BOT)
+ return badpat("Null pattern inside \\(\\)");
+ if (tagi > 0) {
+ *mp++ = static_cast<char>(EOT);
+ *mp++ = static_cast<char>(tagstk[tagi--]);
+ } else
+ return badpat("Unmatched \\)");
+ } else {
+ int incr;
+ int c = GetBackslashExpression(p, incr);
+ i += incr;
+ p += incr;
+ if (c >= 0) {
+ *mp++ = CHR;
+ *mp++ = static_cast<unsigned char>(c);
+ } else {
+ *mp++ = CCL;
+ mask = 0;
+ for (n = 0; n < BITBLK; bittab[n++] = 0)
+ *mp++ = static_cast<char>(mask ^ bittab[n]);
+ }
+ }
+ }
+ break;
+
+ default : /* an ordinary char */
+ if (posix && *p == '(') {
+ if (tagc < MAXTAG) {
+ tagstk[++tagi] = tagc;
+ *mp++ = BOT;
+ *mp++ = static_cast<char>(tagc++);
+ } else
+ return badpat("Too many () pairs");
+ } else if (posix && *p == ')') {
+ if (*sp == BOT)
+ return badpat("Null pattern inside ()");
+ if (tagi > 0) {
+ *mp++ = static_cast<char>(EOT);
+ *mp++ = static_cast<char>(tagstk[tagi--]);
+ } else
+ return badpat("Unmatched )");
+ } else {
+ unsigned char c = *p;
+ if (!c) // End of RE
+ c = '\\'; // We take it as raw backslash
+ if (caseSensitive || !iswordc(c)) {
+ *mp++ = CHR;
+ *mp++ = c;
+ } else {
+ *mp++ = CCL;
+ mask = 0;
+ ChSetWithCase(c, false);
+ for (n = 0; n < BITBLK; bittab[n++] = 0)
+ *mp++ = static_cast<char>(mask ^ bittab[n]);
+ }
+ }
+ break;
+ }
+ sp = lp;
+ }
+ if (tagi > 0)
+ return badpat((posix ? "Unmatched (" : "Unmatched \\("));
+ *mp = END;
+ sta = OKP;
+ return 0;
+}
+
+/*
+ * RESearch::Execute:
+ * execute nfa to find a match.
+ *
+ * special cases: (nfa[0])
+ * BOL
+ * Match only once, starting from the
+ * beginning.
+ * CHR
+ * First locate the character without
+ * calling PMatch, and if found, call
+ * PMatch for the remaining string.
+ * END
+ * RESearch::Compile failed, poor luser did not
+ * check for it. Fail fast.
+ *
+ * If a match is found, bopat[0] and eopat[0] are set
+ * to the beginning and the end of the matched fragment,
+ * respectively.
+ *
+ */
+int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) {
+ unsigned char c;
+ int ep = NOTFOUND;
+ char *ap = nfa;
+
+ bol = lp;
+ failure = 0;
+
+ Clear();
+
+ switch (*ap) {
+
+ case BOL: /* anchored: match from BOL only */
+ ep = PMatch(ci, lp, endp, ap);
+ break;
+ case EOL: /* just searching for end of line normal path doesn't work */
+ if (*(ap+1) == END) {
+ lp = endp;
+ ep = lp;
+ break;
+ } else {
+ return 0;
+ }
+ case CHR: /* ordinary char: locate it fast */
+ c = *(ap+1);
+ while ((lp < endp) && (ci.CharAt(lp) != c))
+ lp++;
+ if (lp >= endp) /* if EOS, fail, else fall thru. */
+ return 0;
+ default: /* regular matching all the way. */
+ while (lp < endp) {
+ ep = PMatch(ci, lp, endp, ap);
+ if (ep != NOTFOUND)
+ break;
+ lp++;
+ }
+ break;
+ case END: /* munged automaton. fail always */
+ return 0;
+ }
+ if (ep == NOTFOUND)
+ return 0;
+
+ bopat[0] = lp;
+ eopat[0] = ep;
+ return 1;
+}
+
+/*
+ * PMatch: internal routine for the hard part
+ *
+ * This code is partly snarfed from an early grep written by
+ * David Conroy. The backref and tag stuff, and various other
+ * innovations are by oz.
+ *
+ * special case optimizations: (nfa[n], nfa[n+1])
+ * CLO ANY
+ * We KNOW .* will match everything upto the
+ * end of line. Thus, directly go to the end of
+ * line, without recursive PMatch calls. As in
+ * the other closure cases, the remaining pattern
+ * must be matched by moving backwards on the
+ * string recursively, to find a match for xy
+ * (x is ".*" and y is the remaining pattern)
+ * where the match satisfies the LONGEST match for
+ * x followed by a match for y.
+ * CLO CHR
+ * We can again scan the string forward for the
+ * single char and at the point of failure, we
+ * execute the remaining nfa recursively, same as
+ * above.
+ *
+ * At the end of a successful match, bopat[n] and eopat[n]
+ * are set to the beginning and end of subpatterns matched
+ * by tagged expressions (n = 1 to 9).
+ */
+
+extern void re_fail(char *,char);
+
+#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
+
+/*
+ * skip values for CLO XXX to skip past the closure
+ */
+
+#define ANYSKIP 2 /* [CLO] ANY END */
+#define CHRSKIP 3 /* [CLO] CHR chr END */
+#define CCLSKIP 34 /* [CLO] CCL 32 bytes END */
+
+int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) {
+ int op, c, n;
+ int e; /* extra pointer for CLO */
+ int bp; /* beginning of subpat... */
+ int ep; /* ending of subpat... */
+ int are; /* to save the line ptr. */
+
+ while ((op = *ap++) != END)
+ switch (op) {
+
+ case CHR:
+ if (ci.CharAt(lp++) != *ap++)
+ return NOTFOUND;
+ break;
+ case ANY:
+ if (lp++ >= endp)
+ return NOTFOUND;
+ break;
+ case CCL:
+ if (lp >= endp)
+ return NOTFOUND;
+ c = ci.CharAt(lp++);
+ if (!isinset(ap,c))
+ return NOTFOUND;
+ ap += BITBLK;
+ break;
+ case BOL:
+ if (lp != bol)
+ return NOTFOUND;
+ break;
+ case EOL:
+ if (lp < endp)
+ return NOTFOUND;
+ break;
+ case BOT:
+ bopat[*ap++] = lp;
+ break;
+ case EOT:
+ eopat[*ap++] = lp;
+ break;
+ case BOW:
+ if ((lp!=bol && iswordc(ci.CharAt(lp-1))) || !iswordc(ci.CharAt(lp)))
+ return NOTFOUND;
+ break;
+ case EOW:
+ if (lp==bol || !iswordc(ci.CharAt(lp-1)) || iswordc(ci.CharAt(lp)))
+ return NOTFOUND;
+ break;
+ case REF:
+ n = *ap++;
+ bp = bopat[n];
+ ep = eopat[n];
+ while (bp < ep)
+ if (ci.CharAt(bp++) != ci.CharAt(lp++))
+ return NOTFOUND;
+ break;
+ case CLO:
+ are = lp;
+ switch (*ap) {
+
+ case ANY:
+ while (lp < endp)
+ lp++;
+ n = ANYSKIP;
+ break;
+ case CHR:
+ c = *(ap+1);
+ while ((lp < endp) && (c == ci.CharAt(lp)))
+ lp++;
+ n = CHRSKIP;
+ break;
+ case CCL:
+ while ((lp < endp) && isinset(ap+1,ci.CharAt(lp)))
+ lp++;
+ n = CCLSKIP;
+ break;
+ default:
+ failure = true;
+ //re_fail("closure: bad nfa.", *ap);
+ return NOTFOUND;
+ }
+
+ ap += n;
+
+ while (lp >= are) {
+ if ((e = PMatch(ci, lp, endp, ap)) != NOTFOUND)
+ return e;
+ --lp;
+ }
+ return NOTFOUND;
+ default:
+ //re_fail("RESearch::Execute: bad nfa.", static_cast<char>(op));
+ return NOTFOUND;
+ }
+ return lp;
+}
+
+/*
+ * RESearch::Substitute:
+ * substitute the matched portions of the src in dst.
+ *
+ * & substitute the entire matched pattern.
+ *
+ * \digit substitute a subpattern, with the given tag number.
+ * Tags are numbered from 1 to 9. If the particular
+ * tagged subpattern does not exist, null is substituted.
+ */
+int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst) {
+ unsigned char c;
+ int pin;
+ int bp;
+ int ep;
+
+ if (!*src || !bopat[0])
+ return 0;
+
+ while ((c = *src++) != 0) {
+ switch (c) {
+
+ case '&':
+ pin = 0;
+ break;
+
+ case '\\':
+ c = *src++;
+ if (c >= '0' && c <= '9') {
+ pin = c - '0';
+ break;
+ }
+
+ default:
+ *dst++ = c;
+ continue;
+ }
+
+ if ((bp = bopat[pin]) != 0 && (ep = eopat[pin]) != 0) {
+ while (ci.CharAt(bp) && bp < ep)
+ *dst++ = ci.CharAt(bp++);
+ if (bp < ep)
+ return 0;
+ }
+ }
+ *dst = '\0';
+ return 1;
+}
+
diff --git a/scintilla/src/RESearch.h b/scintilla/src/RESearch.h
new file mode 100644
index 0000000..e2f8d50
--- /dev/null
+++ b/scintilla/src/RESearch.h
@@ -0,0 +1,75 @@
+// Scintilla source code edit control
+/** @file RESearch.h
+ ** Interface to the regular expression search library.
+ **/
+// Written by Neil Hodgson <neilh@scintilla.org>
+// Based on the work of Ozan S. Yigit.
+// This file is in the public domain.
+
+#ifndef RESEARCH_H
+#define RESEARCH_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/*
+ * The following defines are not meant to be changeable.
+ * They are for readability only.
+ */
+#define MAXCHR 256
+#define CHRBIT 8
+#define BITBLK MAXCHR/CHRBIT
+
+class CharacterIndexer {
+public:
+ virtual char CharAt(int index)=0;
+ virtual ~CharacterIndexer() {
+ }
+};
+
+class RESearch {
+
+public:
+ RESearch(CharClassify *charClassTable);
+ ~RESearch();
+ bool GrabMatches(CharacterIndexer &ci);
+ const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
+ int Execute(CharacterIndexer &ci, int lp, int endp);
+ int Substitute(CharacterIndexer &ci, char *src, char *dst);
+
+ enum { MAXTAG=10 };
+ enum { MAXNFA=2048 };
+ enum { NOTFOUND=-1 };
+
+ int bopat[MAXTAG];
+ int eopat[MAXTAG];
+ char *pat[MAXTAG];
+
+private:
+ void Init();
+ void Clear();
+ void ChSet(unsigned char c);
+ void ChSetWithCase(unsigned char c, bool caseSensitive);
+ int GetBackslashExpression(const char *pattern, int &incr);
+
+ int PMatch(CharacterIndexer &ci, int lp, int endp, char *ap);
+
+ int bol;
+ int tagstk[MAXTAG]; /* subpat tag stack */
+ char nfa[MAXNFA]; /* automaton */
+ int sta;
+ unsigned char bittab[BITBLK]; /* bit table for CCL pre-set bits */
+ int failure;
+ CharClassify *charClass;
+ bool iswordc(unsigned char x) {
+ return charClass->IsWord(x);
+ }
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
+
diff --git a/scintilla/src/RunStyles.cxx b/scintilla/src/RunStyles.cxx
new file mode 100644
index 0000000..eed5897
--- /dev/null
+++ b/scintilla/src/RunStyles.cxx
@@ -0,0 +1,216 @@
+/** @file RunStyles.cxx
+ ** Data structure used to store sparse styles.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// Find the first run at a position
+int RunStyles::RunFromPosition(int position) {
+ int run = starts->PartitionFromPosition(position);
+ // Go to first element with this position
+ while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
+ run--;
+ }
+ return run;
+}
+
+// If there is no run boundary at position, insert one continuing style.
+int RunStyles::SplitRun(int position) {
+ int run = RunFromPosition(position);
+ int posRun = starts->PositionFromPartition(run);
+ if (posRun < position) {
+ int runStyle = ValueAt(position);
+ run++;
+ starts->InsertPartition(run, position);
+ styles->InsertValue(run, 1, runStyle);
+ }
+ return run;
+}
+
+void RunStyles::RemoveRun(int run) {
+ starts->RemovePartition(run);
+ styles->DeleteRange(run, 1);
+}
+
+void RunStyles::RemoveRunIfEmpty(int run) {
+ if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
+ if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
+ RemoveRun(run);
+ }
+ }
+}
+
+void RunStyles::RemoveRunIfSameAsPrevious(int run) {
+ if ((run > 0) && (run < starts->Partitions())) {
+ if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
+ RemoveRun(run);
+ }
+ }
+}
+
+RunStyles::RunStyles() {
+ starts = new Partitioning(8);
+ styles = new SplitVector<int>();
+ styles->InsertValue(0, 2, 0);
+}
+
+RunStyles::~RunStyles() {
+ delete starts;
+ starts = NULL;
+ delete styles;
+ styles = NULL;
+}
+
+int RunStyles::Length() const {
+ return starts->PositionFromPartition(starts->Partitions());
+}
+
+int RunStyles::ValueAt(int position) const {
+ return styles->ValueAt(starts->PartitionFromPosition(position));
+}
+
+int RunStyles::FindNextChange(int position, int end) {
+ int run = starts->PartitionFromPosition(position);
+ if (run < starts->Partitions()) {
+ int runChange = starts->PositionFromPartition(run);
+ if (runChange > position)
+ return runChange;
+ int nextChange = starts->PositionFromPartition(run + 1);
+ if (nextChange > position) {
+ return nextChange;
+ } else if (position < end) {
+ return end;
+ } else {
+ return end + 1;
+ }
+ } else {
+ return end + 1;
+ }
+}
+
+int RunStyles::StartRun(int position) {
+ return starts->PositionFromPartition(starts->PartitionFromPosition(position));
+}
+
+int RunStyles::EndRun(int position) {
+ return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
+}
+
+bool RunStyles::FillRange(int &position, int value, int &fillLength) {
+ int end = position + fillLength;
+ int runEnd = RunFromPosition(end);
+ if (styles->ValueAt(runEnd) == value) {
+ // End already has value so trim range.
+ end = starts->PositionFromPartition(runEnd);
+ if (position >= end) {
+ // Whole range is already same as value so no action
+ return false;
+ }
+ fillLength = end - position;
+ } else {
+ runEnd = SplitRun(end);
+ }
+ int runStart = RunFromPosition(position);
+ if (styles->ValueAt(runStart) == value) {
+ // Start is in expected value so trim range.
+ runStart++;
+ position = starts->PositionFromPartition(runStart);
+ fillLength = end - position;
+ } else {
+ if (starts->PositionFromPartition(runStart) < position) {
+ runStart = SplitRun(position);
+ runEnd++;
+ }
+ }
+ if (runStart < runEnd) {
+ styles->SetValueAt(runStart, value);
+ // Remove each old run over the range
+ for (int run=runStart+1; run<runEnd; run++) {
+ RemoveRun(runStart+1);
+ }
+ runEnd = RunFromPosition(end);
+ RemoveRunIfSameAsPrevious(runEnd);
+ RemoveRunIfSameAsPrevious(runStart);
+ }
+ return true;
+}
+
+void RunStyles::SetValueAt(int position, int value) {
+ int len = 1;
+ FillRange(position, value, len);
+}
+
+void RunStyles::InsertSpace(int position, int insertLength) {
+ int runStart = RunFromPosition(position);
+ if (starts->PositionFromPartition(runStart) == position) {
+ int runStyle = ValueAt(position);
+ // Inserting at start of run so make previous longer
+ if (runStart == 0) {
+ // Inserting at start of document so ensure 0
+ if (runStyle) {
+ styles->SetValueAt(0, 0);
+ starts->InsertPartition(1, 0);
+ styles->InsertValue(1, 1, runStyle);
+ starts->InsertText(0, insertLength);
+ } else {
+ starts->InsertText(runStart, insertLength);
+ }
+ } else {
+ if (runStyle) {
+ starts->InsertText(runStart-1, insertLength);
+ } else {
+ // Insert at end of run so do not extend style
+ starts->InsertText(runStart, insertLength);
+ }
+ }
+ } else {
+ starts->InsertText(runStart, insertLength);
+ }
+}
+
+void RunStyles::DeleteAll() {
+ delete starts;
+ starts = NULL;
+ delete styles;
+ styles = NULL;
+ starts = new Partitioning(8);
+ styles = new SplitVector<int>();
+ styles->InsertValue(0, 2, 0);
+}
+
+void RunStyles::DeleteRange(int position, int deleteLength) {
+ int end = position + deleteLength;
+ int runStart = RunFromPosition(position);
+ int runEnd = RunFromPosition(end);
+ if (runStart == runEnd) {
+ // Deleting from inside one run
+ starts->InsertText(runStart, -deleteLength);
+ } else {
+ runStart = SplitRun(position);
+ runEnd = SplitRun(end);
+ starts->InsertText(runStart, -deleteLength);
+ // Remove each old run over the range
+ for (int run=runStart; run<runEnd; run++) {
+ RemoveRun(runStart);
+ }
+ RemoveRunIfEmpty(runStart);
+ RemoveRunIfSameAsPrevious(runStart);
+ }
+}
+
diff --git a/scintilla/src/RunStyles.h b/scintilla/src/RunStyles.h
new file mode 100644
index 0000000..ca01e4d
--- /dev/null
+++ b/scintilla/src/RunStyles.h
@@ -0,0 +1,46 @@
+/** @file RunStyles.h
+ ** Data structure used to store sparse styles.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/// Styling buffer using one element for each run rather than using
+/// a filled buffer.
+
+#ifndef RUNSTYLES_H
+#define RUNSTYLES_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class RunStyles {
+public:
+ Partitioning *starts;
+ SplitVector<int> *styles;
+ int RunFromPosition(int position);
+ int SplitRun(int position);
+ void RemoveRun(int run);
+ void RemoveRunIfEmpty(int run);
+ void RemoveRunIfSameAsPrevious(int run);
+public:
+ RunStyles();
+ ~RunStyles();
+ int Length() const;
+ int ValueAt(int position) const;
+ int FindNextChange(int position, int end);
+ int StartRun(int position);
+ int EndRun(int position);
+ // Returns true if some values may have changed
+ bool FillRange(int &position, int value, int &fillLength);
+ void SetValueAt(int position, int value);
+ void InsertSpace(int position, int insertLength);
+ void DeleteAll();
+ void DeleteRange(int position, int deleteLength);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/SVector.h b/scintilla/src/SVector.h
new file mode 100644
index 0000000..7d1a8a8
--- /dev/null
+++ b/scintilla/src/SVector.h
@@ -0,0 +1,123 @@
+// Scintilla source code edit control
+/** @file SVector.h
+ ** A simple expandable vector.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@hare.net.au>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SVECTOR_H
+#define SVECTOR_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ * A simple expandable integer vector.
+ * Storage not allocated for elements until an element is used.
+ * This makes it very lightweight unless used so is a good match for optional features.
+ */
+class SVector {
+ enum { allocSize = 4000 };
+
+ int *v; ///< The vector
+ unsigned int size; ///< Number of elements allocated
+ unsigned int len; ///< Number of elements used in vector
+
+ /** Internally allocate more elements than the user wants
+ * to avoid thrashing the memory allocator. */
+ void SizeTo(int newSize) {
+ if (newSize < allocSize)
+ newSize += allocSize;
+ else
+ newSize = (newSize * 3) / 2;
+ int *newv = new int[newSize];
+ size = newSize;
+ unsigned int i=0;
+ for (; i<len; i++) {
+ newv[i] = v[i];
+ }
+ for (; i<size; i++) {
+ newv[i] = 0;
+ }
+ delete []v;
+ v = newv;
+ }
+
+public:
+ SVector() {
+ v = 0;
+ len = 0;
+ size = 0;
+ }
+ ~SVector() {
+ Free();
+ }
+ /// Constructor from another vector.
+ SVector(const SVector &other) {
+ v = 0;
+ len = 0;
+ size = 0;
+ if (other.Length() > 0) {
+ SizeTo(other.Length());
+ for (int i=0; i<other.Length(); i++)
+ v[i] = other.v[i];
+ len = other.Length();
+ }
+ }
+ /// Copy constructor.
+ SVector &operator=(const SVector &other) {
+ if (this != &other) {
+ delete []v;
+ v = 0;
+ len = 0;
+ size = 0;
+ if (other.Length() > 0) {
+ SizeTo(other.Length());
+ for (int i=0; i<other.Length(); i++)
+ v[i] = other.v[i];
+ len = other.Length();
+ }
+ }
+ return *this;
+ }
+ /** @brief Accessor.
+ * Allows to access values from the list, and grows it if accessing
+ * outside the current bounds. The returned value in this case is 0. */
+ int &operator[](unsigned int i) {
+ if (i >= len) {
+ if (i >= size) {
+ SizeTo(i);
+ }
+ len = i+1;
+ }
+ return v[i];
+ }
+ /// Reset vector.
+ void Free() {
+ delete []v;
+ v = 0;
+ size = 0;
+ len = 0;
+ }
+ /** @brief Grow vector size.
+ * Doesn't allow a vector to be shrinked. */
+ void SetLength(unsigned int newLength) {
+ if (newLength > len) {
+ if (newLength >= size) {
+ SizeTo(newLength);
+ }
+ }
+ len = newLength;
+ }
+ /// Get the current length (number of used elements) of the vector.
+ int Length() const {
+ return len;
+ }
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/SciTE.properties b/scintilla/src/SciTE.properties
new file mode 100644
index 0000000..41f2bd7
--- /dev/null
+++ b/scintilla/src/SciTE.properties
@@ -0,0 +1,6 @@
+# SciTE.properties is the per directory local options file and can be used to override
+# settings made in SciTEGlobal.properties
+command.build.directory.*.cxx=..\win32
+command.build.directory.*.h=..\win32
+command.build.*.cxx=nmake -f scintilla.mak QUIET=1 DEBUG=0
+command.build.*.h=nmake -f scintilla.mak QUIET=1 DEBUG=0
diff --git a/scintilla/src/ScintillaBase.cxx b/scintilla/src/ScintillaBase.cxx
new file mode 100644
index 0000000..890d2b1
--- /dev/null
+++ b/scintilla/src/ScintillaBase.cxx
@@ -0,0 +1,774 @@
+// Scintilla source code edit control
+/** @file ScintillaBase.cxx
+ ** An enhanced subclass of Editor with calltips, autocomplete and context menu.
+ **/
+// 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 <stdio.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "PropSet.h"
+#include "PropSetSimple.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "Accessor.h"
+#include "DocumentAccessor.h"
+#include "KeyWords.h"
+#endif
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+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;
+ keyWordLists[numWordLists] = 0;
+#endif
+}
+
+ScintillaBase::~ScintillaBase() {
+#ifdef SCI_LEXER
+ for (int wl = 0; wl < numWordLists; wl++)
+ delete keyWordLists[wl];
+#endif
+}
+
+void ScintillaBase::Finalise() {
+ Editor::Finalise();
+ popup.Destroy();
+}
+
+void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
+ Editor::RefreshColourPalette(pal, want);
+ ct.RefreshColourPalette(pal, want);
+}
+
+void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
+ bool isFillUp = ac.Active() && ac.IsFillUpChar(*s);
+ if (!isFillUp) {
+ Editor::AddCharUTF(s, len, treatAsDBCS);
+ }
+ if (ac.Active()) {
+ AutoCompleteCharacterAdded(s[0]);
+ // For fill ups add the character after the autocompletion has
+ // triggered so containers see the key so can display a calltip.
+ if (isFillUp) {
+ Editor::AddCharUTF(s, len, treatAsDBCS);
+ }
+ }
+}
+
+void ScintillaBase::Command(int cmdId) {
+
+ switch (cmdId) {
+
+ case idAutoComplete: // Nothing to do
+
+ break;
+
+ case idCallTip: // Nothing to do
+
+ break;
+
+ case idcmdUndo:
+ WndProc(SCI_UNDO, 0, 0);
+ break;
+
+ case idcmdRedo:
+ WndProc(SCI_REDO, 0, 0);
+ break;
+
+ case idcmdCut:
+ WndProc(SCI_CUT, 0, 0);
+ break;
+
+ case idcmdCopy:
+ WndProc(SCI_COPY, 0, 0);
+ break;
+
+ case idcmdPaste:
+ WndProc(SCI_PASTE, 0, 0);
+ break;
+
+ case idcmdDelete:
+ WndProc(SCI_CLEAR, 0, 0);
+ break;
+
+ case idcmdSelectAll:
+ WndProc(SCI_SELECTALL, 0, 0);
+ break;
+ }
+}
+
+int ScintillaBase::KeyCommand(unsigned int iMessage) {
+ // Most key commands cancel autocompletion mode
+ if (ac.Active()) {
+ switch (iMessage) {
+ // Except for these
+ case SCI_LINEDOWN:
+ AutoCompleteMove(1);
+ return 0;
+ case SCI_LINEUP:
+ AutoCompleteMove( -1);
+ return 0;
+ case SCI_PAGEDOWN:
+ AutoCompleteMove(5);
+ return 0;
+ case SCI_PAGEUP:
+ AutoCompleteMove( -5);
+ return 0;
+ case SCI_VCHOME:
+ AutoCompleteMove( -5000);
+ return 0;
+ case SCI_LINEEND:
+ AutoCompleteMove(5000);
+ return 0;
+ case SCI_DELETEBACK:
+ DelCharBack(true);
+ AutoCompleteCharacterDeleted();
+ EnsureCaretVisible();
+ return 0;
+ case SCI_DELETEBACKNOTLINE:
+ DelCharBack(false);
+ AutoCompleteCharacterDeleted();
+ EnsureCaretVisible();
+ return 0;
+ case SCI_TAB:
+ AutoCompleteCompleted();
+ return 0;
+ case SCI_NEWLINE:
+ AutoCompleteCompleted();
+ return 0;
+
+ default:
+ AutoCompleteCancel();
+ }
+ }
+
+ if (ct.inCallTipMode) {
+ if (
+ (iMessage != SCI_CHARLEFT) &&
+ (iMessage != SCI_CHARLEFTEXTEND) &&
+ (iMessage != SCI_CHARRIGHT) &&
+ (iMessage != SCI_CHARRIGHTEXTEND) &&
+ (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
+ (iMessage != SCI_DELETEBACK) &&
+ (iMessage != SCI_DELETEBACKNOTLINE)
+ ) {
+ ct.CallTipCancel();
+ }
+ if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) {
+ if (sel.MainCaret() <= ct.posStartCallTip) {
+ ct.CallTipCancel();
+ }
+ }
+ }
+ return Editor::KeyCommand(iMessage);
+}
+
+void ScintillaBase::AutoCompleteDoubleClick(void *p) {
+ ScintillaBase *sci = reinterpret_cast<ScintillaBase *>(p);
+ sci->AutoCompleteCompleted();
+}
+
+void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
+ //Platform::DebugPrintf("AutoComplete %s\n", list);
+ ct.CallTipCancel();
+
+ if (ac.chooseSingle && (listType == 0)) {
+ if (list && !strchr(list, ac.GetSeparator())) {
+ const char *typeSep = strchr(list, ac.GetTypesep());
+ size_t lenInsert = (typeSep) ? (typeSep-list) : strlen(list);
+ if (ac.ignoreCase) {
+ SetEmptySelection(sel.MainCaret() - lenEntered);
+ pdoc->DeleteChars(sel.MainCaret(), lenEntered);
+ SetEmptySelection(sel.MainCaret());
+ pdoc->InsertString(sel.MainCaret(), list, lenInsert);
+ SetEmptySelection(sel.MainCaret() + lenInsert);
+ } else {
+ SetEmptySelection(sel.MainCaret());
+ pdoc->InsertString(sel.MainCaret(), list + lenEntered, lenInsert - lenEntered);
+ SetEmptySelection(sel.MainCaret() + lenInsert - lenEntered);
+ }
+ return;
+ }
+ }
+ ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(),
+ lenEntered, vs.lineHeight, IsUnicodeMode());
+
+ PRectangle rcClient = GetClientRectangle();
+ Point pt = LocationFromPosition(sel.MainCaret() - lenEntered);
+ PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
+ if (rcPopupBounds.Height() == 0)
+ rcPopupBounds = rcClient;
+
+ int heightLB = 100;
+ int widthLB = 100;
+ if (pt.x >= rcClient.right - widthLB) {
+ HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB);
+ Redraw();
+ pt = PointMainCaret();
+ }
+ PRectangle rcac;
+ rcac.left = pt.x - ac.lb->CaretFromEdge();
+ if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below.
+ pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above.
+ rcac.top = pt.y - heightLB;
+ if (rcac.top < rcPopupBounds.top) {
+ heightLB -= (rcPopupBounds.top - rcac.top);
+ rcac.top = rcPopupBounds.top;
+ }
+ } else {
+ rcac.top = pt.y + vs.lineHeight;
+ }
+ rcac.right = rcac.left + widthLB;
+ rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcPopupBounds.bottom);
+ ac.lb->SetPositionRelative(rcac, wMain);
+ ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
+ unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
+ ac.lb->SetAverageCharWidth(aveCharWidth);
+ ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);
+
+ ac.SetList(list);
+
+ // Fiddle the position of the list so it is right next to the target and wide enough for all its strings
+ 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;
+ if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Wont fit below.
+ ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above.
+ rcList.top = pt.y - heightAlloced;
+ } else {
+ rcList.top = pt.y + vs.lineHeight;
+ }
+ rcList.bottom = rcList.top + heightAlloced;
+ ac.lb->SetPositionRelative(rcList, wMain);
+ ac.Show(true);
+ if (lenEntered != 0) {
+ AutoCompleteMoveToCurrentWord();
+ }
+}
+
+void ScintillaBase::AutoCompleteCancel() {
+ if (ac.Active()) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_AUTOCCANCELLED;
+ scn.wParam = 0;
+ scn.listType = 0;
+ NotifyParent(scn);
+ }
+ ac.Cancel();
+}
+
+void ScintillaBase::AutoCompleteMove(int delta) {
+ ac.Move(delta);
+}
+
+void ScintillaBase::AutoCompleteMoveToCurrentWord() {
+ char wordCurrent[1000];
+ int i;
+ int startWord = ac.posStart - ac.startLen;
+ for (i = startWord; i < sel.MainCaret() && i - startWord < 1000; i++)
+ wordCurrent[i - startWord] = pdoc->CharAt(i);
+ wordCurrent[Platform::Minimum(i - startWord, 999)] = '\0';
+ ac.Select(wordCurrent);
+}
+
+void ScintillaBase::AutoCompleteCharacterAdded(char ch) {
+ if (ac.IsFillUpChar(ch)) {
+ AutoCompleteCompleted();
+ } else if (ac.IsStopChar(ch)) {
+ AutoCompleteCancel();
+ } else {
+ AutoCompleteMoveToCurrentWord();
+ }
+}
+
+void ScintillaBase::AutoCompleteCharacterDeleted() {
+ if (sel.MainCaret() < ac.posStart - ac.startLen) {
+ AutoCompleteCancel();
+ } else if (ac.cancelAtStartPos && (sel.MainCaret() <= ac.posStart)) {
+ AutoCompleteCancel();
+ } else {
+ AutoCompleteMoveToCurrentWord();
+ }
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_AUTOCCHARDELETED;
+ scn.wParam = 0;
+ scn.listType = 0;
+ NotifyParent(scn);
+}
+
+void ScintillaBase::AutoCompleteCompleted() {
+ int item = ac.lb->GetSelection();
+ char selected[1000];
+ selected[0] = '\0';
+ if (item != -1) {
+ ac.lb->GetValue(item, selected, sizeof(selected));
+ } else {
+ AutoCompleteCancel();
+ return;
+ }
+
+ ac.Show(false);
+
+ 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 = selected;
+ NotifyParent(scn);
+
+ if (!ac.Active())
+ return;
+ ac.Cancel();
+
+ if (listType > 0)
+ return;
+
+ Position endPos = sel.MainCaret();
+ if (ac.dropRestOfWord)
+ endPos = pdoc->ExtendWordSelect(endPos, 1, true);
+ if (endPos < firstPos)
+ return;
+ UndoGroup ug(pdoc);
+ if (endPos != firstPos) {
+ pdoc->DeleteChars(firstPos, endPos - firstPos);
+ }
+ SetEmptySelection(ac.posStart);
+ if (item != -1) {
+ pdoc->InsertCString(firstPos, selected);
+ SetEmptySelection(firstPos + static_cast<int>(strlen(selected)));
+ }
+}
+
+int ScintillaBase::AutoCompleteGetCurrent() {
+ if (!ac.Active())
+ return -1;
+ return ac.lb->GetSelection();
+}
+
+int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) {
+ if (ac.Active()) {
+ int item = ac.lb->GetSelection();
+ char selected[1000];
+ selected[0] = '\0';
+ if (item != -1) {
+ ac.lb->GetValue(item, selected, sizeof(selected));
+ if (buffer != NULL)
+ strcpy(buffer, selected);
+ return strlen(selected);
+ }
+ }
+ if (buffer != NULL)
+ *buffer = '\0';
+ return 0;
+}
+
+void ScintillaBase::CallTipShow(Point pt, const char *defn) {
+ ac.Cancel();
+ pt.y += vs.lineHeight;
+ // If container knows about STYLE_CALLTIP then use it in place of the
+ // STYLE_DEFAULT for the face name, size and character set. Also use it
+ // for the foreground and background colour.
+ int ctStyle = ct.UseStyleCallTip() ? STYLE_CALLTIP : STYLE_DEFAULT;
+ if (ct.UseStyleCallTip()) {
+ ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back);
+ }
+ PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
+ defn,
+ vs.styles[ctStyle].fontName,
+ vs.styles[ctStyle].sizeZoomed,
+ CodePage(),
+ vs.styles[ctStyle].characterSet,
+ wMain);
+ // If the call-tip window would be out of the client
+ // space, adjust so it displays above the text.
+ PRectangle rcClient = GetClientRectangle();
+ if (rc.bottom > rcClient.bottom) {
+ int offset = vs.lineHeight + rc.Height();
+ rc.top -= offset;
+ rc.bottom -= offset;
+ }
+ // Now display the window.
+ CreateCallTipWindow(rc);
+ ct.wCallTip.SetPositionRelative(rc, wMain);
+ ct.wCallTip.Show();
+}
+
+void ScintillaBase::CallTipClick() {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_CALLTIPCLICK;
+ scn.position = ct.clickPlace;
+ NotifyParent(scn);
+}
+
+void ScintillaBase::ContextMenu(Point pt) {
+ if (displayPopupMenu) {
+ bool writable = !WndProc(SCI_GETREADONLY, 0, 0);
+ popup.CreatePopUp();
+ AddToPopUp("Undo", idcmdUndo, writable && pdoc->CanUndo());
+ AddToPopUp("Redo", idcmdRedo, writable && pdoc->CanRedo());
+ AddToPopUp("");
+ AddToPopUp("Cut", idcmdCut, writable && !sel.Empty());
+ AddToPopUp("Copy", idcmdCopy, !sel.Empty());
+ AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0));
+ AddToPopUp("Delete", idcmdDelete, writable && !sel.Empty());
+ AddToPopUp("");
+ AddToPopUp("Select All", idcmdSelectAll);
+ popup.Show(pt, wMain);
+ }
+}
+
+void ScintillaBase::CancelModes() {
+ AutoCompleteCancel();
+ ct.CallTipCancel();
+ Editor::CancelModes();
+}
+
+void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+ CancelModes();
+ Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+#ifdef SCI_LEXER
+void ScintillaBase::SetLexer(uptr_t wParam) {
+ lexLanguage = wParam;
+ lexCurrent = LexerModule::Find(lexLanguage);
+ if (!lexCurrent)
+ lexCurrent = LexerModule::Find(SCLEX_NULL);
+ int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
+ vs.EnsureStyle((1 << bits) - 1);
+}
+
+void ScintillaBase::SetLexerLanguage(const char *languageName) {
+ lexLanguage = SCLEX_CONTAINER;
+ lexCurrent = LexerModule::Find(languageName);
+ if (!lexCurrent)
+ lexCurrent = LexerModule::Find(SCLEX_NULL);
+ if (lexCurrent)
+ lexLanguage = lexCurrent->GetLanguage();
+ int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
+ vs.EnsureStyle((1 << bits) - 1);
+}
+
+void ScintillaBase::Colourise(int start, int end) {
+ 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) & pdoc->stylingBitsMask;
+ 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
+
+void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
+#ifdef SCI_LEXER
+ if (lexLanguage != SCLEX_CONTAINER) {
+ int endStyled = WndProc(SCI_GETENDSTYLED, 0, 0);
+ int lineEndStyled = WndProc(SCI_LINEFROMPOSITION, endStyled, 0);
+ endStyled = WndProc(SCI_POSITIONFROMLINE, lineEndStyled, 0);
+ Colourise(endStyled, endStyleNeeded);
+ return;
+ }
+#endif
+ Editor::NotifyStyleToNeeded(endStyleNeeded);
+}
+
+sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ switch (iMessage) {
+ case SCI_AUTOCSHOW:
+ listType = 0;
+ AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_AUTOCCANCEL:
+ ac.Cancel();
+ break;
+
+ case SCI_AUTOCACTIVE:
+ return ac.Active();
+
+ case SCI_AUTOCPOSSTART:
+ return ac.posStart;
+
+ case SCI_AUTOCCOMPLETE:
+ AutoCompleteCompleted();
+ break;
+
+ case SCI_AUTOCSETSEPARATOR:
+ ac.SetSeparator(static_cast<char>(wParam));
+ break;
+
+ case SCI_AUTOCGETSEPARATOR:
+ return ac.GetSeparator();
+
+ case SCI_AUTOCSTOPS:
+ ac.SetStopChars(reinterpret_cast<char *>(lParam));
+ break;
+
+ case SCI_AUTOCSELECT:
+ ac.Select(reinterpret_cast<char *>(lParam));
+ break;
+
+ case SCI_AUTOCGETCURRENT:
+ return AutoCompleteGetCurrent();
+
+ case SCI_AUTOCGETCURRENTTEXT:
+ return AutoCompleteGetCurrentText(reinterpret_cast<char *>(lParam));
+
+ case SCI_AUTOCSETCANCELATSTART:
+ ac.cancelAtStartPos = wParam != 0;
+ break;
+
+ case SCI_AUTOCGETCANCELATSTART:
+ return ac.cancelAtStartPos;
+
+ case SCI_AUTOCSETFILLUPS:
+ ac.SetFillUpChars(reinterpret_cast<char *>(lParam));
+ break;
+
+ case SCI_AUTOCSETCHOOSESINGLE:
+ ac.chooseSingle = wParam != 0;
+ break;
+
+ case SCI_AUTOCGETCHOOSESINGLE:
+ return ac.chooseSingle;
+
+ case SCI_AUTOCSETIGNORECASE:
+ ac.ignoreCase = wParam != 0;
+ break;
+
+ case SCI_AUTOCGETIGNORECASE:
+ return ac.ignoreCase;
+
+ case SCI_USERLISTSHOW:
+ listType = wParam;
+ AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_AUTOCSETAUTOHIDE:
+ ac.autoHide = wParam != 0;
+ break;
+
+ case SCI_AUTOCGETAUTOHIDE:
+ return ac.autoHide;
+
+ case SCI_AUTOCSETDROPRESTOFWORD:
+ ac.dropRestOfWord = wParam != 0;
+ break;
+
+ 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;
+
+ case SCI_CLEARREGISTEREDIMAGES:
+ ac.lb->ClearRegisteredImages();
+ break;
+
+ case SCI_AUTOCSETTYPESEPARATOR:
+ ac.SetTypesep(static_cast<char>(wParam));
+ break;
+
+ case SCI_AUTOCGETTYPESEPARATOR:
+ return ac.GetTypesep();
+
+ case SCI_CALLTIPSHOW:
+ CallTipShow(LocationFromPosition(wParam),
+ reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_CALLTIPCANCEL:
+ ct.CallTipCancel();
+ break;
+
+ case SCI_CALLTIPACTIVE:
+ return ct.inCallTipMode;
+
+ case SCI_CALLTIPPOSSTART:
+ return ct.posStartCallTip;
+
+ case SCI_CALLTIPSETHLT:
+ ct.SetHighlight(wParam, lParam);
+ break;
+
+ case SCI_CALLTIPSETBACK:
+ ct.colourBG = ColourDesired(wParam);
+ vs.styles[STYLE_CALLTIP].back = ct.colourBG;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_CALLTIPSETFORE:
+ ct.colourUnSel = ColourDesired(wParam);
+ vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel;
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_CALLTIPSETFOREHLT:
+ ct.colourSel = ColourDesired(wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_CALLTIPUSESTYLE:
+ ct.SetTabSize((int)wParam);
+ InvalidateStyleRedraw();
+ break;
+
+ case SCI_USEPOPUP:
+ displayPopupMenu = wParam != 0;
+ break;
+
+#ifdef SCI_LEXER
+ case SCI_SETLEXER:
+ SetLexer(wParam);
+ lexLanguage = wParam;
+ break;
+
+ case SCI_GETLEXER:
+ return lexLanguage;
+
+ case SCI_COLOURISE:
+ if (lexLanguage == SCLEX_CONTAINER) {
+ pdoc->ModifiedAt(wParam);
+ NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
+ } else {
+ Colourise(wParam, lParam);
+ }
+ Redraw();
+ break;
+
+ case SCI_SETPROPERTY:
+ props.Set(reinterpret_cast<const char *>(wParam),
+ reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_GETPROPERTY:
+ return StringResult(lParam, props.Get(reinterpret_cast<const char *>(wParam)));
+
+ case SCI_GETPROPERTYEXPANDED: {
+ char *val = props.Expanded(reinterpret_cast<const char *>(wParam));
+ const int n = strlen(val);
+ if (lParam != 0) {
+ char *ptr = reinterpret_cast<char *>(lParam);
+ strcpy(ptr, val);
+ }
+ delete []val;
+ 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();
+ keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
+ }
+ break;
+
+ case SCI_SETLEXERLANGUAGE:
+ SetLexerLanguage(reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_GETLEXERLANGUAGE:
+ return StringResult(lParam, lexCurrent ? lexCurrent->languageName : "");
+
+ case SCI_GETSTYLEBITSNEEDED:
+ return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
+
+#endif
+
+ default:
+ return Editor::WndProc(iMessage, wParam, lParam);
+ }
+ return 0l;
+}
diff --git a/scintilla/src/ScintillaBase.h b/scintilla/src/ScintillaBase.h
new file mode 100644
index 0000000..9355a08
--- /dev/null
+++ b/scintilla/src/ScintillaBase.h
@@ -0,0 +1,100 @@
+// Scintilla source code edit control
+/** @file ScintillaBase.h
+ ** Defines an enhanced subclass of Editor with calltips, autocomplete and context menu.
+ **/
+// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCINTILLABASE_H
+#define SCINTILLABASE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class ScintillaBase : public Editor {
+ // Private so ScintillaBase objects can not be copied
+ ScintillaBase(const ScintillaBase &);
+ ScintillaBase &operator=(const ScintillaBase &);
+
+protected:
+ /** Enumeration of commands and child windows. */
+ enum {
+ idCallTip=1,
+ idAutoComplete=2,
+
+ idcmdUndo=10,
+ idcmdRedo=11,
+ idcmdCut=12,
+ idcmdCopy=13,
+ idcmdPaste=14,
+ idcmdDelete=15,
+ idcmdSelectAll=16
+ };
+
+ bool displayPopupMenu;
+ Menu popup;
+ AutoComplete ac;
+
+ CallTip ct;
+
+ int listType; ///< 0 is an autocomplete list
+ int maxListWidth; /// Maximum width of list, in average character widths
+
+#ifdef SCI_LEXER
+ bool performingStyle; ///< Prevent reentrance
+ int lexLanguage;
+ const LexerModule *lexCurrent;
+ PropSetSimple props;
+ enum {numWordLists=KEYWORDSET_MAX+1};
+ WordList *keyWordLists[numWordLists+1];
+ void SetLexer(uptr_t wParam);
+ void SetLexerLanguage(const char *languageName);
+ void Colourise(int start, int end);
+#endif
+
+ ScintillaBase();
+ virtual ~ScintillaBase();
+ virtual void Initialise() = 0;
+ virtual void Finalise() = 0;
+
+ virtual void RefreshColourPalette(Palette &pal, bool want);
+
+ virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
+ void Command(int cmdId);
+ virtual void CancelModes();
+ virtual int KeyCommand(unsigned int iMessage);
+
+ void AutoCompleteStart(int lenEntered, const char *list);
+ void AutoCompleteCancel();
+ void AutoCompleteMove(int delta);
+ int AutoCompleteGetCurrent();
+ int AutoCompleteGetCurrentText(char *buffer);
+ void AutoCompleteCharacterAdded(char ch);
+ void AutoCompleteCharacterDeleted();
+ void AutoCompleteCompleted();
+ void AutoCompleteMoveToCurrentWord();
+ static void AutoCompleteDoubleClick(void *p);
+
+ void CallTipClick();
+ void CallTipShow(Point pt, const char *defn);
+ virtual void CreateCallTipWindow(PRectangle rc) = 0;
+
+ virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0;
+ void ContextMenu(Point pt);
+
+ virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+
+ virtual void NotifyStyleToNeeded(int endStyleNeeded);
+public:
+ // Public so scintilla_send_message can use it
+ virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/Selection.cxx b/scintilla/src/Selection.cxx
new file mode 100644
index 0000000..d33bd02
--- /dev/null
+++ b/scintilla/src/Selection.cxx
@@ -0,0 +1,366 @@
+// Scintilla source code edit control
+/** @file Selection.cxx
+ ** Classes maintaining the selection.
+ **/
+// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+
+#include <vector>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+
+#include "Selection.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
+ if (insertion) {
+ if (position > startChange) {
+ position += length;
+ }
+ } else {
+ if (position > startChange) {
+ int endDeletion = startChange + length;
+ if (position > endDeletion) {
+ position -= length;
+ } else {
+ position = startChange;
+ }
+ }
+ }
+}
+
+bool SelectionPosition::operator <(const SelectionPosition &other) const {
+ if (position == other.position)
+ return virtualSpace < other.virtualSpace;
+ else
+ return position < other.position;
+}
+
+bool SelectionPosition::operator >(const SelectionPosition &other) const {
+ if (position == other.position)
+ return virtualSpace > other.virtualSpace;
+ else
+ return position > other.position;
+}
+
+bool SelectionPosition::operator <=(const SelectionPosition &other) const {
+ if (position == other.position && virtualSpace == other.virtualSpace)
+ return true;
+ else
+ return other > *this;
+}
+
+bool SelectionPosition::operator >=(const SelectionPosition &other) const {
+ if (position == other.position && virtualSpace == other.virtualSpace)
+ return true;
+ else
+ return *this > other;
+}
+
+int SelectionRange::Length() const {
+ if (anchor > caret) {
+ return anchor.Position() - caret.Position();
+ } else {
+ return caret.Position() - anchor.Position();
+ }
+}
+
+bool SelectionRange::Contains(int pos) const {
+ if (anchor > caret)
+ return (pos >= caret.Position()) && (pos <= anchor.Position());
+ else
+ return (pos >= anchor.Position()) && (pos <= caret.Position());
+}
+
+bool SelectionRange::Contains(SelectionPosition sp) const {
+ if (anchor > caret)
+ return (sp >= caret) && (sp <= anchor);
+ else
+ return (sp >= anchor) && (sp <= caret);
+}
+
+bool SelectionRange::ContainsCharacter(int posCharacter) const {
+ if (anchor > caret)
+ return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
+ else
+ return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
+}
+
+SelectionSegment SelectionRange::Intersect(SelectionSegment check) const {
+ SelectionSegment inOrder(caret, anchor);
+ if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
+ SelectionSegment portion = check;
+ if (portion.start < inOrder.start)
+ portion.start = inOrder.start;
+ if (portion.end > inOrder.end)
+ portion.end = inOrder.end;
+ if (portion.start > portion.end)
+ return SelectionSegment();
+ else
+ return portion;
+ } else {
+ return SelectionSegment();
+ }
+}
+
+bool SelectionRange::Trim(SelectionRange range) {
+ SelectionPosition startRange = range.Start();
+ SelectionPosition endRange = range.End();
+ SelectionPosition start = Start();
+ SelectionPosition end = End();
+ PLATFORM_ASSERT(start <= end);
+ PLATFORM_ASSERT(startRange <= endRange);
+ if ((startRange <= end) && (endRange >= start)) {
+ if ((start > startRange) && (end < endRange)) {
+ // Completely covered by range -> empty at start
+ end = start;
+ } else if ((start < startRange) && (end > endRange)) {
+ // Completely covers range -> empty at start
+ end = start;
+ } else if (start <= startRange) {
+ // Trim end
+ end = startRange;
+ } else { //
+ PLATFORM_ASSERT(end >= endRange);
+ // Trim start
+ start = endRange;
+ }
+ if (anchor > caret) {
+ caret = start;
+ anchor = end;
+ } else {
+ anchor = start;
+ caret = end;
+ }
+ return Empty();
+ } else {
+ return false;
+ }
+}
+
+// If range is all virtual collapse to start of virtual space
+void SelectionRange::MinimizeVirtualSpace() {
+ if (caret.Position() == anchor.Position()) {
+ int virtualSpace = caret.VirtualSpace();
+ if (virtualSpace > anchor.VirtualSpace())
+ virtualSpace = anchor.VirtualSpace();
+ caret.SetVirtualSpace(virtualSpace);
+ anchor.SetVirtualSpace(virtualSpace);
+ }
+}
+
+Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
+ AddSelection(SelectionPosition(0));
+}
+
+Selection::~Selection() {
+}
+
+bool Selection::IsRectangular() const {
+ return (selType == selRectangle) || (selType == selThin);
+}
+
+int Selection::MainCaret() const {
+ return ranges[mainRange].caret.Position();
+}
+
+int Selection::MainAnchor() const {
+ return ranges[mainRange].anchor.Position();
+}
+
+SelectionRange &Selection::Rectangular() {
+ return rangeRectangular;
+}
+
+SelectionSegment Selection::Limits() const {
+ if (ranges.empty()) {
+ return SelectionSegment();
+ } else {
+ SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
+ for (size_t i=1; i<ranges.size(); i++) {
+ sr.Extend(ranges[i].anchor);
+ sr.Extend(ranges[i].caret);
+ }
+ return sr;
+ }
+}
+
+SelectionSegment Selection::LimitsForRectangularElseMain() const {
+ if (IsRectangular()) {
+ return Limits();
+ } else {
+ return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
+ }
+}
+
+size_t Selection::Count() const {
+ return ranges.size();
+}
+
+size_t Selection::Main() const {
+ return mainRange;
+}
+
+void Selection::SetMain(size_t r) {
+ PLATFORM_ASSERT(r < ranges.size());
+ mainRange = r;
+}
+
+SelectionRange &Selection::Range(size_t r) {
+ return ranges[r];
+}
+
+SelectionRange &Selection::RangeMain() {
+ return ranges[mainRange];
+}
+
+bool Selection::MoveExtends() const {
+ return moveExtends;
+}
+
+void Selection::SetMoveExtends(bool moveExtends_) {
+ moveExtends = moveExtends_;
+}
+
+bool Selection::Empty() const {
+ for (size_t i=0; i<ranges.size(); i++) {
+ if (!ranges[i].Empty())
+ return false;
+ }
+ return true;
+}
+
+SelectionPosition Selection::Last() const {
+ SelectionPosition lastPosition;
+ for (size_t i=0; i<ranges.size(); i++) {
+ if (lastPosition < ranges[i].caret)
+ lastPosition = ranges[i].caret;
+ if (lastPosition < ranges[i].anchor)
+ lastPosition = ranges[i].anchor;
+ }
+ return lastPosition;
+}
+
+int Selection::Length() const {
+ int len = 0;
+ for (size_t i=0; i<ranges.size(); i++) {
+ len += ranges[i].Length();
+ }
+ return len;
+}
+
+void Selection::MovePositions(bool insertion, int startChange, int length) {
+ for (size_t i=0; i<ranges.size(); i++) {
+ ranges[i].caret.MoveForInsertDelete(insertion, startChange, length);
+ ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length);
+ }
+}
+
+void Selection::TrimSelection(SelectionRange range) {
+ for (size_t i=0; i<ranges.size();) {
+ if ((i != mainRange) && (ranges[i].Trim(range))) {
+ // Trimmed to empty so remove
+ for (size_t j=i; j<ranges.size()-1; j++) {
+ ranges[j] = ranges[j+1];
+ if (j == mainRange-1)
+ mainRange--;
+ }
+ ranges.pop_back();
+ } else {
+ i++;
+ }
+ }
+}
+
+void Selection::SetSelection(SelectionRange range) {
+ ranges.clear();
+ ranges.push_back(range);
+ mainRange = ranges.size() - 1;
+}
+
+void Selection::AddSelection(SelectionRange range) {
+ TrimSelection(range);
+ ranges.push_back(range);
+ mainRange = ranges.size() - 1;
+}
+
+void Selection::TentativeSelection(SelectionRange range) {
+ if (!tentativeMain) {
+ rangesSaved = ranges;
+ }
+ ranges = rangesSaved;
+ AddSelection(range);
+ TrimSelection(ranges[mainRange]);
+ tentativeMain = true;
+}
+
+void Selection::CommitTentative() {
+ rangesSaved.clear();
+ tentativeMain = false;
+}
+
+int Selection::CharacterInSelection(int posCharacter) const {
+ for (size_t i=0; i<ranges.size(); i++) {
+ if (ranges[i].ContainsCharacter(posCharacter))
+ return i == mainRange ? 1 : 2;
+ }
+ return 0;
+}
+
+int Selection::InSelectionForEOL(int pos) const {
+ for (size_t i=0; i<ranges.size(); i++) {
+ if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
+ return i == mainRange ? 1 : 2;
+ }
+ return 0;
+}
+
+int Selection::VirtualSpaceFor(int pos) const {
+ int virtualSpace = 0;
+ for (size_t i=0; i<ranges.size(); i++) {
+ if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace()))
+ virtualSpace = ranges[i].caret.VirtualSpace();
+ if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace()))
+ virtualSpace = ranges[i].anchor.VirtualSpace();
+ }
+ return virtualSpace;
+}
+
+void Selection::Clear() {
+ ranges.clear();
+ ranges.push_back(SelectionRange());
+ mainRange = ranges.size() - 1;
+ selType = selStream;
+ moveExtends = false;
+ ranges[mainRange].Reset();
+ rangeRectangular.Reset();
+}
+
+void Selection::RemoveDuplicates() {
+ for (size_t i=0; i<ranges.size()-1; i++) {
+ if (ranges[i].Empty()) {
+ size_t j=i+1;
+ while (j<ranges.size()) {
+ if (ranges[i] == ranges[j]) {
+ ranges.erase(ranges.begin() + j);
+ if (mainRange >= j)
+ mainRange--;
+ } else {
+ j++;
+ }
+ }
+ }
+ }
+}
+
+void Selection::RotateMain() {
+ mainRange = (mainRange + 1) % ranges.size();
+}
+
diff --git a/scintilla/src/Selection.h b/scintilla/src/Selection.h
new file mode 100644
index 0000000..c7f2062
--- /dev/null
+++ b/scintilla/src/Selection.h
@@ -0,0 +1,187 @@
+// Scintilla source code edit control
+/** @file Selection.h
+ ** Classes maintaining the selection.
+ **/
+// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SELECTION_H
+#define SELECTION_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class SelectionPosition {
+ int position;
+ int virtualSpace;
+public:
+ explicit SelectionPosition(int position_=INVALID_POSITION, int virtualSpace_=0) : position(position_), virtualSpace(virtualSpace_) {
+ PLATFORM_ASSERT(virtualSpace < 800000);
+ if (virtualSpace < 0)
+ virtualSpace = 0;
+ }
+ void Reset() {
+ position = 0;
+ virtualSpace = 0;
+ }
+ void MoveForInsertDelete(bool insertion, int startChange, int length);
+ bool operator ==(const SelectionPosition &other) const {
+ return position == other.position && virtualSpace == other.virtualSpace;
+ }
+ bool operator <(const SelectionPosition &other) const;
+ bool operator >(const SelectionPosition &other) const;
+ bool operator <=(const SelectionPosition &other) const;
+ bool operator >=(const SelectionPosition &other) const;
+ int Position() const {
+ return position;
+ }
+ void SetPosition(int position_) {
+ position = position_;
+ virtualSpace = 0;
+ }
+ int VirtualSpace() const {
+ return virtualSpace;
+ }
+ void SetVirtualSpace(int virtualSpace_) {
+ PLATFORM_ASSERT(virtualSpace_ < 800000);
+ if (virtualSpace_ >= 0)
+ virtualSpace = virtualSpace_;
+ }
+ void Add(int increment) {
+ position = position + increment;
+ }
+ bool IsValid() const {
+ return position >= 0;
+ }
+};
+
+// Ordered range to make drawing simpler
+struct SelectionSegment {
+ SelectionPosition start;
+ SelectionPosition end;
+ SelectionSegment() {
+ }
+ SelectionSegment(SelectionPosition a, SelectionPosition b) {
+ if (a < b) {
+ start = a;
+ end = b;
+ } else {
+ start = b;
+ end = a;
+ }
+ }
+ bool Empty() const {
+ return start == end;
+ }
+ void Extend(SelectionPosition p) {
+ if (start > p)
+ start = p;
+ if (end < p)
+ end = p;
+ }
+};
+
+struct SelectionRange {
+ SelectionPosition caret;
+ SelectionPosition anchor;
+
+ SelectionRange() {
+ }
+ SelectionRange(SelectionPosition single) : caret(single), anchor(single) {
+ }
+ SelectionRange(int single) : caret(single), anchor(single) {
+ }
+ SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) {
+ }
+ SelectionRange(int caret_, int anchor_) : caret(caret_), anchor(anchor_) {
+ }
+ bool Empty() const {
+ return anchor == caret;
+ }
+ int Length() const;
+ // int Width() const; // Like Length but takes virtual space into account
+ bool operator ==(const SelectionRange &other) const {
+ return caret == other.caret && anchor == other.anchor;
+ }
+ bool operator <(const SelectionRange &other) const {
+ return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor));
+ }
+ void Reset() {
+ anchor.Reset();
+ caret.Reset();
+ }
+ void ClearVirtualSpace() {
+ anchor.SetVirtualSpace(0);
+ caret.SetVirtualSpace(0);
+ }
+ bool Contains(int pos) const;
+ bool Contains(SelectionPosition sp) const;
+ bool ContainsCharacter(int posCharacter) const;
+ SelectionSegment Intersect(SelectionSegment check) const;
+ SelectionPosition Start() const {
+ return (anchor < caret) ? anchor : caret;
+ }
+ SelectionPosition End() const {
+ return (anchor < caret) ? caret : anchor;
+ }
+ bool Trim(SelectionRange range);
+ // If range is all virtual collapse to start of virtual space
+ void MinimizeVirtualSpace();
+};
+
+class Selection {
+ std::vector<SelectionRange> ranges;
+ std::vector<SelectionRange> rangesSaved;
+ SelectionRange rangeRectangular;
+ size_t mainRange;
+ bool moveExtends;
+ bool tentativeMain;
+public:
+ enum selTypes { noSel, selStream, selRectangle, selLines, selThin };
+ selTypes selType;
+
+ Selection();
+ ~Selection();
+ bool IsRectangular() const;
+ int MainCaret() const;
+ int MainAnchor() const;
+ SelectionRange &Rectangular();
+ SelectionSegment Limits() const;
+ // This is for when you want to move the caret in response to a
+ // user direction command - for rectangular selections, use the range
+ // that covers all selected text otherwise return the main selection.
+ SelectionSegment LimitsForRectangularElseMain() const;
+ size_t Count() const;
+ size_t Main() const;
+ void SetMain(size_t r);
+ SelectionRange &Range(size_t r);
+ SelectionRange &RangeMain();
+ bool MoveExtends() const;
+ void SetMoveExtends(bool moveExtends_);
+ bool Empty() const;
+ SelectionPosition Last() const;
+ int Length() const;
+ void MovePositions(bool insertion, int startChange, int length);
+ void TrimSelection(SelectionRange range);
+ void SetSelection(SelectionRange range);
+ void AddSelection(SelectionRange range);
+ void TentativeSelection(SelectionRange range);
+ void CommitTentative();
+ int CharacterInSelection(int posCharacter) const;
+ int InSelectionForEOL(int pos) const;
+ int VirtualSpaceFor(int pos) const;
+ void Clear();
+ void RemoveDuplicates();
+ void RotateMain();
+ bool Tentative() const { return tentativeMain; }
+ std::vector<SelectionRange> RangesCopy() const {
+ return ranges;
+ }
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/SplitVector.h b/scintilla/src/SplitVector.h
new file mode 100644
index 0000000..306d03e
--- /dev/null
+++ b/scintilla/src/SplitVector.h
@@ -0,0 +1,249 @@
+// Scintilla source code edit control
+/** @file SplitVector.h
+ ** Main data structure for holding arrays that handle insertions
+ ** and deletions efficiently.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SPLITVECTOR_H
+#define SPLITVECTOR_H
+
+template <typename T>
+class SplitVector {
+protected:
+ T *body;
+ int size;
+ int lengthBody;
+ int part1Length;
+ int gapLength; /// invariant: gapLength == size - lengthBody
+ int growSize;
+
+ /// Move the gap to a particular position so that insertion and
+ /// deletion at that point will not require much copying and
+ /// hence be fast.
+ void GapTo(int position) {
+ if (position != part1Length) {
+ if (position < part1Length) {
+ memmove(
+ body + position + gapLength,
+ body + position,
+ sizeof(T) * (part1Length - position));
+ } else { // position > part1Length
+ memmove(
+ body + part1Length,
+ body + part1Length + gapLength,
+ sizeof(T) * (position - part1Length));
+ }
+ part1Length = position;
+ }
+ }
+
+ /// Check that there is room in the buffer for an insertion,
+ /// reallocating if more space needed.
+ void RoomFor(int insertionLength) {
+ if (gapLength <= insertionLength) {
+ while (growSize < size / 6)
+ growSize *= 2;
+ ReAllocate(size + insertionLength + growSize);
+ }
+ }
+
+ void Init() {
+ body = NULL;
+ growSize = 8;
+ size = 0;
+ lengthBody = 0;
+ part1Length = 0;
+ gapLength = 0;
+ }
+
+public:
+ /// Construct a split buffer.
+ SplitVector() {
+ Init();
+ }
+
+ ~SplitVector() {
+ delete []body;
+ body = 0;
+ }
+
+ int GetGrowSize() const {
+ return growSize;
+ }
+
+ void SetGrowSize(int growSize_) {
+ growSize = growSize_;
+ }
+
+ /// Reallocate the storage for the buffer to be newSize and
+ /// copy exisiting contents to the new buffer.
+ /// Must not be used to decrease the size of the buffer.
+ void ReAllocate(int newSize) {
+ if (newSize > size) {
+ // Move the gap to the end
+ GapTo(lengthBody);
+ T *newBody = new T[newSize];
+ if ((size != 0) && (body != 0)) {
+ memmove(newBody, body, sizeof(T) * lengthBody);
+ delete []body;
+ }
+ body = newBody;
+ gapLength += newSize - size;
+ size = newSize;
+ }
+ }
+
+ /// Retrieve the character at a particular position.
+ /// Retrieving positions outside the range of the buffer returns 0.
+ /// The assertions here are disabled since calling code can be
+ /// simpler if out of range access works and returns 0.
+ T ValueAt(int position) const {
+ if (position < part1Length) {
+ //PLATFORM_ASSERT(position >= 0);
+ if (position < 0) {
+ return 0;
+ } else {
+ return body[position];
+ }
+ } else {
+ //PLATFORM_ASSERT(position < lengthBody);
+ if (position >= lengthBody) {
+ return 0;
+ } else {
+ return body[gapLength + position];
+ }
+ }
+ }
+
+ void SetValueAt(int position, T v) {
+ if (position < part1Length) {
+ PLATFORM_ASSERT(position >= 0);
+ if (position < 0) {
+ ;
+ } else {
+ body[position] = v;
+ }
+ } else {
+ PLATFORM_ASSERT(position < lengthBody);
+ if (position >= lengthBody) {
+ ;
+ } else {
+ body[gapLength + position] = v;
+ }
+ }
+ }
+
+ T &operator[](int position) const {
+ PLATFORM_ASSERT(position >= 0 && position < lengthBody);
+ if (position < part1Length) {
+ return body[position];
+ } else {
+ return body[gapLength + position];
+ }
+ }
+
+ /// Retrieve the length of the buffer.
+ int Length() const {
+ return lengthBody;
+ }
+
+ /// Insert a single value into the buffer.
+ /// Inserting at positions outside the current range fails.
+ void Insert(int position, T v) {
+ PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
+ if ((position < 0) || (position > lengthBody)) {
+ return;
+ }
+ RoomFor(1);
+ GapTo(position);
+ body[part1Length] = v;
+ lengthBody++;
+ part1Length++;
+ gapLength--;
+ }
+
+ /// Insert a number of elements into the buffer setting their value.
+ /// Inserting at positions outside the current range fails.
+ void InsertValue(int position, int insertLength, T v) {
+ PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
+ if (insertLength > 0) {
+ if ((position < 0) || (position > lengthBody)) {
+ return;
+ }
+ RoomFor(insertLength);
+ GapTo(position);
+ for (int i = 0; i < insertLength; i++)
+ body[part1Length + i] = v;
+ lengthBody += insertLength;
+ part1Length += insertLength;
+ gapLength -= insertLength;
+ }
+ }
+
+ /// Ensure at least length elements allocated,
+ /// appending zero valued elements if needed.
+ void EnsureLength(int wantedLength) {
+ if (Length() < wantedLength) {
+ InsertValue(Length(), wantedLength - Length(), 0);
+ }
+ }
+
+ /// Insert text into the buffer from an array.
+ void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) {
+ PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody));
+ if (insertLength > 0) {
+ if ((positionToInsert < 0) || (positionToInsert > lengthBody)) {
+ return;
+ }
+ RoomFor(insertLength);
+ GapTo(positionToInsert);
+ memmove(body + part1Length, s + positionFrom, sizeof(T) * insertLength);
+ lengthBody += insertLength;
+ part1Length += insertLength;
+ gapLength -= insertLength;
+ }
+ }
+
+ /// Delete one element from the buffer.
+ void Delete(int position) {
+ PLATFORM_ASSERT((position >= 0) && (position < lengthBody));
+ if ((position < 0) || (position >= lengthBody)) {
+ return;
+ }
+ DeleteRange(position, 1);
+ }
+
+ /// Delete a range from the buffer.
+ /// Deleting positions outside the current range fails.
+ void DeleteRange(int position, int deleteLength) {
+ PLATFORM_ASSERT((position >= 0) && (position + deleteLength <= lengthBody));
+ if ((position < 0) || ((position + deleteLength) > lengthBody)) {
+ return;
+ }
+ if ((position == 0) && (deleteLength == lengthBody)) {
+ // Full deallocation returns storage and is faster
+ delete []body;
+ Init();
+ } else if (deleteLength > 0) {
+ GapTo(position);
+ lengthBody -= deleteLength;
+ gapLength += deleteLength;
+ }
+ }
+
+ /// Delete all the buffer contents.
+ void DeleteAll() {
+ DeleteRange(0, lengthBody);
+ }
+
+ T *BufferPointer() {
+ RoomFor(1);
+ GapTo(lengthBody);
+ body[lengthBody] = 0;
+ return body;
+ }
+};
+
+#endif
diff --git a/scintilla/src/Style.cxx b/scintilla/src/Style.cxx
new file mode 100644
index 0000000..f1f91c1
--- /dev/null
+++ b/scintilla/src/Style.cxx
@@ -0,0 +1,165 @@
+// Scintilla source code edit control
+/** @file Style.cxx
+ ** Defines the font and colour style for a class of text.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "Style.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+Style::Style() {
+ aliasOfDefaultFont = true;
+ Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
+ Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
+ false, false, false, false, caseMixed, true, true, false);
+}
+
+Style::Style(const Style &source) {
+ Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
+ 0, 0, 0,
+ false, false, false, false, caseMixed, true, true, false);
+ fore.desired = source.fore.desired;
+ back.desired = source.back.desired;
+ characterSet = source.characterSet;
+ bold = source.bold;
+ italic = source.italic;
+ size = source.size;
+ eolFilled = source.eolFilled;
+ underline = source.underline;
+ caseForce = source.caseForce;
+ visible = source.visible;
+ changeable = source.changeable;
+ hotspot = source.hotspot;
+}
+
+Style::~Style() {
+ if (aliasOfDefaultFont)
+ font.SetID(0);
+ else
+ font.Release();
+ aliasOfDefaultFont = false;
+}
+
+Style &Style::operator=(const Style &source) {
+ if (this == &source)
+ return * this;
+ Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
+ 0, 0, SC_CHARSET_DEFAULT,
+ false, false, false, false, caseMixed, true, true, false);
+ fore.desired = source.fore.desired;
+ back.desired = source.back.desired;
+ characterSet = source.characterSet;
+ bold = source.bold;
+ italic = source.italic;
+ size = source.size;
+ eolFilled = source.eolFilled;
+ underline = source.underline;
+ caseForce = source.caseForce;
+ visible = source.visible;
+ changeable = source.changeable;
+ return *this;
+}
+
+void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
+ const char *fontName_, int characterSet_,
+ bool bold_, bool italic_, bool eolFilled_,
+ bool underline_, ecaseForced caseForce_,
+ bool visible_, bool changeable_, bool hotspot_) {
+ fore.desired = fore_;
+ back.desired = back_;
+ characterSet = characterSet_;
+ bold = bold_;
+ italic = italic_;
+ size = size_;
+ fontName = fontName_;
+ eolFilled = eolFilled_;
+ underline = underline_;
+ caseForce = caseForce_;
+ visible = visible_;
+ changeable = changeable_;
+ hotspot = hotspot_;
+ if (aliasOfDefaultFont)
+ font.SetID(0);
+ else
+ font.Release();
+ aliasOfDefaultFont = false;
+ sizeZoomed = 2;
+ lineHeight = 2;
+ ascent = 1;
+ descent = 1;
+ externalLeading = 0;
+ aveCharWidth = 1;
+ spaceWidth = 1;
+}
+
+void Style::ClearTo(const Style &source) {
+ Clear(
+ source.fore.desired,
+ source.back.desired,
+ source.size,
+ source.fontName,
+ source.characterSet,
+ source.bold,
+ source.italic,
+ source.eolFilled,
+ source.underline,
+ source.caseForce,
+ source.visible,
+ source.changeable,
+ source.hotspot);
+}
+
+bool Style::EquivalentFontTo(const Style *other) const {
+ if (bold != other->bold ||
+ italic != other->italic ||
+ size != other->size ||
+ characterSet != other->characterSet)
+ return false;
+ if (fontName == other->fontName)
+ return true;
+ if (!fontName)
+ return false;
+ if (!other->fontName)
+ return false;
+ return strcmp(fontName, other->fontName) == 0;
+}
+
+void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle, int extraFontFlag) {
+ sizeZoomed = size + zoomLevel;
+ if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2;
+
+ if (aliasOfDefaultFont)
+ font.SetID(0);
+ else
+ font.Release();
+ int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
+ aliasOfDefaultFont = defaultStyle &&
+ (EquivalentFontTo(defaultStyle) || !fontName);
+ if (aliasOfDefaultFont) {
+ font.SetID(defaultStyle->font.GetID());
+ } else if (fontName) {
+ font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
+ } else {
+ font.SetID(0);
+ }
+
+ ascent = surface.Ascent(font);
+ descent = surface.Descent(font);
+ // Probably more typographically correct to include leading
+ // but that means more complex drawing as leading must be erased
+ //lineHeight = surface.ExternalLeading() + surface.Height();
+ externalLeading = surface.ExternalLeading(font);
+ lineHeight = surface.Height(font);
+ aveCharWidth = surface.AverageCharWidth(font);
+ spaceWidth = surface.WidthChar(font, ' ');
+}
diff --git a/scintilla/src/Style.h b/scintilla/src/Style.h
new file mode 100644
index 0000000..c7e8879
--- /dev/null
+++ b/scintilla/src/Style.h
@@ -0,0 +1,64 @@
+// Scintilla source code edit control
+/** @file Style.h
+ ** Defines the font and colour style for a class of text.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef STYLE_H
+#define STYLE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class Style {
+public:
+ ColourPair fore;
+ ColourPair back;
+ bool aliasOfDefaultFont;
+ bool bold;
+ bool italic;
+ int size;
+ const char *fontName;
+ int characterSet;
+ bool eolFilled;
+ bool underline;
+ enum ecaseForced {caseMixed, caseUpper, caseLower};
+ ecaseForced caseForce;
+ bool visible;
+ bool changeable;
+ bool hotspot;
+
+ Font font;
+ int sizeZoomed;
+ unsigned int lineHeight;
+ unsigned int ascent;
+ unsigned int descent;
+ unsigned int externalLeading;
+ unsigned int aveCharWidth;
+ unsigned int spaceWidth;
+
+ Style();
+ Style(const Style &source);
+ ~Style();
+ Style &operator=(const Style &source);
+ void Clear(ColourDesired fore_, ColourDesired back_,
+ int size_,
+ const char *fontName_, int characterSet_,
+ bool bold_, bool italic_, bool eolFilled_,
+ bool underline_, ecaseForced caseForce_,
+ bool visible_, bool changeable_, bool hotspot_);
+ void ClearTo(const Style &source);
+ bool EquivalentFontTo(const Style *other) const;
+ void Realise(Surface &surface, int zoomLevel, Style *defaultStyle = 0, int extraFontFlag = 0);
+ bool IsProtected() const { return !(changeable && visible);}
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/StyleContext.cxx b/scintilla/src/StyleContext.cxx
new file mode 100644
index 0000000..6c99dbd
--- /dev/null
+++ b/scintilla/src/StyleContext.cxx
@@ -0,0 +1,55 @@
+// Scintilla source code edit control
+/** @file StyleContext.cxx
+ ** Lexer infrastructure.
+ **/
+// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// This file is in the public domain.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static void getRange(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = styler[start + i];
+ i++;
+ }
+ s[i] = '\0';
+}
+
+void StyleContext::GetCurrent(char *s, unsigned int len) {
+ getRange(styler.GetStartSegment(), currentPos - 1, styler, s, len);
+}
+
+static void getRangeLowered(unsigned int start,
+ unsigned int end,
+ Accessor &styler,
+ char *s,
+ unsigned int len) {
+ unsigned int i = 0;
+ while ((i < end - start + 1) && (i < len-1)) {
+ s[i] = static_cast<char>(tolower(styler[start + i]));
+ i++;
+ }
+ s[i] = '\0';
+}
+
+void StyleContext::GetCurrentLowered(char *s, unsigned int len) {
+ getRangeLowered(styler.GetStartSegment(), currentPos - 1, styler, s, len);
+}
diff --git a/scintilla/src/StyleContext.h b/scintilla/src/StyleContext.h
new file mode 100644
index 0000000..0bb89d0
--- /dev/null
+++ b/scintilla/src/StyleContext.h
@@ -0,0 +1,177 @@
+// Scintilla source code edit control
+/** @file StyleContext.cxx
+ ** Lexer infrastructure.
+ **/
+// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// This file is in the public domain.
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+// All languages handled so far can treat all characters >= 0x80 as one class
+// which just continues the current token or starts an identifier if in default.
+// DBCS treated specially as the second character can be < 0x80 and hence
+// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
+class StyleContext {
+ Accessor &styler;
+ unsigned int endPos;
+ StyleContext &operator=(const StyleContext &);
+ void GetNextChar(unsigned int pos) {
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1));
+ if (styler.IsLeadByte(static_cast<char>(chNext))) {
+ chNext = chNext << 8;
+ chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2));
+ }
+ // End of line?
+ // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win)
+ // or on LF alone (Unix). Avoid triggering two times on Dos/Win.
+ atLineEnd = (ch == '\r' && chNext != '\n') ||
+ (ch == '\n') ||
+ (currentPos >= endPos);
+ }
+
+public:
+ unsigned int currentPos;
+ bool atLineStart;
+ bool atLineEnd;
+ int state;
+ int chPrev;
+ int ch;
+ int chNext;
+
+ StyleContext(unsigned int startPos, unsigned int length,
+ int initStyle, Accessor &styler_, char chMask=31) :
+ styler(styler_),
+ endPos(startPos + length),
+ currentPos(startPos),
+ atLineStart(true),
+ atLineEnd(false),
+ state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
+ chPrev(0),
+ ch(0),
+ chNext(0) {
+ styler.StartAt(startPos, chMask);
+ styler.StartSegment(startPos);
+ unsigned int pos = currentPos;
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
+ if (styler.IsLeadByte(static_cast<char>(ch))) {
+ pos++;
+ ch = ch << 8;
+ ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos));
+ }
+ GetNextChar(pos);
+ }
+ void Complete() {
+ styler.ColourTo(currentPos - 1, state);
+ }
+ bool More() const {
+ return currentPos < endPos;
+ }
+ void Forward() {
+ if (currentPos < endPos) {
+ atLineStart = atLineEnd;
+ chPrev = ch;
+ currentPos++;
+ if (ch >= 0x100)
+ currentPos++;
+ ch = chNext;
+ GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
+ } else {
+ atLineStart = false;
+ chPrev = ' ';
+ ch = ' ';
+ chNext = ' ';
+ atLineEnd = true;
+ }
+ }
+ void Forward(int nb) {
+ for (int i = 0; i < nb; i++) {
+ Forward();
+ }
+ }
+ void ChangeState(int state_) {
+ state = state_;
+ }
+ void SetState(int state_) {
+ styler.ColourTo(currentPos - 1, state);
+ state = state_;
+ }
+ void ForwardSetState(int state_) {
+ Forward();
+ styler.ColourTo(currentPos - 1, state);
+ state = state_;
+ }
+ int LengthCurrent() {
+ return currentPos - styler.GetStartSegment();
+ }
+ int GetRelative(int n) {
+ return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
+ }
+ bool Match(char ch0) const {
+ return ch == static_cast<unsigned char>(ch0);
+ }
+ bool Match(char ch0, char ch1) const {
+ return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1));
+ }
+ bool Match(const char *s) {
+ if (ch != static_cast<unsigned char>(*s))
+ return false;
+ s++;
+ if (!*s)
+ return true;
+ if (chNext != static_cast<unsigned char>(*s))
+ return false;
+ s++;
+ for (int n=2; *s; n++) {
+ if (*s != styler.SafeGetCharAt(currentPos+n))
+ return false;
+ s++;
+ }
+ return true;
+ }
+ bool MatchIgnoreCase(const char *s) {
+ if (tolower(ch) != static_cast<unsigned char>(*s))
+ return false;
+ s++;
+ if (tolower(chNext) != static_cast<unsigned char>(*s))
+ return false;
+ s++;
+ for (int n=2; *s; n++) {
+ if (static_cast<unsigned char>(*s) !=
+ tolower(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
+ return false;
+ s++;
+ }
+ return true;
+ }
+ // Non-inline
+ void GetCurrent(char *s, unsigned int len);
+ void GetCurrentLowered(char *s, unsigned int len);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+inline bool IsASpace(unsigned int ch) {
+ return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+inline bool IsASpaceOrTab(unsigned int ch) {
+ return (ch == ' ') || (ch == '\t');
+}
+
+inline bool IsADigit(unsigned int ch) {
+ return (ch >= '0') && (ch <= '9');
+}
+
+inline bool IsADigit(unsigned int ch, unsigned int base) {
+ if (base <= 10) {
+ return (ch >= '0') && (ch < '0' + base);
+ } else {
+ return ((ch >= '0') && (ch <= '9')) ||
+ ((ch >= 'A') && (ch < 'A' + base - 10)) ||
+ ((ch >= 'a') && (ch < 'a' + base - 10));
+ }
+}
diff --git a/scintilla/src/UniConversion.cxx b/scintilla/src/UniConversion.cxx
new file mode 100644
index 0000000..e965c58
--- /dev/null
+++ b/scintilla/src/UniConversion.cxx
@@ -0,0 +1,131 @@
+// Scintilla source code edit control
+/** @file UniConversion.cxx
+ ** Functions to handle UTF-8 and UTF-16 strings.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+
+#include "UniConversion.h"
+
+enum { SURROGATE_LEAD_FIRST = 0xD800 };
+enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
+enum { SURROGATE_TRAIL_LAST = 0xDFFF };
+
+unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) {
+ unsigned int len = 0;
+ for (unsigned int i = 0; i < tlen && uptr[i];) {
+ unsigned int uch = uptr[i];
+ if (uch < 0x80) {
+ len++;
+ } else if (uch < 0x800) {
+ len += 2;
+ } else if ((uch >= SURROGATE_LEAD_FIRST) &&
+ (uch <= SURROGATE_TRAIL_LAST)) {
+ len += 4;
+ i++;
+ } else {
+ len += 3;
+ }
+ i++;
+ }
+ return len;
+}
+
+void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) {
+ int k = 0;
+ for (unsigned int i = 0; i < tlen && uptr[i];) {
+ unsigned int uch = uptr[i];
+ if (uch < 0x80) {
+ putf[k++] = static_cast<char>(uch);
+ } else if (uch < 0x800) {
+ putf[k++] = static_cast<char>(0xC0 | (uch >> 6));
+ putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
+ } else if ((uch >= SURROGATE_LEAD_FIRST) &&
+ (uch <= SURROGATE_TRAIL_LAST)) {
+ // Half a surrogate pair
+ i++;
+ unsigned int xch = 0x10000 + ((uch & 0x3ff) << 10) + (uptr[i] & 0x3ff);
+ putf[k++] = static_cast<char>(0xF0 | (xch >> 18));
+ putf[k++] = static_cast<char>(0x80 | ((xch >> 12) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | ((xch >> 6) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | (xch & 0x3f));
+ } else {
+ putf[k++] = static_cast<char>(0xE0 | (uch >> 12));
+ putf[k++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ i++;
+ }
+ putf[len] = '\0';
+}
+
+unsigned int UTF8CharLength(unsigned char ch) {
+ if (ch < 0x80) {
+ return 1;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ return 2;
+ } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
+ return 3;
+ } else {
+ return 4;
+ }
+}
+
+unsigned int UTF16Length(const char *s, unsigned int len) {
+ unsigned int ulen = 0;
+ unsigned int charLen;
+ for (unsigned int i=0; i<len;) {
+ unsigned char ch = static_cast<unsigned char>(s[i]);
+ if (ch < 0x80) {
+ charLen = 1;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ charLen = 2;
+ } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
+ charLen = 3;
+ } else {
+ charLen = 4;
+ ulen++;
+ }
+ i += charLen;
+ ulen++;
+ }
+ return ulen;
+}
+
+unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) {
+ unsigned int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ unsigned int i=0;
+ while ((i<len) && (ui<tlen)) {
+ unsigned char ch = us[i++];
+ if (ch < 0x80) {
+ tbuf[ui] = ch;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ tbuf[ui] = static_cast<wchar_t>((ch & 0x1F) << 6);
+ ch = us[i++];
+ tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
+ } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
+ tbuf[ui] = static_cast<wchar_t>((ch & 0xF) << 12);
+ ch = us[i++];
+ tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + ((ch & 0x7F) << 6));
+ ch = us[i++];
+ tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
+ } else {
+ // Outside the BMP so need two surrogates
+ int val = (ch & 0x7) << 18;
+ ch = us[i++];
+ val += (ch & 0x3F) << 12;
+ ch = us[i++];
+ val += (ch & 0x3F) << 6;
+ ch = us[i++];
+ val += (ch & 0x3F);
+ tbuf[ui] = static_cast<wchar_t>(((val - 0x10000) >> 10) + SURROGATE_LEAD_FIRST);
+ ui++;
+ tbuf[ui] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST);
+ }
+ ui++;
+ }
+ return ui;
+}
diff --git a/scintilla/src/UniConversion.h b/scintilla/src/UniConversion.h
new file mode 100644
index 0000000..222e55f
--- /dev/null
+++ b/scintilla/src/UniConversion.h
@@ -0,0 +1,13 @@
+// Scintilla source code edit control
+/** @file UniConversion.h
+ ** Functions to handle UTF-8 and UTF-16 strings.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
+void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
+unsigned int UTF8CharLength(unsigned char ch);
+unsigned int UTF16Length(const char *s, unsigned int len);
+unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);
+
diff --git a/scintilla/src/ViewStyle.cxx b/scintilla/src/ViewStyle.cxx
new file mode 100644
index 0000000..bdeac90
--- /dev/null
+++ b/scintilla/src/ViewStyle.cxx
@@ -0,0 +1,389 @@
+// Scintilla source code edit control
+/** @file ViewStyle.cxx
+ ** Store information on how the document is to be viewed.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+MarginStyle::MarginStyle() :
+ style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false) {
+}
+
+// A list of the fontnames - avoids wasting space in each style
+FontNames::FontNames() {
+ size = 8;
+ names = new char *[size];
+ max = 0;
+}
+
+FontNames::~FontNames() {
+ Clear();
+ delete []names;
+ names = 0;
+}
+
+void FontNames::Clear() {
+ for (int i=0; i<max; i++) {
+ delete []names[i];
+ }
+ max = 0;
+}
+
+const char *FontNames::Save(const char *name) {
+ if (!name)
+ return 0;
+ for (int i=0; i<max; i++) {
+ if (strcmp(names[i], name) == 0) {
+ return names[i];
+ }
+ }
+ if (max >= size) {
+ // Grow array
+ int sizeNew = size * 2;
+ char **namesNew = new char *[sizeNew];
+ for (int j=0; j<max; j++) {
+ namesNew[j] = names[j];
+ }
+ delete []names;
+ names = namesNew;
+ size = sizeNew;
+ }
+ names[max] = new char[strlen(name) + 1];
+ strcpy(names[max], name);
+ max++;
+ return names[max-1];
+}
+
+ViewStyle::ViewStyle() {
+ Init();
+}
+
+ViewStyle::ViewStyle(const ViewStyle &source) {
+ Init(source.stylesSize);
+ for (unsigned int sty=0; sty<source.stylesSize; sty++) {
+ styles[sty] = source.styles[sty];
+ // Can't just copy fontname as its lifetime is relative to its owning ViewStyle
+ styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
+ }
+ for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
+ markers[mrk] = source.markers[mrk];
+ }
+ for (int ind=0; ind<=INDIC_MAX; ind++) {
+ indicators[ind] = source.indicators[ind];
+ }
+
+ selforeset = source.selforeset;
+ selforeground.desired = source.selforeground.desired;
+ selAdditionalForeground.desired = source.selAdditionalForeground.desired;
+ selbackset = source.selbackset;
+ selbackground.desired = source.selbackground.desired;
+ selAdditionalBackground.desired = source.selAdditionalBackground.desired;
+ selbackground2.desired = source.selbackground2.desired;
+ selAlpha = source.selAlpha;
+ selAdditionalAlpha = source.selAdditionalAlpha;
+ selEOLFilled = source.selEOLFilled;
+
+ foldmarginColourSet = source.foldmarginColourSet;
+ foldmarginColour.desired = source.foldmarginColour.desired;
+ foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
+ foldmarginHighlightColour.desired = source.foldmarginHighlightColour.desired;
+
+ hotspotForegroundSet = source.hotspotForegroundSet;
+ hotspotForeground.desired = source.hotspotForeground.desired;
+ hotspotBackgroundSet = source.hotspotBackgroundSet;
+ hotspotBackground.desired = source.hotspotBackground.desired;
+ hotspotUnderline = source.hotspotUnderline;
+ hotspotSingleLine = source.hotspotSingleLine;
+
+ whitespaceForegroundSet = source.whitespaceForegroundSet;
+ whitespaceForeground.desired = source.whitespaceForeground.desired;
+ whitespaceBackgroundSet = source.whitespaceBackgroundSet;
+ whitespaceBackground.desired = source.whitespaceBackground.desired;
+ selbar.desired = source.selbar.desired;
+ selbarlight.desired = source.selbarlight.desired;
+ caretcolour.desired = source.caretcolour.desired;
+ additionalCaretColour.desired = source.additionalCaretColour.desired;
+ showCaretLineBackground = source.showCaretLineBackground;
+ caretLineBackground.desired = source.caretLineBackground.desired;
+ caretLineAlpha = source.caretLineAlpha;
+ edgecolour.desired = source.edgecolour.desired;
+ edgeState = source.edgeState;
+ caretStyle = source.caretStyle;
+ caretWidth = source.caretWidth;
+ someStylesProtected = false;
+ leftMarginWidth = source.leftMarginWidth;
+ rightMarginWidth = source.rightMarginWidth;
+ for (int i=0; i < margins; i++) {
+ ms[i] = source.ms[i];
+ }
+ symbolMargin = source.symbolMargin;
+ maskInLine = source.maskInLine;
+ fixedColumnWidth = source.fixedColumnWidth;
+ zoomLevel = source.zoomLevel;
+ viewWhitespace = source.viewWhitespace;
+ whitespaceSize = source.whitespaceSize;
+ viewIndentationGuides = source.viewIndentationGuides;
+ viewEOL = source.viewEOL;
+ showMarkedLines = source.showMarkedLines;
+ extraFontFlag = source.extraFontFlag;
+ extraAscent = source.extraAscent;
+ extraDescent = source.extraDescent;
+ marginStyleOffset = source.marginStyleOffset;
+ annotationVisible = source.annotationVisible;
+ annotationStyleOffset = source.annotationStyleOffset;
+}
+
+ViewStyle::~ViewStyle() {
+ delete []styles;
+ styles = NULL;
+}
+
+void ViewStyle::Init(size_t stylesSize_) {
+ stylesSize = 0;
+ styles = NULL;
+ AllocStyles(stylesSize_);
+ fontNames.Clear();
+ ResetDefaultStyle();
+
+ indicators[0].style = INDIC_SQUIGGLE;
+ indicators[0].under = false;
+ indicators[0].fore = ColourDesired(0, 0x7f, 0);
+ indicators[1].style = INDIC_TT;
+ indicators[1].under = false;
+ indicators[1].fore = ColourDesired(0, 0, 0xff);
+ indicators[2].style = INDIC_PLAIN;
+ indicators[2].under = false;
+ indicators[2].fore = ColourDesired(0xff, 0, 0);
+
+ lineHeight = 1;
+ maxAscent = 1;
+ maxDescent = 1;
+ aveCharWidth = 8;
+ spaceWidth = 8;
+
+ selforeset = false;
+ selforeground.desired = ColourDesired(0xff, 0, 0);
+ selAdditionalForeground.desired = ColourDesired(0xff, 0, 0);
+ selbackset = true;
+ selbackground.desired = ColourDesired(0xc0, 0xc0, 0xc0);
+ selAdditionalBackground.desired = ColourDesired(0xd7, 0xd7, 0xd7);
+ selbackground2.desired = ColourDesired(0xb0, 0xb0, 0xb0);
+ selAlpha = SC_ALPHA_NOALPHA;
+ selAdditionalAlpha = SC_ALPHA_NOALPHA;
+ selEOLFilled = false;
+
+ foldmarginColourSet = false;
+ foldmarginColour.desired = ColourDesired(0xff, 0, 0);
+ foldmarginHighlightColourSet = false;
+ foldmarginHighlightColour.desired = ColourDesired(0xc0, 0xc0, 0xc0);
+
+ whitespaceForegroundSet = false;
+ whitespaceForeground.desired = ColourDesired(0, 0, 0);
+ whitespaceBackgroundSet = false;
+ whitespaceBackground.desired = ColourDesired(0xff, 0xff, 0xff);
+ selbar.desired = Platform::Chrome();
+ selbarlight.desired = Platform::ChromeHighlight();
+ styles[STYLE_LINENUMBER].fore.desired = ColourDesired(0, 0, 0);
+ styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+ caretcolour.desired = ColourDesired(0, 0, 0);
+ additionalCaretColour.desired = ColourDesired(0x7f, 0x7f, 0x7f);
+ showCaretLineBackground = false;
+ caretLineBackground.desired = ColourDesired(0xff, 0xff, 0);
+ caretLineAlpha = SC_ALPHA_NOALPHA;
+ edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0);
+ edgeState = EDGE_NONE;
+ caretStyle = CARETSTYLE_LINE;
+ caretWidth = 1;
+ someStylesProtected = false;
+
+ hotspotForegroundSet = false;
+ hotspotForeground.desired = ColourDesired(0, 0, 0xff);
+ hotspotBackgroundSet = false;
+ hotspotBackground.desired = ColourDesired(0xff, 0xff, 0xff);
+ hotspotUnderline = true;
+ hotspotSingleLine = true;
+
+ leftMarginWidth = 1;
+ rightMarginWidth = 1;
+ ms[0].style = SC_MARGIN_NUMBER;
+ ms[0].width = 0;
+ ms[0].mask = 0;
+ ms[1].style = SC_MARGIN_SYMBOL;
+ ms[1].width = 16;
+ ms[1].mask = ~SC_MASK_FOLDERS;
+ ms[2].style = SC_MARGIN_SYMBOL;
+ ms[2].width = 0;
+ ms[2].mask = 0;
+ fixedColumnWidth = leftMarginWidth;
+ symbolMargin = false;
+ maskInLine = 0xffffffff;
+ for (int margin=0; margin < margins; margin++) {
+ fixedColumnWidth += ms[margin].width;
+ symbolMargin = symbolMargin || (ms[margin].style != SC_MARGIN_NUMBER);
+ if (ms[margin].width > 0)
+ maskInLine &= ~ms[margin].mask;
+ }
+ zoomLevel = 0;
+ viewWhitespace = wsInvisible;
+ whitespaceSize = 1;
+ viewIndentationGuides = ivNone;
+ viewEOL = false;
+ showMarkedLines = true;
+ extraFontFlag = 0;
+ extraAscent = 0;
+ extraDescent = 0;
+ marginStyleOffset = 0;
+ annotationVisible = ANNOTATION_HIDDEN;
+ annotationStyleOffset = 0;
+}
+
+void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
+ unsigned int i;
+ for (i=0; i<stylesSize; i++) {
+ pal.WantFind(styles[i].fore, want);
+ pal.WantFind(styles[i].back, want);
+ }
+ for (i=0; i<(sizeof(indicators)/sizeof(indicators[0])); i++) {
+ pal.WantFind(indicators[i].fore, want);
+ }
+ for (i=0; i<(sizeof(markers)/sizeof(markers[0])); i++) {
+ markers[i].RefreshColourPalette(pal, want);
+ }
+ pal.WantFind(selforeground, want);
+ pal.WantFind(selAdditionalForeground, want);
+ pal.WantFind(selbackground, want);
+ pal.WantFind(selAdditionalBackground, want);
+ pal.WantFind(selbackground2, want);
+
+ pal.WantFind(foldmarginColour, want);
+ pal.WantFind(foldmarginHighlightColour, want);
+
+ pal.WantFind(whitespaceForeground, want);
+ pal.WantFind(whitespaceBackground, want);
+ pal.WantFind(selbar, want);
+ pal.WantFind(selbarlight, want);
+ pal.WantFind(caretcolour, want);
+ pal.WantFind(additionalCaretColour, want);
+ pal.WantFind(caretLineBackground, want);
+ pal.WantFind(edgecolour, want);
+ pal.WantFind(hotspotForeground, want);
+ pal.WantFind(hotspotBackground, want);
+}
+
+void ViewStyle::Refresh(Surface &surface) {
+ selbar.desired = Platform::Chrome();
+ selbarlight.desired = Platform::ChromeHighlight();
+ styles[STYLE_DEFAULT].Realise(surface, zoomLevel, NULL, extraFontFlag);
+ maxAscent = styles[STYLE_DEFAULT].ascent;
+ maxDescent = styles[STYLE_DEFAULT].descent;
+ someStylesProtected = false;
+ for (unsigned int i=0; i<stylesSize; i++) {
+ if (i != STYLE_DEFAULT) {
+ styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag);
+ if (maxAscent < styles[i].ascent)
+ maxAscent = styles[i].ascent;
+ if (maxDescent < styles[i].descent)
+ maxDescent = styles[i].descent;
+ }
+ if (styles[i].IsProtected()) {
+ someStylesProtected = true;
+ }
+ }
+ maxAscent += extraAscent;
+ maxDescent += extraDescent;
+
+ lineHeight = maxAscent + maxDescent;
+ aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
+ spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
+
+ fixedColumnWidth = leftMarginWidth;
+ symbolMargin = false;
+ maskInLine = 0xffffffff;
+ for (int margin=0; margin < margins; margin++) {
+ fixedColumnWidth += ms[margin].width;
+ symbolMargin = symbolMargin || (ms[margin].style != SC_MARGIN_NUMBER);
+ if (ms[margin].width > 0)
+ maskInLine &= ~ms[margin].mask;
+ }
+}
+
+void ViewStyle::AllocStyles(size_t sizeNew) {
+ Style *stylesNew = new Style[sizeNew];
+ size_t i=0;
+ for (; i<stylesSize; i++) {
+ stylesNew[i] = styles[i];
+ stylesNew[i].fontName = styles[i].fontName;
+ }
+ if (stylesSize > STYLE_DEFAULT) {
+ for (; i<sizeNew; i++) {
+ if (i != STYLE_DEFAULT) {
+ stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
+ }
+ }
+ }
+ delete []styles;
+ styles = stylesNew;
+ stylesSize = sizeNew;
+}
+
+void ViewStyle::EnsureStyle(size_t index) {
+ if (index >= stylesSize) {
+ size_t sizeNew = stylesSize * 2;
+ while (sizeNew <= index)
+ sizeNew *= 2;
+ AllocStyles(sizeNew);
+ }
+}
+
+void ViewStyle::ResetDefaultStyle() {
+ styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
+ ColourDesired(0xff,0xff,0xff),
+ Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
+ SC_CHARSET_DEFAULT,
+ false, false, false, false, Style::caseMixed, true, true, false);
+}
+
+void ViewStyle::ClearStyles() {
+ // Reset all styles to be like the default style
+ for (unsigned int i=0; i<stylesSize; i++) {
+ if (i != STYLE_DEFAULT) {
+ styles[i].ClearTo(styles[STYLE_DEFAULT]);
+ }
+ }
+ styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+
+ // Set call tip fore/back to match the values previously set for call tips
+ styles[STYLE_CALLTIP].back.desired = ColourDesired(0xff, 0xff, 0xff);
+ styles[STYLE_CALLTIP].fore.desired = ColourDesired(0x80, 0x80, 0x80);
+}
+
+void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
+ styles[styleIndex].fontName = fontNames.Save(name);
+}
+
+bool ViewStyle::ProtectionActive() const {
+ return someStylesProtected;
+}
+
+bool ViewStyle::ValidStyle(size_t styleIndex) const {
+ return styleIndex < stylesSize;
+}
+
diff --git a/scintilla/src/ViewStyle.h b/scintilla/src/ViewStyle.h
new file mode 100644
index 0000000..1282c44
--- /dev/null
+++ b/scintilla/src/ViewStyle.h
@@ -0,0 +1,135 @@
+// Scintilla source code edit control
+/** @file ViewStyle.h
+ ** Store information on how the document is to be viewed.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef VIEWSTYLE_H
+#define VIEWSTYLE_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ */
+class MarginStyle {
+public:
+ int style;
+ int width;
+ int mask;
+ bool sensitive;
+ MarginStyle();
+};
+
+/**
+ */
+class FontNames {
+private:
+ char **names;
+ int size;
+ int max;
+
+public:
+ FontNames();
+ ~FontNames();
+ void Clear();
+ const char *Save(const char *name);
+};
+
+enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
+
+enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
+
+/**
+ */
+class ViewStyle {
+public:
+ FontNames fontNames;
+ size_t stylesSize;
+ Style *styles;
+ LineMarker markers[MARKER_MAX + 1];
+ Indicator indicators[INDIC_MAX + 1];
+ int lineHeight;
+ unsigned int maxAscent;
+ unsigned int maxDescent;
+ unsigned int aveCharWidth;
+ unsigned int spaceWidth;
+ bool selforeset;
+ ColourPair selforeground;
+ ColourPair selAdditionalForeground;
+ bool selbackset;
+ ColourPair selbackground;
+ ColourPair selAdditionalBackground;
+ ColourPair selbackground2;
+ int selAlpha;
+ int selAdditionalAlpha;
+ bool selEOLFilled;
+ bool whitespaceForegroundSet;
+ ColourPair whitespaceForeground;
+ bool whitespaceBackgroundSet;
+ ColourPair whitespaceBackground;
+ ColourPair selbar;
+ ColourPair selbarlight;
+ bool foldmarginColourSet;
+ ColourPair foldmarginColour;
+ bool foldmarginHighlightColourSet;
+ ColourPair foldmarginHighlightColour;
+ bool hotspotForegroundSet;
+ ColourPair hotspotForeground;
+ bool hotspotBackgroundSet;
+ ColourPair hotspotBackground;
+ bool hotspotUnderline;
+ bool hotspotSingleLine;
+ /// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
+ enum { margins=5 };
+ int leftMarginWidth; ///< Spacing margin on left of text
+ int rightMarginWidth; ///< Spacing margin on left of text
+ bool symbolMargin;
+ int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
+ MarginStyle ms[margins];
+ int fixedColumnWidth;
+ int zoomLevel;
+ WhiteSpaceVisibility viewWhitespace;
+ int whitespaceSize;
+ IndentView viewIndentationGuides;
+ bool viewEOL;
+ bool showMarkedLines;
+ ColourPair caretcolour;
+ ColourPair additionalCaretColour;
+ bool showCaretLineBackground;
+ ColourPair caretLineBackground;
+ int caretLineAlpha;
+ ColourPair edgecolour;
+ int edgeState;
+ int caretStyle;
+ int caretWidth;
+ bool someStylesProtected;
+ int extraFontFlag;
+ int extraAscent;
+ int extraDescent;
+ int marginStyleOffset;
+ int annotationVisible;
+ int annotationStyleOffset;
+
+ ViewStyle();
+ ViewStyle(const ViewStyle &source);
+ ~ViewStyle();
+ void Init(size_t stylesSize_=64);
+ void RefreshColourPalette(Palette &pal, bool want);
+ void Refresh(Surface &surface);
+ void AllocStyles(size_t sizeNew);
+ void EnsureStyle(size_t index);
+ void ResetDefaultStyle();
+ void ClearStyles();
+ void SetStyleFontName(int styleIndex, const char *name);
+ bool ProtectionActive() const;
+ bool ValidStyle(size_t styleIndex) const;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/src/WindowAccessor.cxx b/scintilla/src/WindowAccessor.cxx
new file mode 100644
index 0000000..cfe057d
--- /dev/null
+++ b/scintilla/src/WindowAccessor.cxx
@@ -0,0 +1,191 @@
+// Scintilla source code edit control
+/** @file WindowAccessor.cxx
+ ** Rapid easy access to contents of a Scintilla.
+ **/
+// Copyright 1998-2001 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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "WindowAccessor.h"
+#include "Scintilla.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+WindowAccessor::~WindowAccessor() {
+}
+
+bool WindowAccessor::InternalIsLeadByte(char ch) {
+ if (SC_CP_UTF8 == codePage)
+ // For lexing, all characters >= 0x80 are treated the
+ // same so none is considered a lead byte.
+ return false;
+ else
+ return Platform::IsDBCSLeadByte(codePage, ch);
+}
+
+void WindowAccessor::Fill(int position) {
+ if (lenDoc == -1)
+ lenDoc = Platform::SendScintilla(id, SCI_GETTEXTLENGTH, 0, 0);
+ startPos = position - slopSize;
+ if (startPos + bufferSize > lenDoc)
+ startPos = lenDoc - bufferSize;
+ if (startPos < 0)
+ startPos = 0;
+ endPos = startPos + bufferSize;
+ if (endPos > lenDoc)
+ endPos = lenDoc;
+
+ Sci_TextRange tr = {{startPos, endPos}, buf};
+ Platform::SendScintillaPointer(id, SCI_GETTEXTRANGE, 0, &tr);
+}
+
+bool WindowAccessor::Match(int pos, const char *s) {
+ for (int i=0; *s; i++) {
+ if (*s != SafeGetCharAt(pos+i))
+ return false;
+ s++;
+ }
+ return true;
+}
+
+char WindowAccessor::StyleAt(int position) {
+ return static_cast<char>(Platform::SendScintilla(
+ id, SCI_GETSTYLEAT, position, 0));
+}
+
+int WindowAccessor::GetLine(int position) {
+ return Platform::SendScintilla(id, SCI_LINEFROMPOSITION, position, 0);
+}
+
+int WindowAccessor::LineStart(int line) {
+ return Platform::SendScintilla(id, SCI_POSITIONFROMLINE, line, 0);
+}
+
+int WindowAccessor::LevelAt(int line) {
+ return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0);
+}
+
+int WindowAccessor::Length() {
+ if (lenDoc == -1)
+ lenDoc = Platform::SendScintilla(id, SCI_GETTEXTLENGTH, 0, 0);
+ return lenDoc;
+}
+
+int WindowAccessor::GetLineState(int line) {
+ return Platform::SendScintilla(id, SCI_GETLINESTATE, line);
+}
+
+int WindowAccessor::SetLineState(int line, int state) {
+ return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state);
+}
+
+void WindowAccessor::StartAt(unsigned int start, char chMask) {
+ Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask);
+}
+
+void WindowAccessor::StartSegment(unsigned int pos) {
+ startSeg = pos;
+}
+
+void WindowAccessor::ColourTo(unsigned int pos, int chAttr) {
+ // Only perform styling if non empty range
+ if (pos != startSeg - 1) {
+ if (pos < startSeg) {
+ Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos);
+ }
+
+ if (validLen + (pos - startSeg + 1) >= bufferSize)
+ Flush();
+ if (validLen + (pos - startSeg + 1) >= bufferSize) {
+ // Too big for buffer so send directly
+ Platform::SendScintilla(id, SCI_SETSTYLING, pos - startSeg + 1, chAttr);
+ } else {
+ if (chAttr != chWhile)
+ chFlags = 0;
+ chAttr |= chFlags;
+ for (unsigned int i = startSeg; i <= pos; i++) {
+ styleBuf[validLen++] = static_cast<char>(chAttr);
+ }
+ }
+ }
+ startSeg = pos+1;
+}
+
+void WindowAccessor::SetLevel(int line, int level) {
+ Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level);
+}
+
+void WindowAccessor::Flush() {
+ startPos = extremePosition;
+ lenDoc = -1;
+ if (validLen > 0) {
+ Platform::SendScintillaPointer(id, SCI_SETSTYLINGEX, validLen,
+ styleBuf);
+ validLen = 0;
+ }
+}
+
+int WindowAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
+ int end = Length();
+ int spaceFlags = 0;
+
+ // Determines the indentation level of the current line and also checks for consistent
+ // indentation compared to the previous line.
+ // Indentation is judged consistent when the indentation whitespace of each line lines
+ // the same or the indentation of one line is a prefix of the other.
+
+ int pos = LineStart(line);
+ char ch = (*this)[pos];
+ int indent = 0;
+ bool inPrevPrefix = line > 0;
+ int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
+ while ((ch == ' ' || ch == '\t') && (pos < end)) {
+ if (inPrevPrefix) {
+ char chPrev = (*this)[posPrev++];
+ if (chPrev == ' ' || chPrev == '\t') {
+ if (chPrev != ch)
+ spaceFlags |= wsInconsistent;
+ } else {
+ inPrevPrefix = false;
+ }
+ }
+ if (ch == ' ') {
+ spaceFlags |= wsSpace;
+ indent++;
+ } else { // Tab
+ spaceFlags |= wsTab;
+ if (spaceFlags & wsSpace)
+ spaceFlags |= wsSpaceTab;
+ indent = (indent / 8 + 1) * 8;
+ }
+ ch = (*this)[++pos];
+ }
+
+ *flags = spaceFlags;
+ indent += SC_FOLDLEVELBASE;
+ // if completely empty line or the start of a comment...
+ if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)))
+ return indent | SC_FOLDLEVELWHITEFLAG;
+ else
+ return indent;
+}
+
+void WindowAccessor::IndicatorFill(int start, int end, int indicator, int value) {
+ Platform::SendScintilla(id, SCI_SETINDICATORCURRENT, indicator);
+ if (value) {
+ Platform::SendScintilla(id, SCI_SETINDICATORVALUE, value);
+ Platform::SendScintilla(id, SCI_INDICATORFILLRANGE, start, end - start);
+ } else {
+ Platform::SendScintilla(id, SCI_INDICATORCLEARRANGE, start, end - start);
+ }
+}
diff --git a/scintilla/src/XPM.cxx b/scintilla/src/XPM.cxx
new file mode 100644
index 0000000..97d1f80
--- /dev/null
+++ b/scintilla/src/XPM.cxx
@@ -0,0 +1,326 @@
+// Scintilla source code edit control
+/** @file XPM.cxx
+ ** Define a class that holds data in the X Pixmap (XPM) format.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "Platform.h"
+
+#include "XPM.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static const char *NextField(const char *s) {
+ // In case there are leading spaces in the string
+ while (*s && *s == ' ') {
+ s++;
+ }
+ while (*s && *s != ' ') {
+ s++;
+ }
+ while (*s && *s == ' ') {
+ s++;
+ }
+ return s;
+}
+
+// Data lines in XPM can be terminated either with NUL or "
+static size_t MeasureLength(const char *s) {
+ size_t i = 0;
+ while (s[i] && (s[i] != '\"'))
+ i++;
+ return i;
+}
+
+ColourAllocated XPM::ColourFromCode(int ch) const {
+ return colourCodeTable[ch]->allocated;
+#ifdef SLOW
+ for (int i=0; i<nColours; i++) {
+ if (codes[i] == ch) {
+ return colours[i].allocated;
+ }
+ }
+ return colours[0].allocated;
+#endif
+}
+
+void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) {
+ if ((code != codeTransparent) && (startX != x)) {
+ PRectangle rc(startX, y, x, y+1);
+ surface->FillRectangle(rc, ColourFromCode(code));
+ }
+}
+
+XPM::XPM(const char *textForm) :
+ data(0), codes(0), colours(0), lines(0) {
+ Init(textForm);
+}
+
+XPM::XPM(const char *const *linesForm) :
+ data(0), codes(0), colours(0), lines(0) {
+ Init(linesForm);
+}
+
+XPM::~XPM() {
+ Clear();
+}
+
+void XPM::Init(const char *textForm) {
+ Clear();
+ // Test done is two parts to avoid possibility of overstepping the memory
+ // if memcmp implemented strangely. Must be 4 bytes at least at destination.
+ if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
+ // Build the lines form out of the text form
+ const char **linesForm = LinesFormFromTextForm(textForm);
+ if (linesForm != 0) {
+ Init(linesForm);
+ delete []linesForm;
+ }
+ } else {
+ // It is really in line form
+ Init(reinterpret_cast<const char * const *>(textForm));
+ }
+}
+
+void XPM::Init(const char *const *linesForm) {
+ Clear();
+ height = 1;
+ width = 1;
+ nColours = 1;
+ data = NULL;
+ codeTransparent = ' ';
+ codes = NULL;
+ colours = NULL;
+ lines = NULL;
+ if (!linesForm)
+ return;
+
+ const char *line0 = linesForm[0];
+ width = atoi(line0);
+ line0 = NextField(line0);
+ 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];
+
+ int strings = 1+height+nColours;
+ lines = new char *[strings];
+ size_t allocation = 0;
+ for (int i=0; i<strings; i++) {
+ allocation += MeasureLength(linesForm[i]) + 1;
+ }
+ data = new char[allocation];
+ char *nextBit = data;
+ for (int j=0; j<strings; j++) {
+ lines[j] = nextBit;
+ size_t len = MeasureLength(linesForm[j]);
+ memcpy(nextBit, linesForm[j], len);
+ nextBit += len;
+ *nextBit++ = '\0';
+ }
+
+ for (int code=0; code<256; code++) {
+ colourCodeTable[code] = 0;
+ }
+
+ for (int c=0; c<nColours; c++) {
+ const char *colourDef = linesForm[c+1];
+ codes[c] = colourDef[0];
+ colourDef += 4;
+ if (*colourDef == '#') {
+ colours[c].desired.Set(colourDef);
+ } else {
+ colours[c].desired = ColourDesired(0xff, 0xff, 0xff);
+ codeTransparent = codes[c];
+ }
+ colourCodeTable[static_cast<unsigned char>(codes[c])] = &(colours[c]);
+ }
+}
+
+void XPM::Clear() {
+ delete []data;
+ data = 0;
+ delete []codes;
+ codes = 0;
+ delete []colours;
+ colours = 0;
+ delete []lines;
+ lines = 0;
+}
+
+void XPM::RefreshColourPalette(Palette &pal, bool want) {
+ if (!data || !codes || !colours || !lines) {
+ return;
+ }
+ for (int i=0; i<nColours; i++) {
+ pal.WantFind(colours[i], want);
+ }
+}
+
+void XPM::CopyDesiredColours() {
+ if (!data || !codes || !colours || !lines) {
+ return;
+ }
+ for (int i=0; i<nColours; i++) {
+ colours[i].Copy();
+ }
+}
+
+void XPM::Draw(Surface *surface, PRectangle &rc) {
+ if (!data || !codes || !colours || !lines) {
+ return;
+ }
+ // Centre the pixmap
+ int startY = rc.top + (rc.Height() - height) / 2;
+ int startX = rc.left + (rc.Width() - width) / 2;
+ for (int y=0; y<height; y++) {
+ int prevCode = 0;
+ int xStartRun = 0;
+ for (int x=0; x<width; x++) {
+ int code = lines[y+nColours+1][x];
+ if (code != prevCode) {
+ FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x);
+ xStartRun = x;
+ prevCode = code;
+ }
+ }
+ FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + width);
+ }
+}
+
+const char **XPM::LinesFormFromTextForm(const char *textForm) {
+ // Build the lines form out of the text form
+ const char **linesForm = 0;
+ int countQuotes = 0;
+ int strings=1;
+ int j=0;
+ for (; countQuotes < (2*strings) && textForm[j] != '\0'; j++) {
+ if (textForm[j] == '\"') {
+ if (countQuotes == 0) {
+ // First field: width, height, number of colors, chars per pixel
+ const char *line0 = textForm + j + 1;
+ // Skip width
+ line0 = NextField(line0);
+ // Add 1 line for each pixel of height
+ strings += atoi(line0);
+ line0 = NextField(line0);
+ // Add 1 line for each colour
+ strings += atoi(line0);
+ linesForm = new const char *[strings];
+ if (linesForm == 0) {
+ break; // Memory error!
+ }
+ }
+ if (countQuotes / 2 >= strings) {
+ break; // Bad height or number of colors!
+ }
+ if ((countQuotes & 1) == 0) {
+ linesForm[countQuotes / 2] = textForm + j + 1;
+ }
+ countQuotes++;
+ }
+ }
+ if (textForm[j] == '\0' || countQuotes / 2 > strings) {
+ // Malformed XPM! Height + number of colors too high or too low
+ delete []linesForm;
+ linesForm = 0;
+ }
+ return linesForm;
+}
+
+// In future, may want to minimize search time by sorting and using a binary search.
+
+XPMSet::XPMSet() : set(0), len(0), maximum(0), height(-1), width(-1) {
+}
+
+XPMSet::~XPMSet() {
+ Clear();
+}
+
+void XPMSet::Clear() {
+ for (int i = 0; i < len; i++) {
+ delete set[i];
+ }
+ delete []set;
+ set = 0;
+ len = 0;
+ maximum = 0;
+ height = -1;
+ width = -1;
+}
+
+void XPMSet::Add(int id, const char *textForm) {
+ // Invalidate cached dimensions
+ height = -1;
+ width = -1;
+
+ // Replace if this id already present
+ for (int i = 0; i < len; i++) {
+ if (set[i]->GetId() == id) {
+ set[i]->Init(textForm);
+ set[i]->CopyDesiredColours();
+ return;
+ }
+ }
+
+ // Not present, so add to end
+ XPM *pxpm = new XPM(textForm);
+ if (pxpm) {
+ pxpm->SetId(id);
+ pxpm->CopyDesiredColours();
+ if (len == maximum) {
+ maximum += 64;
+ XPM **setNew = new XPM *[maximum];
+ for (int i = 0; i < len; i++) {
+ setNew[i] = set[i];
+ }
+ delete []set;
+ set = setNew;
+ }
+ set[len] = pxpm;
+ len++;
+ }
+}
+
+XPM *XPMSet::Get(int id) {
+ for (int i = 0; i < len; i++) {
+ if (set[i]->GetId() == id) {
+ return set[i];
+ }
+ }
+ return 0;
+}
+
+int XPMSet::GetHeight() {
+ if (height < 0) {
+ for (int i = 0; i < len; i++) {
+ if (height < set[i]->GetHeight()) {
+ height = set[i]->GetHeight();
+ }
+ }
+ }
+ return (height > 0) ? height : 0;
+}
+
+int XPMSet::GetWidth() {
+ if (width < 0) {
+ for (int i = 0; i < len; i++) {
+ if (width < set[i]->GetWidth()) {
+ width = set[i]->GetWidth();
+ }
+ }
+ }
+ return (width > 0) ? width : 0;
+}
diff --git a/scintilla/src/XPM.h b/scintilla/src/XPM.h
new file mode 100644
index 0000000..dbeab0b
--- /dev/null
+++ b/scintilla/src/XPM.h
@@ -0,0 +1,80 @@
+// Scintilla source code edit control
+/** @file XPM.h
+ ** Define a class that holds data in the X Pixmap (XPM) format.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef XPM_H
+#define XPM_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+ * Hold a pixmap in XPM format.
+ */
+class XPM {
+ int pid; // Assigned by container
+ int height;
+ int width;
+ int nColours;
+ char *data;
+ char codeTransparent;
+ char *codes;
+ ColourPair *colours;
+ ColourAllocated ColourFromCode(int ch) const;
+ void FillRun(Surface *surface, int code, int startX, int y, int x);
+ char **lines;
+ ColourPair *colourCodeTable[256];
+public:
+ XPM(const char *textForm);
+ XPM(const char *const *linesForm);
+ ~XPM();
+ void Init(const char *textForm);
+ void Init(const char *const *linesForm);
+ void Clear();
+ /// Similar to same named method in ViewStyle:
+ void RefreshColourPalette(Palette &pal, bool want);
+ /// No palette used, so just copy the desired colours to the allocated colours
+ void CopyDesiredColours();
+ /// Decompose image into runs and use FillRectangle for each run
+ void Draw(Surface *surface, PRectangle &rc);
+ char **InLinesForm() { return lines; }
+ void SetId(int pid_) { pid = pid_; }
+ int GetId() const { return pid; }
+ int GetHeight() const { return height; }
+ int GetWidth() const { return width; }
+ static const char **LinesFormFromTextForm(const char *textForm);
+};
+
+/**
+ * A collection of pixmaps indexed by integer id.
+ */
+class XPMSet {
+ XPM **set; ///< The stored XPMs.
+ int len; ///< Current number of XPMs.
+ int maximum; ///< Current maximum number of XPMs, increased by steps if reached.
+ int height; ///< Memorize largest height of the set.
+ int width; ///< Memorize largest width of the set.
+public:
+ XPMSet();
+ ~XPMSet();
+ /// Remove all XPMs.
+ void Clear();
+ /// Add a XPM.
+ void Add(int id, const char *textForm);
+ /// Get XPM by id.
+ XPM *Get(int id);
+ /// Give the largest height of the set.
+ int GetHeight();
+ /// Give the largest width of the set.
+ int GetWidth();
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/scintilla/test/MessageNumbers.py b/scintilla/test/MessageNumbers.py
new file mode 100644
index 0000000..ef1c6fb
--- /dev/null
+++ b/scintilla/test/MessageNumbers.py
@@ -0,0 +1,63 @@
+# List many windows message numbers
+
+msgs = {
+"WM_ACTIVATE":6,
+"WM_ACTIVATEAPP":28,
+"WM_CAPTURECHANGED":533,
+"WM_CHAR":258,
+"WM_CLOSE":16,
+"WM_CREATE":1,
+"WM_COMMAND":273,
+"WM_DESTROY":2,
+"WM_ENTERSIZEMOVE":561,
+"WM_ERASEBKGND":20,
+"WM_EXITSIZEMOVE":562,
+"WM_GETMINMAXINFO":36,
+"WM_GETTEXT":13,
+"WM_IME_SETCONTEXT":0x0281,
+"WM_IME_NOTIFY":0x0282,
+"WM_KEYDOWN":256,
+"WM_KEYUP":257,
+"WM_KILLFOCUS":8,
+"WM_LBUTTONDOWN":513,
+"WM_LBUTTONUP":514,
+"WM_MBUTTONDOWN":519,
+"WM_MBUTTONUP":520,
+"WM_MBUTTONDBLCLK":521,
+"WM_MOUSEACTIVATE":33,
+"WM_MOUSEMOVE":512,
+"WM_MOVE":3,
+"WM_MOVING":534,
+"WM_NCACTIVATE":134,
+"WM_NCCALCSIZE":131,
+"WM_NCCREATE":129,
+"WM_NCDESTROY":130,
+"WM_NCHITTEST":132,
+"WM_NCLBUTTONDBLCLK":163,
+"WM_NCLBUTTONDOWN":161,
+"WM_NCLBUTTONUP":162,
+"WM_NCMOUSEMOVE":160,
+"WM_NCPAINT":133,
+"WM_PAINT":15,
+"WM_PARENTNOTIFY":528,
+"WM_SETCURSOR":32,
+"WM_SETFOCUS":7,
+"WM_SETFONT":48,
+"WM_SETTEXT":12,
+"WM_SHOWWINDOW":24,
+"WM_SIZE":5,
+"WM_SIZING":532,
+"WM_SYNCPAINT":136,
+"WM_SYSCOMMAND":274,
+"WM_SYSKEYDOWN":260,
+"WM_TIMER":275,
+"WM_USER":1024,
+"WM_USER+1":1025,
+"WM_WINDOWPOSCHANGED":71,
+"WM_WINDOWPOSCHANGING":70,
+}
+
+sgsm={}
+for k,v in msgs.items():
+ sgsm[v] = k
+
diff --git a/scintilla/test/README b/scintilla/test/README
new file mode 100644
index 0000000..98e720f
--- /dev/null
+++ b/scintilla/test/README
@@ -0,0 +1,31 @@
+The test directory contains some unit and performance tests for Scintilla.
+
+The tests can only be run on Windows using Python 3.x. Running on another platform
+would require writing a file similar to XiteWin.py for that platform. Python 3.x is required
+because its default string type is Unicode and earlier Python versions use byte strings
+and the interface to the platform assumes a particular string type.
+
+A test application is in xite.py and this can be run to experiment:
+pythonw xite.py
+
+To run the basic tests:
+pythonw simpleTests.py
+
+There are some lexing tests with simple input files in several languages in the examples
+subdirectory and their expected lexed states in *.styled where the start of each style
+is marked with {styleNumber}, for example:
+{15}<%@{16}language=javas{15}%>{0}
+
+To run the lexing tests:
+pythonw lexTests.py
+
+To check for performance regressions:
+pythonw performanceTests.py
+While each test run will be different and the timer has only limited granularity, some results
+from a 2 GHz Athlon with a DEBUG build are:
+ 0.187 testAddLine
+. 0.203 testAddLineMiddle
+. 0.171 testHuge
+. 0.203 testHugeInserts
+. 0.312 testHugeReplace
+.
diff --git a/scintilla/test/XiteMenu.py b/scintilla/test/XiteMenu.py
new file mode 100644
index 0000000..66fe77c
--- /dev/null
+++ b/scintilla/test/XiteMenu.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+""" Define the menu structure used by the Pentacle applications """
+
+MenuStructure = [
+ ["&File", [
+ ["&New", "<control>N"],
+ ["&Open...", "<control>O"],
+ ["&Save", "<control>S"],
+ ["Save &As...", "<control><shift>S"],
+ ["Test", ""],
+ ["Exercised", ""],
+ ["Uncalled", ""],
+ ["-", ""],
+ ["&Exit", ""]]],
+ [ "&Edit", [
+ ["&Undo", "<control>Z"],
+ ["&Redo", "<control>Y"],
+ ["-", ""],
+ ["Cu&t", "<control>X"],
+ ["&Copy", "<control>C"],
+ ["&Paste", "<control>V"],
+ ["&Delete", "Del"],
+ ["Select &All", "<control>A"],
+ ]],
+]
diff --git a/scintilla/test/XiteWin.py b/scintilla/test/XiteWin.py
new file mode 100644
index 0000000..d1ce819
--- /dev/null
+++ b/scintilla/test/XiteWin.py
@@ -0,0 +1,651 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import os, sys, unittest
+
+import ctypes
+from ctypes import wintypes
+from ctypes import c_int, c_ulong, c_char_p, c_wchar_p, c_ushort
+user32=ctypes.windll.user32
+gdi32=ctypes.windll.gdi32
+kernel32=ctypes.windll.kernel32
+from MessageNumbers import msgs, sgsm
+
+import XiteMenu
+
+scintillaDirectory = ".."
+scintillaIncludeDirectory = os.path.join(scintillaDirectory, "include")
+sys.path.append(scintillaIncludeDirectory)
+import Face
+
+scintillaBinDirectory = os.path.join(scintillaDirectory, "bin")
+os.environ['PATH'] = os.environ['PATH'] + ";" + scintillaBinDirectory
+#print(os.environ['PATH'])
+
+WFUNC = ctypes.WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
+
+WS_CHILD = 0x40000000
+WS_CLIPCHILDREN = 0x2000000
+WS_OVERLAPPEDWINDOW = 0xcf0000
+WS_VISIBLE = 0x10000000
+WS_HSCROLL = 0x100000
+WS_VSCROLL = 0x200000
+WA_INACTIVE = 0
+MF_POPUP = 16
+MF_SEPARATOR = 0x800
+IDYES = 6
+OFN_HIDEREADONLY = 4
+MB_OK = 0
+MB_YESNOCANCEL = 3
+MF_CHECKED = 8
+MF_UNCHECKED = 0
+SW_SHOW = 5
+PM_REMOVE = 1
+
+VK_SHIFT = 16
+VK_CONTROL = 17
+VK_MENU = 18
+
+class OPENFILENAME(ctypes.Structure):
+ _fields_ = (("lStructSize", c_int),
+ ("hwndOwner", c_int),
+ ("hInstance", c_int),
+ ("lpstrFilter", c_wchar_p),
+ ("lpstrCustomFilter", c_char_p),
+ ("nMaxCustFilter", c_int),
+ ("nFilterIndex", c_int),
+ ("lpstrFile", c_wchar_p),
+ ("nMaxFile", c_int),
+ ("lpstrFileTitle", c_wchar_p),
+ ("nMaxFileTitle", c_int),
+ ("lpstrInitialDir", c_wchar_p),
+ ("lpstrTitle", c_wchar_p),
+ ("flags", c_int),
+ ("nFileOffset", c_ushort),
+ ("nFileExtension", c_ushort),
+ ("lpstrDefExt", c_char_p),
+ ("lCustData", c_int),
+ ("lpfnHook", c_char_p),
+ ("lpTemplateName", c_char_p),
+ ("pvReserved", c_char_p),
+ ("dwReserved", c_int),
+ ("flagsEx", c_int))
+
+ def __init__(self, win, title):
+ ctypes.Structure.__init__(self)
+ self.lStructSize = ctypes.sizeof(OPENFILENAME)
+ self.nMaxFile = 1024
+ self.hwndOwner = win
+ self.lpstrTitle = title
+ self.Flags = OFN_HIDEREADONLY
+
+trace = False
+#~ trace = True
+
+def WindowSize(w):
+ rc = ctypes.wintypes.RECT()
+ user32.GetClientRect(w, ctypes.byref(rc))
+ return rc.right - rc.left, rc.bottom - rc.top
+
+def IsKeyDown(key):
+ return (user32.GetKeyState(key) & 0x8000) != 0
+
+def KeyTranslate(w):
+ tr = { 9: "Tab", 0xD:"Enter", 0x1B: "Esc" }
+ if w in tr:
+ return tr[w]
+ elif ord("A") <= w <= ord("Z"):
+ return chr(w)
+ elif 0x70 <= w <= 0x7b:
+ return "F" + str(w-0x70+1)
+ else:
+ return "Unknown_" + hex(w)
+
+class WNDCLASS(ctypes.Structure):
+ _fields_= (\
+ ('style', c_int),
+ ('lpfnWndProc', WFUNC),
+ ('cls_extra', c_int),
+ ('wnd_extra', c_int),
+ ('hInst', c_int),
+ ('hIcon', c_int),
+ ('hCursor', c_int),
+ ('hbrBackground', c_int),
+ ('menu_name', c_wchar_p),
+ ('lpzClassName', c_wchar_p),
+ )
+
+class XTEXTRANGE(ctypes.Structure):
+ _fields_= (\
+ ('cpMin', c_int),
+ ('cpMax', c_int),
+ ('lpstrText', c_char_p),
+ )
+
+class TEXTRANGE(ctypes.Structure):
+ _fields_= (\
+ ('cpMin', c_int),
+ ('cpMax', c_int),
+ ('lpstrText', ctypes.POINTER(ctypes.c_char)),
+ )
+
+class FINDTEXT(ctypes.Structure):
+ _fields_= (\
+ ('cpMin', c_int),
+ ('cpMax', c_int),
+ ('lpstrText', c_char_p),
+ ('cpMinText', c_int),
+ ('cpMaxText', c_int),
+ )
+
+hinst = ctypes.windll.kernel32.GetModuleHandleW(0)
+
+def RegisterClass(name, func, background = 0):
+ # register a window class for toplevel windows.
+ wc = WNDCLASS()
+ wc.style = 0
+ wc.lpfnWndProc = func
+ wc.cls_extra = 0
+ wc.wnd_extra = 0
+ wc.hInst = hinst
+ wc.hIcon = 0
+ wc.hCursor = 0
+ wc.hbrBackground = background
+ wc.menu_name = 0
+ wc.lpzClassName = name
+ user32.RegisterClassW(ctypes.byref(wc))
+
+class SciCall:
+ def __init__(self, fn, ptr, msg):
+ self._fn = fn
+ self._ptr = ptr
+ self._msg = msg
+ def __call__(self, w=0, l=0):
+ return self._fn(self._ptr, self._msg, w, l)
+
+class Scintilla:
+ def __init__(self, face, hwndParent, hinstance):
+ self.__dict__["face"] = face
+ self.__dict__["used"] = set()
+ self.__dict__["all"] = set()
+ # The k member is for accessing constants as a dictionary
+ self.__dict__["k"] = {}
+ for f in face.features:
+ self.all.add(f)
+ if face.features[f]["FeatureType"] == "val":
+ self.k[f] = int(self.face.features[f]["Value"], 0)
+ elif face.features[f]["FeatureType"] == "evt":
+ self.k["SCN_"+f] = int(self.face.features[f]["Value"], 0)
+ # Get the function first as that also loads the DLL
+ self.__dict__["_scifn"] = ctypes.windll.SciLexer.Scintilla_DirectFunction
+ self.__dict__["_hwnd"] = user32.CreateWindowExW(0,
+ "Scintilla", "Source",
+ WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,
+ 0, 0, 100, 100, hwndParent, 0, hinstance, 0)
+ self.__dict__["_sciptr"] = user32.SendMessageW(self._hwnd,
+ int(self.face.features["GetDirectPointer"]["Value"], 0), 0,0)
+ user32.ShowWindow(self._hwnd, SW_SHOW)
+ def __getattr__(self, name):
+ if name in self.face.features:
+ self.used.add(name)
+ feature = self.face.features[name]
+ value = int(feature["Value"], 0)
+ #~ print("Feature", name, feature)
+ if feature["FeatureType"] == "val":
+ self.__dict__[name] = value
+ return value
+ else:
+ return SciCall(self._scifn, self._sciptr, value)
+ elif ("Get" + name) in self.face.features:
+ self.used.add("Get" + name)
+ feature = self.face.features["Get" + name]
+ value = int(feature["Value"], 0)
+ if feature["FeatureType"] == "get" and \
+ not name.startswith("Get") and \
+ not feature["Param1Type"] and \
+ not feature["Param2Type"] and \
+ feature["ReturnType"] in ["bool", "int", "position"]:
+ #~ print("property", feature)
+ return self._scifn(self._sciptr, value, 0, 0)
+ elif name.startswith("SCN_") and name in self.k:
+ self.used.add(name)
+ feature = self.face.features[name[4:]]
+ value = int(feature["Value"], 0)
+ #~ print("Feature", name, feature)
+ if feature["FeatureType"] == "val":
+ return value
+ raise AttributeError(name)
+ def __setattr__(self, name, val):
+ if ("Set" + name) in self.face.features:
+ self.used.add("Set" + name)
+ feature = self.face.features["Set" + name]
+ value = int(feature["Value"], 0)
+ #~ print("setproperty", feature)
+ if feature["FeatureType"] == "set" and not name.startswith("Set"):
+ if feature["Param1Type"] in ["bool", "int", "position"]:
+ return self._scifn(self._sciptr, value, val, 0)
+ elif feature["Param2Type"] in ["string"]:
+ return self._scifn(self._sciptr, value, 0, val)
+ raise AttributeError(name)
+ raise AttributeError(name)
+ def getvalue(self, name):
+ if name in self.face.features:
+ feature = self.face.features[name]
+ if feature["FeatureType"] != "evt":
+ try:
+ return int(feature["Value"], 0)
+ except ValueError:
+ return -1
+ return -1
+
+
+ def ByteRange(self, start, end):
+ tr = TEXTRANGE()
+ tr.cpMin = start
+ tr.cpMax = end
+ length = end - start
+ tr.lpstrText = ctypes.create_string_buffer(length + 1)
+ self.GetTextRange(0, ctypes.byref(tr))
+ text = tr.lpstrText[:length]
+ text += b"\0" * (length - len(text))
+ return text
+ def StyledTextRange(self, start, end):
+ tr = TEXTRANGE()
+ tr.cpMin = start
+ tr.cpMax = end
+ length = 2 * (end - start)
+ tr.lpstrText = ctypes.create_string_buffer(length + 2)
+ self.GetStyledText(0, ctypes.byref(tr))
+ styledText = tr.lpstrText[:length]
+ styledText += b"\0" * (length - len(styledText))
+ return styledText
+ def FindBytes(self, start, end, s, flags):
+ ft = FINDTEXT()
+ ft.cpMin = start
+ ft.cpMax = end
+ ft.lpstrText = s
+ ft.cpMinText = 0
+ ft.cpMaxText = 0
+ pos = self.FindText(flags, ctypes.byref(ft))
+ #~ print(start, end, ft.cpMinText, ft.cpMaxText)
+ return pos
+
+ def Contents(self):
+ return self.ByteRange(0, self.Length)
+ def SizeTo(self, width, height):
+ user32.SetWindowPos(self._hwnd, 0, 0, 0, width, height, 0)
+ def FocusOn(self):
+ user32.SetFocus(self._hwnd)
+
+class XiteWin():
+ def __init__(self, test=""):
+ self.face = Face.Face()
+ self.face.ReadFromFile(os.path.join(scintillaIncludeDirectory, "Scintilla.iface"))
+
+ self.titleDirty = True
+ self.fullPath = ""
+ self.test = test
+
+ self.appName = "xite"
+
+ self.cmds = {}
+ self.windowName = "XiteWindow"
+ self.wfunc = WFUNC(self.WndProc)
+ RegisterClass(self.windowName, self.wfunc)
+ user32.CreateWindowExW(0, self.windowName, self.appName, \
+ WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, \
+ 0, 0, 500, 700, 0, 0, hinst, 0)
+
+ args = sys.argv[1:]
+ self.SetMenus()
+ if args:
+ self.GrabFile(args[0])
+ self.ed.FocusOn()
+ self.ed.GotoPos(self.ed.Length)
+
+ print(self.test)
+ if self.test:
+ for k in self.cmds:
+ if self.cmds[k] == "Test":
+ user32.PostMessageW(self.win, msgs["WM_COMMAND"], k, 0)
+
+ def OnSize(self):
+ width, height = WindowSize(self.win)
+ self.ed.SizeTo(width, height)
+ user32.InvalidateRect(self.win, 0, 0)
+
+ def OnCreate(self, hwnd):
+ self.win = hwnd
+ self.ed = Scintilla(self.face, hwnd, hinst)
+ self.ed.FocusOn()
+
+
+ def Invalidate(self):
+ user32.InvalidateRect(self.win, 0, 0)
+
+ def WndProc(self, h, m, w, l):
+ ms = sgsm.get(m, "XXX")
+ if trace:
+ print("%s %s %s %s" % (hex(h)[2:],ms,w,l))
+ if ms == "WM_CLOSE":
+ user32.PostQuitMessage(0)
+ elif ms == "WM_CREATE":
+ self.OnCreate(h)
+ return 0
+ elif ms == "WM_SIZE":
+ # Work out size
+ if w != 1:
+ self.OnSize()
+ return 0
+ elif ms == "WM_COMMAND":
+ cmdCode = w & 0xffff
+ if cmdCode in self.cmds:
+ self.Command(self.cmds[cmdCode])
+ return 0
+ elif ms == "WM_ACTIVATE":
+ if w != WA_INACTIVE:
+ self.ed.FocusOn()
+ return 0
+ else:
+ return user32.DefWindowProcW(h, m, w, l)
+ return 0
+
+ def Command(self, name):
+ name = name.replace(" ", "")
+ method = "Cmd" + name
+ cmd = None
+ try:
+ cmd = getattr(self, method)
+ except AttributeError:
+ return
+ if cmd:
+ cmd()
+
+ def KeyDown(self, w, prefix = ""):
+ keyName = prefix
+ if IsKeyDown(VK_CONTROL):
+ keyName += "<control>"
+ if IsKeyDown(VK_SHIFT):
+ keyName += "<shift>"
+ keyName += KeyTranslate(w)
+ if trace:
+ print("Key:", keyName)
+ if keyName in self.keys:
+ method = "Cmd" + self.keys[keyName]
+ getattr(self, method)()
+ return True
+ #~ print("UKey:", keyName)
+ return False
+
+ def Accelerator(self, msg):
+ ms = sgsm.get(msg.message, "XXX")
+ if ms == "WM_KEYDOWN":
+ return self.KeyDown(msg.wParam)
+ elif ms == "WM_SYSKEYDOWN":
+ return self.KeyDown(msg.wParam, "<alt>")
+ return False
+
+ def AppLoop(self):
+ msg = ctypes.wintypes.MSG()
+ lpmsg = ctypes.byref(msg)
+ while user32.GetMessageW(lpmsg, 0, 0, 0):
+ if trace and msg.message != msgs["WM_TIMER"]:
+ print('mm', hex(msg.hWnd)[2:],sgsm.get(msg.message, "XXX"))
+ if not self.Accelerator(msg):
+ user32.TranslateMessage(lpmsg)
+ user32.DispatchMessageW(lpmsg)
+
+ def DoEvents(self):
+ msg = ctypes.wintypes.MSG()
+ lpmsg = ctypes.byref(msg)
+ cont = True
+ while cont:
+ cont = user32.PeekMessageW(lpmsg, 0, 0, 0, PM_REMOVE)
+ if cont:
+ if not self.Accelerator(msg):
+ user32.TranslateMessage(lpmsg)
+ user32.DispatchMessageW(lpmsg)
+
+ def SetTitle(self, changePath):
+ if changePath or self.titleDirty != self.ed.Modify:
+ self.titleDirty = self.ed.Modify
+ self.title = self.fullPath
+ if self.titleDirty:
+ self.title += " * "
+ else:
+ self.title += " - "
+ self.title += self.appName
+ if self.win:
+ user32.SetWindowTextW(self.win, self.title)
+
+ def Open(self):
+ ofx = OPENFILENAME(self.win, "Open File")
+ opath = "\0" * 1024
+ ofx.lpstrFile = opath
+ filters = ["Python (.py;.pyw)|*.py;*.pyw|All|*.*"]
+ filterText = "\0".join([f.replace("|", "\0") for f in filters])+"\0\0"
+ ofx.lpstrFilter = filterText
+ if ctypes.windll.comdlg32.GetOpenFileNameW(ctypes.byref(ofx)):
+ absPath = opath.replace("\0", "")
+ self.GrabFile(absPath)
+ self.ed.FocusOn()
+ self.ed.LexerLanguage = "python"
+ self.ed.Lexer = self.ed.SCLEX_PYTHON
+ self.ed.SetKeyWords(0, "class def else for if import print return while")
+ for style in [k for k in self.ed.k if k.startswith("SCE_P_")]:
+ self.ed.StyleSetFont(self.ed.k[style], "Verdana")
+ if "COMMENT" in style:
+ self.ed.StyleSetFore(self.ed.k[style], 127 * 256)
+ self.ed.StyleSetFont(self.ed.k[style], "Comic Sans MS")
+ elif "OPERATOR" in style:
+ print(style, self.ed.k[style])
+ self.ed.StyleSetBold(self.ed.k[style], 1)
+ self.ed.StyleSetFore(self.ed.k[style], 127 * 256 * 256)
+ elif "WORD" in style:
+ print(style, self.ed.k[style])
+ self.ed.StyleSetItalic(self.ed.k[style], 255)
+ self.ed.StyleSetFore(self.ed.k[style], 255 * 256 * 256)
+ else:
+ self.ed.StyleSetFore(self.ed.k[style], 0)
+
+ def SaveAs(self):
+ ofx = OPENFILENAME(self.win, "Save File")
+ opath = "\0" * 1024
+ ofx.lpstrFile = opath
+ if ctypes.windll.comdlg32.GetSaveFileNameW(ctypes.byref(ofx)):
+ self.fullPath = opath.replace("\0", "")
+ self.Save()
+ self.SetTitle(1)
+ self.ed.FocusOn()
+
+ def SetMenus(self):
+ ui = XiteMenu.MenuStructure
+ self.cmds = {}
+ self.keys = {}
+
+ cmdId = 0
+ self.menuBar = user32.CreateMenu()
+ for name, contents in ui:
+ cmdId += 1
+ menu = user32.CreateMenu()
+ for item in contents:
+ text, key = item
+ cmdText = text.replace("&", "")
+ cmdText = cmdText.replace("...", "")
+ cmdText = cmdText.replace(" ", "")
+ cmdId += 1
+ if key:
+ keyText = key.replace("<control>", "Ctrl+")
+ keyText = keyText.replace("<shift>", "Shift+")
+ text += "\t" + keyText
+ if text == "-":
+ user32.AppendMenuW(menu, MF_SEPARATOR, cmdId, text)
+ else:
+ user32.AppendMenuW(menu, 0, cmdId, text)
+ self.cmds[cmdId] = cmdText
+ self.keys[key] = cmdText
+ #~ print(cmdId, item)
+ user32.AppendMenuW(self.menuBar, MF_POPUP, menu, name)
+ user32.SetMenu(self.win, self.menuBar)
+ self.CheckMenuItem("Wrap", True)
+ user32.ShowWindow(self.win, SW_SHOW)
+
+ def CheckMenuItem(self, name, val):
+ #~ print(name, val)
+ if self.cmds:
+ for k,v in self.cmds.items():
+ if v == name:
+ #~ print(name, k)
+ user32.CheckMenuItem(user32.GetMenu(self.win), \
+ k, [MF_UNCHECKED, MF_CHECKED][val])
+
+ def Exit(self):
+ sys.exit(0)
+
+ def DisplayMessage(self, msg, ask):
+ return IDYES == user32.MessageBoxW(self.win, \
+ msg, self.appName, [MB_OK, MB_YESNOCANCEL][ask])
+
+ def NewDocument(self):
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.ed.SetSavePoint()
+
+ def SaveIfUnsure(self):
+ if self.ed.Modify:
+ msg = "Save changes to \"" + self.fullPath + "\"?"
+ print(msg)
+ decision = self.DisplayMessage(msg, True)
+ if decision:
+ self.CmdSave()
+ return decision
+ return True
+
+ def New(self):
+ if self.SaveIfUnsure():
+ self.fullPath = ""
+ self.overrideMode = None
+ self.NewDocument()
+ self.SetTitle(1)
+ self.Invalidate()
+
+ def CheckMenus(self):
+ pass
+
+ def MoveSelection(self, caret, anchor=-1):
+ if anchor == -1:
+ anchor = caret
+ self.ed.SetSelectionStart(caret)
+ self.ed.SetSelectionEnd(anchor)
+ self.ed.ScrollCaret()
+ self.Invalidate()
+
+ def GrabFile(self, name):
+ self.fullPath = name
+ self.overrideMode = None
+ self.NewDocument()
+ fsr = open(name, "rb")
+ data = fsr.read()
+ fsr.close()
+ self.ed.AddText(len(data), data)
+ self.ed.EmptyUndoBuffer()
+ self.MoveSelection(0)
+ self.SetTitle(1)
+
+ def Save(self):
+ fos = open(self.fullPath, "wb")
+ blockSize = 1024
+ length = self.ed.Length
+ i = 0
+ while i < length:
+ grabSize = length - i
+ if grabSize > blockSize:
+ grabSize = blockSize
+ #~ print(i, grabSize, length)
+ data = self.ed.ByteRange(i, i + grabSize)
+ fos.write(data)
+ i += grabSize
+ fos.close()
+ self.ed.SetSavePoint()
+ self.SetTitle(0)
+
+ # Command handlers are called by menu actions
+
+ def CmdNew(self):
+ self.New()
+
+ def CmdOpen(self):
+ self.Open()
+
+ def CmdSave(self):
+ if (self.fullPath == None) or (len(self.fullPath) == 0):
+ self.SaveAs()
+ else:
+ self.Save()
+
+ def CmdSaveAs(self):
+ self.SaveAs()
+
+ def CmdTest(self):
+ runner = unittest.TextTestRunner()
+ if self.test:
+ tests = unittest.defaultTestLoader.loadTestsFromName(self.test)
+ else:
+ tests = unittest.defaultTestLoader.loadTestsFromName("simpleTests")
+ results = runner.run(tests)
+ #~ print(results)
+ if self.test:
+ user32.PostQuitMessage(0)
+
+ def CmdExercised(self):
+ print()
+ unused = sorted(self.ed.all.difference(self.ed.used))
+ print("Unused", len(unused))
+ print()
+ print("\n".join(unused))
+ print()
+ print("Used", len(self.ed.used))
+ print()
+ print("\n".join(sorted(self.ed.used)))
+
+ def Uncalled(self):
+ print()
+ unused = sorted(self.ed.all.difference(self.ed.used))
+ uu = {}
+ for u in unused:
+ v = self.ed.getvalue(u)
+ if v > 2000:
+ uu[v] = u
+ #~ for x in sorted(uu.keys())[150:]:
+ return uu
+
+ def CmdExit(self):
+ self.Exit()
+
+ def CmdUndo(self):
+ self.ed.Undo()
+
+ def CmdRedo(self):
+ self.ed.Redo()
+
+ def CmdCut(self):
+ self.ed.Cut()
+
+ def CmdCopy(self):
+ self.ed.Copy()
+
+ def CmdPaste(self):
+ self.ed.Paste()
+
+ def CmdDelete(self):
+ self.ed.Clear()
+
+xiteFrame = None
+
+def main(test):
+ global xiteFrame
+ xiteFrame = XiteWin(test)
+ xiteFrame.AppLoop()
+ #~ xiteFrame.CmdExercised()
+ return xiteFrame.Uncalled()
diff --git a/scintilla/test/examples/x.asp b/scintilla/test/examples/x.asp
new file mode 100644
index 0000000..ff7c66f
--- /dev/null
+++ b/scintilla/test/examples/x.asp
@@ -0,0 +1,12 @@
+<%@language=javas%>
+<%
+#include
+function x() {
+}
+%>
+<%@language=vbscript%>
+<%
+sub x 'comment
+%>
+<head>
+<body></body>
diff --git a/scintilla/test/examples/x.asp.styled b/scintilla/test/examples/x.asp.styled
new file mode 100644
index 0000000..135af73
--- /dev/null
+++ b/scintilla/test/examples/x.asp.styled
@@ -0,0 +1,12 @@
+{15}<%@{16}language=javas{15}%>{0}
+{15}<%{56}
+#{61}include{56}
+{62}function{56} {61}x{65}(){56} {65}{{56}
+{65}}{56}
+{15}%>{0}
+{15}<%@{16}language=vbscript{15}%>{0}
+{15}<%{81}
+{84}sub{81} {86}x{81} {82}'comment {81}
+{15}%>{0}
+{1}<head>{0}
+{1}<body></body>{0}
diff --git a/scintilla/test/examples/x.cxx b/scintilla/test/examples/x.cxx
new file mode 100644
index 0000000..62b781f
--- /dev/null
+++ b/scintilla/test/examples/x.cxx
@@ -0,0 +1,4 @@
+// A demonstration program
+int main() {
+ printf("hello world %d\n", 9);
+}
diff --git a/scintilla/test/examples/x.cxx.styled b/scintilla/test/examples/x.cxx.styled
new file mode 100644
index 0000000..e096194
--- /dev/null
+++ b/scintilla/test/examples/x.cxx.styled
@@ -0,0 +1,4 @@
+{2}// A demonstration program
+{5}int{0} {11}main{10}(){0} {10}{{0}
+ {11}printf{10}({6}"hello world %d\n"{10},{0} {4}9{10});{0}
+{10}}{0}
diff --git a/scintilla/test/examples/x.d b/scintilla/test/examples/x.d
new file mode 100644
index 0000000..48f3ffe
--- /dev/null
+++ b/scintilla/test/examples/x.d
@@ -0,0 +1,47 @@
+$
+// /++ +/ doccomments are not yet supported
+/* */
+/** */
+/// drdr
+/+ /+ +/ +/
+//keyword test
+keyword1
+keyword2
+keyword4
+keyword5
+keyword6
+keyword7
+//unicode identifier test
+вапёasdÓΘΣαԷԸՑהכ拉麺ã¨ã²ã‚·ãƒžã‚¤ë‹¨ê²°ì„
+//strings test
+'s
+'
+w's'w
+"multiline
+ string"w
+e"zz"e
+r"asd\"e
+r"multiline
+ string"c
+r`asd\`e
+`multiline
+ string`d
+x"023 abc"e
+x"023
+ abc"w
+//numbers test
+a[3..4]=3
+2.stringof
+2.0.stringof
+2.
+2.2e+2
+2.2e-2
+.2e+2
+.2
+2e+2
+0x2e+2
+0x2ep+10
+,.2.stringof,
+
+end
+
diff --git a/scintilla/test/examples/x.d.styled b/scintilla/test/examples/x.d.styled
new file mode 100644
index 0000000..3a52dcd
--- /dev/null
+++ b/scintilla/test/examples/x.d.styled
@@ -0,0 +1,47 @@
+{14}${0}
+{2}// /++ +/ doccomments are not yet supported
+{1}/* */{0}
+{3}/** */{0}
+{15}/// drdr
+{4}/+ /+ +/ +/{0}
+{2}//keyword test
+{6}keyword1{0}
+{7}keyword2{0}
+{9}keyword4{0}
+{20}keyword5{0}
+{21}keyword6{0}
+{22}keyword7{0}
+{2}//unicode identifier test
+{14}вапёasdÓΘΣαԷԸՑהכ拉麺ã¨ã²ã‚·ãƒžã‚¤ë‹¨ê²°ì„{0}
+{2}//strings test
+{11}'s
+'
+{14}w{12}'s'{14}w{0}
+{10}"multiline
+ string"w{0}
+{14}e{10}"zz"{14}e{0}
+{19}r"asd\"{14}e{0}
+{19}r"multiline
+ string"c{0}
+{14}r{18}`asd\`{14}e{0}
+{18}`multiline
+ string`d{0}
+{19}x"023 abc"{14}e{0}
+{19}x"023
+ abc"w{0}
+{2}//numbers test
+{14}a{13}[{5}3{13}..{5}4{13}]={5}3{0}
+{5}2.stringof{0}
+{5}2.0{13}.{14}stringof{0}
+{5}2.{0}
+{5}2.2e+2{0}
+{5}2.2e-2{0}
+{5}.2e+2{0}
+{5}.2{0}
+{5}2e+2{0}
+{5}0x2e{13}+{5}2{0}
+{5}0x2ep+10{0}
+{13},{5}.2{13}.{14}stringof{13},{0}
+
+{14}end{0}
+
diff --git a/scintilla/test/examples/x.html b/scintilla/test/examples/x.html
new file mode 100644
index 0000000..6dd8b71
--- /dev/null
+++ b/scintilla/test/examples/x.html
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta name="Date.Modified" content="20010515" />
+ <title>SinkWorld - Portability</title>
+ <unknown>SinkWorld - Portability</unknown>
+ <link rel="stylesheet" type="text/css" href="SW.css">
+</head>
diff --git a/scintilla/test/examples/x.html.styled b/scintilla/test/examples/x.html.styled
new file mode 100644
index 0000000..d44b17c
--- /dev/null
+++ b/scintilla/test/examples/x.html.styled
@@ -0,0 +1,7 @@
+{1}<html{8} {3}xmlns{8}={6}"http://www.w3.org/1999/xhtml"{1}>{0}
+{1}<head>{0}
+ {1}<meta{8} {3}name{8}={6}"Date.Modified"{8} {3}content{8}={6}"20010515"{8} {11}/>{0}
+ {1}<title>{0}SinkWorld - Portability{1}</title>{0}
+ {2}<unknown>{0}SinkWorld - Portability{2}</unknown>{0}
+ {1}<link{8} {3}rel{8}={6}"stylesheet"{8} {3}type{8}={6}"text/css"{8} {3}href{8}={6}"SW.css"{1}>{0}
+{1}</head>{0}
diff --git a/scintilla/test/examples/x.php b/scintilla/test/examples/x.php
new file mode 100644
index 0000000..7c28d36
--- /dev/null
+++ b/scintilla/test/examples/x.php
@@ -0,0 +1,6 @@
+<head> <!-- About to script -->
+<?php
+echo "<!-- -->\n";
+/* ?> */
+?>
+<strong>for</strong><b>if</b>
diff --git a/scintilla/test/examples/x.php.styled b/scintilla/test/examples/x.php.styled
new file mode 100644
index 0000000..944e312
--- /dev/null
+++ b/scintilla/test/examples/x.php.styled
@@ -0,0 +1,6 @@
+{1}<head>{0} {9}<!-- About to script -->{0}
+{18}<?php{118}
+echo {119}"<!-- -->\n"{127};{118}
+{124}/* ?> */{118}
+{18}?>{0}
+{1}<strong>{0}for{1}</strong><b>{0}if{1}</b>{0}
diff --git a/scintilla/test/examples/x.py b/scintilla/test/examples/x.py
new file mode 100644
index 0000000..7e577dd
--- /dev/null
+++ b/scintilla/test/examples/x.py
@@ -0,0 +1,11 @@
+# Convert all punctuation characters except '_', '*', and '.' into spaces.
+def depunctuate(s):
+ '''A docstring'''
+ """Docstring 2"""
+ d = ""
+ for ch in s:
+ if ch in 'abcde':
+ d = d + ch
+ else:
+ d = d + " "
+ return d
diff --git a/scintilla/test/examples/x.py.styled b/scintilla/test/examples/x.py.styled
new file mode 100644
index 0000000..983c3b8
--- /dev/null
+++ b/scintilla/test/examples/x.py.styled
@@ -0,0 +1,11 @@
+{1}# Convert all punctuation characters except '_', '*', and '.' into spaces.{0}
+{5}def{0} {9}depunctuate{10}({11}s{10}):{0}
+ {6}'''A docstring'''{0}
+ {7}"""Docstring 2"""{0}
+ {11}d{0} {10}={0} {3}""{0}
+ {5}for{0} {11}ch{0} {5}in{0} {11}s{10}:{0}
+ {5}if{0} {11}ch{0} {5}in{0} {4}'abcde'{10}:{0}
+ {11}d{0} {10}={0} {11}d{0} {10}+{0} {11}ch{0}
+ {5}else{10}:{0}
+ {11}d{0} {10}={0} {11}d{0} {10}+{0} {3}" "{0}
+ {5}return{0} {11}d{0}
diff --git a/scintilla/test/examples/x.vb b/scintilla/test/examples/x.vb
new file mode 100644
index 0000000..3588221
--- /dev/null
+++ b/scintilla/test/examples/x.vb
@@ -0,0 +1,9 @@
+' String"
+Dim a As String = "hello, world"
+Dim b As String = "hello world"
+Dim c As String = "Joe said ""Hello"" to me"
+Dim d As String = "\\\\server\\share\\file.txt"
+' Character
+""C "c"C "cc"C
+' Date
+d = #5/31/1993# or # 01/01/0001 12:00:00AM #
diff --git a/scintilla/test/examples/x.vb.styled b/scintilla/test/examples/x.vb.styled
new file mode 100644
index 0000000..bc4e9e0
--- /dev/null
+++ b/scintilla/test/examples/x.vb.styled
@@ -0,0 +1,9 @@
+{1}' String"
+{3}Dim{0} {7}a{0} {3}As{0} {3}String{0} {6}={0} {4}"hello, world"{0}
+{3}Dim{0} {7}b{0} {3}As{0} {3}String{0} {6}={0} {4}"hello world"{0}
+{3}Dim{0} {7}c{0} {3}As{0} {3}String{0} {6}={0} {4}"Joe said ""Hello"" to me"{0}
+{3}Dim{0} {7}d{0} {3}As{0} {3}String{0} {6}={0} {4}"\\\\server\\share\\file.txt"{0}
+{1}' Character
+{4}""C{0} {4}"c"C{0} {4}"cc"C{0}
+{1}' Date
+{7}d{0} {6}={0} {8}#5/31/1993#{0} {3}or{0} {8}# 01/01/0001 12:00:00AM #{0}
diff --git a/scintilla/test/lexTests.py b/scintilla/test/lexTests.py
new file mode 100644
index 0000000..29e9ea8
--- /dev/null
+++ b/scintilla/test/lexTests.py
@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import io
+import os
+import unittest
+
+import XiteWin
+
+keywordsHTML = [
+b"b body content head href html link meta "
+ b"name rel script strong title type xmlns",
+b"function",
+b"sub"
+]
+
+class TestLexers(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def AsStyled(self):
+ text = self.ed.Contents()
+ data = io.BytesIO()
+ prevStyle = -1
+ for o in range(self.ed.Length):
+ styleNow = self.ed.GetStyleAt(o)
+ if styleNow != prevStyle:
+ styleBuf = "{%0d}" % styleNow
+ data.write(styleBuf.encode('utf-8'))
+ prevStyle = styleNow
+ data.write(text[o:o+1])
+ return data.getvalue()
+
+ def LexExample(self, name, lexerName, keywords=None):
+ if keywords is None:
+ keywords = []
+ self.ed.LexerLanguage = lexerName
+ bits = self.ed.StyleBitsNeeded
+ mask = 2 << bits - 1
+ self.ed.StyleBits = bits
+ for i in range(len(keywords)):
+ self.ed.SetKeyWords(i, keywords[i])
+
+ nameExample = os.path.join("examples", name)
+ namePrevious = nameExample +".styled"
+ nameNew = nameExample +".new"
+ with open(nameExample, "rb") as f:
+ prog = f.read()
+ BOM = b"\xEF\xBB\xBF"
+ if prog.startswith(BOM):
+ prog = prog[len(BOM):]
+ lenDocument = len(prog)
+ self.ed.AddText(lenDocument, prog)
+ self.ed.Colourise(0, lenDocument)
+ self.assertEquals(self.ed.EndStyled, lenDocument)
+ with open(namePrevious, "rb") as f:
+ prevStyled = f.read()
+ progStyled = self.AsStyled()
+ if progStyled != prevStyled:
+ with open(nameNew, "wb") as f:
+ f.write(progStyled)
+ print(progStyled)
+ print(prevStyled)
+ self.assertEquals(progStyled, prevStyled)
+ # The whole file doesn't parse like it did before so don't try line by line
+ # as that is likely to fail many times.
+ return
+
+ # Try partial lexes from the start of every line which should all be identical.
+ for line in range(self.ed.LineCount):
+ lineStart = self.ed.PositionFromLine(line)
+ self.ed.StartStyling(lineStart, mask)
+ self.assertEquals(self.ed.EndStyled, lineStart)
+ self.ed.Colourise(0, lenDocument)
+ progStyled = self.AsStyled()
+ if progStyled != prevStyled:
+ with open(nameNew, "wb") as f:
+ f.write(progStyled)
+ assertEquals(progStyled, prevStyled)
+ # Give up after one failure
+ return
+
+ def testCXX(self):
+ self.LexExample("x.cxx", b"cpp", [b"int"])
+
+ def testPython(self):
+ self.LexExample("x.py", b"python",
+ [b"class def else for if import in print return while"])
+
+ def testHTML(self):
+ self.LexExample("x.html", b"hypertext", keywordsHTML)
+
+ def testASP(self):
+ self.LexExample("x.asp", b"hypertext", keywordsHTML)
+
+ def testPHP(self):
+ self.LexExample("x.php", b"hypertext", keywordsHTML)
+
+ def testVB(self):
+ self.LexExample("x.vb", b"vb", [b"as dim or string"])
+
+ def testD(self):
+ self.LexExample("x.d", b"d",
+ [b"keyword1", b"keyword2", b"", b"keyword4", b"keyword5",
+ b"keyword6", b"keyword7"])
+
+if __name__ == '__main__':
+ XiteWin.main("lexTests")
diff --git a/scintilla/test/performanceTests.py b/scintilla/test/performanceTests.py
new file mode 100644
index 0000000..d4613b6
--- /dev/null
+++ b/scintilla/test/performanceTests.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import os, string, time, unittest
+
+import XiteWin
+
+class TestPerformance(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def testAddLine(self):
+ data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
+ start = time.time()
+ for i in range(1000):
+ self.ed.AddText(len(data), data)
+ self.assertEquals(self.ed.LineCount, i + 2)
+ end = time.time()
+ duration = end - start
+ print("%6.3f testAddLine" % duration)
+ self.xite.DoEvents()
+ self.assert_(self.ed.Length > 0)
+
+ def testAddLineMiddle(self):
+ data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
+ start = time.time()
+ for i in range(1000):
+ self.ed.AddText(len(data), data)
+ self.assertEquals(self.ed.LineCount, i + 2)
+ end = time.time()
+ duration = end - start
+ print("%6.3f testAddLineMiddle" % duration)
+ self.xite.DoEvents()
+ self.assert_(self.ed.Length > 0)
+
+ def testHuge(self):
+ data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
+ data = data * 100000
+ start = time.time()
+ self.ed.AddText(len(data), data)
+ end = time.time()
+ duration = end - start
+ print("%6.3f testHuge" % duration)
+ self.xite.DoEvents()
+ self.assert_(self.ed.Length > 0)
+
+ def testHugeInserts(self):
+ data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
+ data = data * 100000
+ insert = (string.digits + "\n").encode('utf-8')
+ self.ed.AddText(len(data), data)
+ start = time.time()
+ for i in range(1000):
+ self.ed.InsertText(0, insert)
+ end = time.time()
+ duration = end - start
+ print("%6.3f testHugeInserts" % duration)
+ self.xite.DoEvents()
+ self.assert_(self.ed.Length > 0)
+
+ def testHugeReplace(self):
+ oneLine = (string.ascii_letters + string.digits + "\n").encode('utf-8')
+ data = oneLine * 100000
+ insert = (string.digits + "\n").encode('utf-8')
+ self.ed.AddText(len(data), data)
+ start = time.time()
+ for i in range(1000):
+ self.ed.TargetStart = i * len(insert)
+ self.ed.TargetEnd = self.ed.TargetStart + len(oneLine)
+ self.ed.ReplaceTarget(len(insert), insert)
+ end = time.time()
+ duration = end - start
+ print("%6.3f testHugeReplace" % duration)
+ self.xite.DoEvents()
+ self.assert_(self.ed.Length > 0)
+
+if __name__ == '__main__':
+ XiteWin.main("performanceTests")
diff --git a/scintilla/test/simpleTests.py b/scintilla/test/simpleTests.py
new file mode 100644
index 0000000..b19964e
--- /dev/null
+++ b/scintilla/test/simpleTests.py
@@ -0,0 +1,1309 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import ctypes, os, unittest
+
+import XiteWin
+
+class TestSimple(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def testLength(self):
+ self.assertEquals(self.ed.Length, 0)
+
+ def testAddText(self):
+ self.ed.AddText(1, "x")
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(self.ed.GetCharAt(0), ord("x"))
+ self.assertEquals(self.ed.GetStyleAt(0), 0)
+ self.ed.ClearAll()
+ self.assertEquals(self.ed.Length, 0)
+
+ def testAddStyledText(self):
+ self.assertEquals(self.ed.EndStyled, 0)
+ self.ed.AddStyledText(2, b"x\002")
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(self.ed.GetCharAt(0), ord("x"))
+ self.assertEquals(self.ed.GetStyleAt(0), 2)
+ self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\002")
+ self.ed.ClearDocumentStyle()
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(self.ed.GetCharAt(0), ord("x"))
+ self.assertEquals(self.ed.GetStyleAt(0), 0)
+ self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\0")
+
+ def testStyling(self):
+ self.assertEquals(self.ed.EndStyled, 0)
+ self.ed.AddStyledText(4, b"x\002y\003")
+ self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\002y\003")
+ self.ed.StartStyling(0,0xf)
+ self.ed.SetStyling(1, 5)
+ self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\005y\003")
+ # Set the mask so 0 bit changed but not 2 bit
+ self.ed.StartStyling(0,0x1)
+ self.ed.SetStyling(1, 0)
+ self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\004y\003")
+
+ self.ed.StartStyling(0,0xff)
+ self.ed.SetStylingEx(2, b"\100\101")
+ self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\100y\101")
+
+ def testPosition(self):
+ self.assertEquals(self.ed.CurrentPos, 0)
+ self.assertEquals(self.ed.Anchor, 0)
+ self.ed.AddText(1, "x")
+ # Caret has automatically moved
+ self.assertEquals(self.ed.CurrentPos, 1)
+ self.assertEquals(self.ed.Anchor, 1)
+ self.ed.SelectAll()
+ self.assertEquals(self.ed.CurrentPos, 0)
+ self.assertEquals(self.ed.Anchor, 1)
+ self.ed.Anchor = 0
+ self.assertEquals(self.ed.Anchor, 0)
+ # Check line positions
+ self.assertEquals(self.ed.PositionFromLine(0), 0)
+ self.assertEquals(self.ed.GetLineEndPosition(0), 1)
+ self.assertEquals(self.ed.PositionFromLine(1), 1)
+
+ self.ed.CurrentPos = 1
+ self.assertEquals(self.ed.Anchor, 0)
+ self.assertEquals(self.ed.CurrentPos, 1)
+
+ def testSelection(self):
+ self.assertEquals(self.ed.CurrentPos, 0)
+ self.assertEquals(self.ed.Anchor, 0)
+ self.assertEquals(self.ed.SelectionStart, 0)
+ self.assertEquals(self.ed.SelectionEnd, 0)
+ self.ed.AddText(1, "x")
+ self.ed.SelectionStart = 0
+ self.assertEquals(self.ed.CurrentPos, 1)
+ self.assertEquals(self.ed.Anchor, 0)
+ self.assertEquals(self.ed.SelectionStart, 0)
+ self.assertEquals(self.ed.SelectionEnd, 1)
+ self.ed.SelectionStart = 1
+ self.assertEquals(self.ed.CurrentPos, 1)
+ self.assertEquals(self.ed.Anchor, 1)
+ self.assertEquals(self.ed.SelectionStart, 1)
+ self.assertEquals(self.ed.SelectionEnd, 1)
+
+ self.ed.SelectionEnd = 0
+ self.assertEquals(self.ed.CurrentPos, 0)
+ self.assertEquals(self.ed.Anchor, 0)
+
+ def testSetSelection(self):
+ self.ed.AddText(4, b"abcd")
+ self.ed.SetSel(1, 3)
+ self.assertEquals(self.ed.SelectionStart, 1)
+ self.assertEquals(self.ed.SelectionEnd, 3)
+ result = b"\0" * 5
+ length = self.ed.GetSelText(0, result)
+ self.assertEquals(length, 3)
+ self.assertEquals(result[:length], b"bc\0")
+ self.ed.ReplaceSel(0, b"1234")
+ self.assertEquals(self.ed.Length, 6)
+ self.assertEquals(self.ed.Contents(), b"a1234d")
+
+ def testReadOnly(self):
+ self.ed.AddText(1, b"x")
+ self.assertEquals(self.ed.ReadOnly, 0)
+ self.assertEquals(self.ed.Contents(), b"x")
+ self.ed.ReadOnly = 1
+ self.assertEquals(self.ed.ReadOnly, 1)
+ self.ed.AddText(1, b"x")
+ self.assertEquals(self.ed.Contents(), b"x")
+ self.ed.ReadOnly = 0
+ self.ed.AddText(1, b"x")
+ self.assertEquals(self.ed.Contents(), b"xx")
+ self.ed.Null()
+ self.assertEquals(self.ed.Contents(), b"xx")
+
+ def testAddLine(self):
+ data = b"x" * 70 + b"\n"
+ for i in range(5):
+ self.ed.AddText(len(data), data)
+ self.xite.DoEvents()
+ self.assertEquals(self.ed.LineCount, i + 2)
+ self.assert_(self.ed.Length > 0)
+
+ def testInsertText(self):
+ data = b"xy"
+ self.ed.InsertText(0, data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(data, self.ed.ByteRange(0,2))
+
+ self.ed.InsertText(1, data)
+ # Should now be "xxyy"
+ self.assertEquals(self.ed.Length, 4)
+ self.assertEquals(b"xxyy", self.ed.ByteRange(0,4))
+
+ def testInsertNul(self):
+ data = b"\0"
+ self.ed.AddText(1, data)
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(data, self.ed.ByteRange(0,1))
+
+ def testUndoRedo(self):
+ data = b"xy"
+ self.assertEquals(self.ed.Modify, 0)
+ self.assertEquals(self.ed.UndoCollection, 1)
+ self.assertEquals(self.ed.CanRedo(), 0)
+ self.assertEquals(self.ed.CanUndo(), 0)
+ self.ed.InsertText(0, data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.ed.Modify, 1)
+ self.assertEquals(self.ed.CanRedo(), 0)
+ self.assertEquals(self.ed.CanUndo(), 1)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.ed.Modify, 0)
+ self.assertEquals(self.ed.CanRedo(), 1)
+ self.assertEquals(self.ed.CanUndo(), 0)
+ self.ed.Redo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.ed.Modify, 1)
+ self.assertEquals(data, self.ed.Contents())
+ self.assertEquals(self.ed.CanRedo(), 0)
+ self.assertEquals(self.ed.CanUndo(), 1)
+
+ def testUndoSavePoint(self):
+ data = b"xy"
+ self.assertEquals(self.ed.Modify, 0)
+ self.ed.InsertText(0, data)
+ self.assertEquals(self.ed.Modify, 1)
+ self.ed.SetSavePoint()
+ self.assertEquals(self.ed.Modify, 0)
+ self.ed.InsertText(0, data)
+ self.assertEquals(self.ed.Modify, 1)
+
+ def testUndoCollection(self):
+ data = b"xy"
+ self.assertEquals(self.ed.UndoCollection, 1)
+ self.ed.UndoCollection = 0
+ self.assertEquals(self.ed.UndoCollection, 0)
+ self.ed.InsertText(0, data)
+ self.assertEquals(self.ed.CanRedo(), 0)
+ self.assertEquals(self.ed.CanUndo(), 0)
+ self.ed.UndoCollection = 1
+
+ def testGetColumn(self):
+ self.ed.AddText(1, b"x")
+ self.assertEquals(self.ed.GetColumn(0), 0)
+ self.assertEquals(self.ed.GetColumn(1), 1)
+ # Next line caused infinite loop in 1.71
+ self.assertEquals(self.ed.GetColumn(2), 1)
+ self.assertEquals(self.ed.GetColumn(3), 1)
+
+ def testTabWidth(self):
+ self.assertEquals(self.ed.TabWidth, 8)
+ self.ed.AddText(3, b"x\tb")
+ self.assertEquals(self.ed.GetColumn(0), 0)
+ self.assertEquals(self.ed.GetColumn(1), 1)
+ self.assertEquals(self.ed.GetColumn(2), 8)
+ for col in range(10):
+ if col == 0:
+ self.assertEquals(self.ed.FindColumn(0, col), 0)
+ elif col == 1:
+ self.assertEquals(self.ed.FindColumn(0, col), 1)
+ elif col == 9:
+ self.assertEquals(self.ed.FindColumn(0, col), 3)
+ else:
+ self.assertEquals(self.ed.FindColumn(0, col), 2)
+ self.ed.TabWidth = 4
+ self.assertEquals(self.ed.TabWidth, 4)
+ self.assertEquals(self.ed.GetColumn(0), 0)
+ self.assertEquals(self.ed.GetColumn(1), 1)
+ self.assertEquals(self.ed.GetColumn(2), 4)
+
+ def testIndent(self):
+ self.assertEquals(self.ed.Indent, 0)
+ self.assertEquals(self.ed.UseTabs, 1)
+ self.ed.Indent = 8
+ self.ed.UseTabs = 0
+ self.assertEquals(self.ed.Indent, 8)
+ self.assertEquals(self.ed.UseTabs, 0)
+ self.ed.AddText(3, b"x\tb")
+ self.assertEquals(self.ed.GetLineIndentation(0), 0)
+ self.ed.InsertText(0, b" ")
+ self.assertEquals(self.ed.GetLineIndentation(0), 1)
+ self.assertEquals(self.ed.GetLineIndentPosition(0), 1)
+ self.assertEquals(self.ed.Contents(), b" x\tb")
+ self.ed.SetLineIndentation(0,2)
+ self.assertEquals(self.ed.Contents(), b" x\tb")
+ self.assertEquals(self.ed.GetLineIndentPosition(0), 2)
+ self.ed.UseTabs = 1
+ self.ed.SetLineIndentation(0,8)
+ self.assertEquals(self.ed.Contents(), b"\tx\tb")
+ self.assertEquals(self.ed.GetLineIndentPosition(0), 1)
+
+ def testGetCurLine(self):
+ self.ed.AddText(1, b"x")
+ data = b"\0" * 100
+ caret = self.ed.GetCurLine(len(data), data)
+ data = data.rstrip(b"\0")
+ self.assertEquals(caret, 1)
+ self.assertEquals(data, b"x")
+
+ def testGetLine(self):
+ self.ed.AddText(1, b"x")
+ data = b"\0" * 100
+ length = self.ed.GetLine(0, data)
+ self.assertEquals(length, 1)
+ data = data[:length]
+ self.assertEquals(data, b"x")
+
+ def testLineEnds(self):
+ self.ed.AddText(3, b"x\ny")
+ self.assertEquals(self.ed.GetLineEndPosition(0), 1)
+ self.assertEquals(self.ed.GetLineEndPosition(1), 3)
+ self.assertEquals(self.ed.LineLength(0), 2)
+ self.assertEquals(self.ed.LineLength(1), 1)
+ self.assertEquals(self.ed.EOLMode, self.ed.SC_EOL_CRLF)
+ lineEnds = [b"\r\n", b"\r", b"\n"]
+ for lineEndType in [self.ed.SC_EOL_CR, self.ed.SC_EOL_LF, self.ed.SC_EOL_CRLF]:
+ self.ed.EOLMode = lineEndType
+ self.assertEquals(self.ed.EOLMode, lineEndType)
+ self.ed.ConvertEOLs(lineEndType)
+ self.assertEquals(self.ed.Contents(), b"x" + lineEnds[lineEndType] + b"y")
+ self.assertEquals(self.ed.LineLength(0), 1 + len(lineEnds[lineEndType]))
+
+ def testGoto(self):
+ self.ed.AddText(5, b"a\nb\nc")
+ self.assertEquals(self.ed.CurrentPos, 5)
+ self.ed.GotoLine(1)
+ self.assertEquals(self.ed.CurrentPos, 2)
+ self.ed.GotoPos(4)
+ self.assertEquals(self.ed.CurrentPos, 4)
+
+ def testCutCopyPaste(self):
+ self.ed.AddText(5, b"a1b2c")
+ self.ed.SetSel(1,3)
+ self.ed.Cut()
+ self.assertEquals(self.ed.CanPaste(), 1)
+ self.ed.SetSel(0, 0)
+ self.ed.Paste()
+ self.assertEquals(self.ed.Contents(), b"1ba2c")
+ self.ed.SetSel(4,5)
+ self.ed.Copy()
+ self.ed.SetSel(1,3)
+ self.ed.Paste()
+ self.assertEquals(self.ed.Contents(), b"1c2c")
+ self.ed.SetSel(2,4)
+ self.ed.Clear()
+ self.assertEquals(self.ed.Contents(), b"1c")
+
+ def testGetSet(self):
+ self.ed.SetText(0, b"abc")
+ self.assertEquals(self.ed.TextLength, 3)
+ result = b"\0" * 5
+ length = self.ed.GetText(4, result)
+ result = result[:length]
+ self.assertEquals(result, b"abc")
+
+ def testAppend(self):
+ self.ed.SetText(0, b"abc")
+ self.assertEquals(self.ed.SelectionStart, 0)
+ self.assertEquals(self.ed.SelectionEnd, 0)
+ text = b"12"
+ self.ed.AppendText(len(text), text)
+ self.assertEquals(self.ed.SelectionStart, 0)
+ self.assertEquals(self.ed.SelectionEnd, 0)
+ self.assertEquals(self.ed.Contents(), b"abc12")
+
+ def testTarget(self):
+ self.ed.SetText(0, b"abcd")
+ self.ed.TargetStart = 1
+ self.ed.TargetEnd = 3
+ self.assertEquals(self.ed.TargetStart, 1)
+ self.assertEquals(self.ed.TargetEnd, 3)
+ rep = b"321"
+ self.ed.ReplaceTarget(len(rep), rep)
+ self.assertEquals(self.ed.Contents(), b"a321d")
+ self.ed.SearchFlags = self.ed.SCFIND_REGEXP
+ self.assertEquals(self.ed.SearchFlags, self.ed.SCFIND_REGEXP)
+ searchString = b"\([1-9]+\)"
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(1, pos)
+ tagString = b"abcdefghijklmnop"
+ lenTag = self.ed.GetTag(1, tagString)
+ tagString = tagString[:lenTag]
+ self.assertEquals(tagString, b"321")
+ rep = b"\\1"
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = 0
+ self.ed.ReplaceTargetRE(len(rep), rep)
+ self.assertEquals(self.ed.Contents(), b"321a321d")
+ self.ed.SetSel(4,5)
+ self.ed.TargetFromSelection()
+ self.assertEquals(self.ed.TargetStart, 4)
+ self.assertEquals(self.ed.TargetEnd, 5)
+
+ def testTargetEscape(self):
+ # Checks that a literal \ can be in the replacement. Bug #2959876
+ self.ed.SetText(0, b"abcd")
+ self.ed.TargetStart = 1
+ self.ed.TargetEnd = 3
+ rep = b"\\\\n"
+ self.ed.ReplaceTargetRE(len(rep), rep)
+ self.assertEquals(self.ed.Contents(), b"a\\nd")
+
+ def testPointsAndPositions(self):
+ self.ed.AddText(1, b"x")
+ # Start of text
+ self.assertEquals(self.ed.PositionFromPoint(0,0), 0)
+ # End of text
+ self.assertEquals(self.ed.PositionFromPoint(0,100), 1)
+
+ def testLinePositions(self):
+ text = b"ab\ncd\nef"
+ self.ed.AddText(len(text), text)
+ self.assertEquals(self.ed.LineFromPosition(-1), 0)
+ line = 0
+ for pos in range(len(text)+1):
+ self.assertEquals(self.ed.LineFromPosition(pos), line)
+ if pos < len(text) and text[pos] == ord("\n"):
+ line += 1
+
+ def testWordPositions(self):
+ text = b"ab cd\tef"
+ self.ed.AddText(len(text), text)
+ self.assertEquals(self.ed.WordStartPosition(3, 0), 2)
+ self.assertEquals(self.ed.WordStartPosition(4, 0), 3)
+ self.assertEquals(self.ed.WordStartPosition(5, 0), 3)
+ self.assertEquals(self.ed.WordStartPosition(6, 0), 5)
+
+ self.assertEquals(self.ed.WordEndPosition(2, 0), 3)
+ self.assertEquals(self.ed.WordEndPosition(3, 0), 5)
+ self.assertEquals(self.ed.WordEndPosition(4, 0), 5)
+ self.assertEquals(self.ed.WordEndPosition(5, 0), 6)
+ self.assertEquals(self.ed.WordEndPosition(6, 0), 8)
+
+MODI = 1
+UNDO = 2
+REDO = 4
+
+class TestContainerUndo(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.data = b"xy"
+
+ def UndoState(self):
+ return (MODI if self.ed.Modify else 0) | \
+ (UNDO if self.ed.CanUndo() else 0) | \
+ (REDO if self.ed.CanRedo() else 0)
+
+ def testContainerActNoCoalesce(self):
+ self.ed.InsertText(0, self.data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 0)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
+ self.ed.Redo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+
+ def testContainerActCoalesce(self):
+ self.ed.InsertText(0, self.data)
+ self.ed.AddUndoAction(5, 1)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+ self.ed.Redo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+
+ def testContainerMultiStage(self):
+ self.ed.InsertText(0, self.data)
+ self.ed.AddUndoAction(5, 1)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+ self.ed.Redo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+
+ def testContainerMultiStageNoText(self):
+ self.ed.AddUndoAction(5, 1)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+ self.assertEquals(self.UndoState(), REDO)
+ self.ed.Redo()
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+ self.assertEquals(self.UndoState(), REDO)
+
+ def testContainerActCoalesceEnd(self):
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.InsertText(0, self.data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+ self.ed.Redo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+
+ def testContainerBetweenInsertAndInsert(self):
+ self.assertEquals(self.ed.Length, 0)
+ self.ed.InsertText(0, self.data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.InsertText(2, self.data)
+ self.assertEquals(self.ed.Length, 4)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ # Undoes both insertions and the containerAction in the middle
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+
+ def testContainerNoCoalesceBetweenInsertAndInsert(self):
+ self.assertEquals(self.ed.Length, 0)
+ self.ed.InsertText(0, self.data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 0)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.InsertText(2, self.data)
+ self.assertEquals(self.ed.Length, 4)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ # Undo last insertion
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
+ # Undo container
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
+ # Undo first insertion
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 0)
+ self.assertEquals(self.UndoState(), REDO)
+
+ def testContainerBetweenDeleteAndDelete(self):
+ self.ed.InsertText(0, self.data)
+ self.ed.EmptyUndoBuffer()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), 0)
+ self.ed.SetSel(2,2)
+ self.ed.DeleteBack()
+ self.assertEquals(self.ed.Length, 1)
+ self.ed.AddUndoAction(5, 1)
+ self.ed.DeleteBack()
+ self.assertEquals(self.ed.Length, 0)
+ # Undoes both deletions and the containerAction in the middle
+ self.ed.Undo()
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), REDO)
+
+ def testContainerBetweenInsertAndDelete(self):
+ self.assertEquals(self.ed.Length, 0)
+ self.ed.InsertText(0, self.data)
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.AddUndoAction(5, 1)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.SetSel(0,1)
+ self.ed.Cut()
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(self.UndoState(), MODI | UNDO)
+ self.ed.Undo() # Only undoes the deletion
+ self.assertEquals(self.ed.Length, 2)
+ self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
+
+class TestKeyCommands(unittest.TestCase):
+ """ These commands are normally assigned to keys and take no arguments """
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def selRange(self):
+ return self.ed.CurrentPos, self.ed.Anchor
+
+ def testLineMove(self):
+ self.ed.AddText(8, b"x1\ny2\nz3")
+ self.ed.SetSel(0,0)
+ self.ed.ChooseCaretX()
+ self.ed.LineDown()
+ self.ed.LineDown()
+ self.assertEquals(self.selRange(), (6, 6))
+ self.ed.LineUp()
+ self.assertEquals(self.selRange(), (3, 3))
+ self.ed.LineDownExtend()
+ self.assertEquals(self.selRange(), (6, 3))
+ self.ed.LineUpExtend()
+ self.ed.LineUpExtend()
+ self.assertEquals(self.selRange(), (0, 3))
+
+ def testCharMove(self):
+ self.ed.AddText(8, b"x1\ny2\nz3")
+ self.ed.SetSel(0,0)
+ self.ed.CharRight()
+ self.ed.CharRight()
+ self.assertEquals(self.selRange(), (2, 2))
+ self.ed.CharLeft()
+ self.assertEquals(self.selRange(), (1, 1))
+ self.ed.CharRightExtend()
+ self.assertEquals(self.selRange(), (2, 1))
+ self.ed.CharLeftExtend()
+ self.ed.CharLeftExtend()
+ self.assertEquals(self.selRange(), (0, 1))
+
+ def testWordMove(self):
+ self.ed.AddText(10, b"a big boat")
+ self.ed.SetSel(3,3)
+ self.ed.WordRight()
+ self.ed.WordRight()
+ self.assertEquals(self.selRange(), (10, 10))
+ self.ed.WordLeft()
+ self.assertEquals(self.selRange(), (6, 6))
+ self.ed.WordRightExtend()
+ self.assertEquals(self.selRange(), (10, 6))
+ self.ed.WordLeftExtend()
+ self.ed.WordLeftExtend()
+ self.assertEquals(self.selRange(), (2, 6))
+
+ def testHomeEndMove(self):
+ self.ed.AddText(10, b"a big boat")
+ self.ed.SetSel(3,3)
+ self.ed.Home()
+ self.assertEquals(self.selRange(), (0, 0))
+ self.ed.LineEnd()
+ self.assertEquals(self.selRange(), (10, 10))
+ self.ed.SetSel(3,3)
+ self.ed.HomeExtend()
+ self.assertEquals(self.selRange(), (0, 3))
+ self.ed.LineEndExtend()
+ self.assertEquals(self.selRange(), (10, 3))
+
+ def testStartEndMove(self):
+ self.ed.AddText(10, b"a\nbig\nboat")
+ self.ed.SetSel(3,3)
+ self.ed.DocumentStart()
+ self.assertEquals(self.selRange(), (0, 0))
+ self.ed.DocumentEnd()
+ self.assertEquals(self.selRange(), (10, 10))
+ self.ed.SetSel(3,3)
+ self.ed.DocumentStartExtend()
+ self.assertEquals(self.selRange(), (0, 3))
+ self.ed.DocumentEndExtend()
+ self.assertEquals(self.selRange(), (10, 3))
+
+
+class TestMarkers(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.ed.AddText(5, b"x\ny\nz")
+
+ def testMarker(self):
+ handle = self.ed.MarkerAdd(1,1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(handle), 1)
+ self.ed.MarkerDelete(1,1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(handle), -1)
+
+ def testMarkerDeleteAll(self):
+ h1 = self.ed.MarkerAdd(0,1)
+ h2 = self.ed.MarkerAdd(1,2)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h1), 0)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h2), 1)
+ self.ed.MarkerDeleteAll(1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h1), -1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h2), 1)
+ self.ed.MarkerDeleteAll(-1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h1), -1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(h2), -1)
+
+ def testMarkerDeleteHandle(self):
+ handle = self.ed.MarkerAdd(0,1)
+ self.assertEquals(self.ed.MarkerLineFromHandle(handle), 0)
+ self.ed.MarkerDeleteHandle(handle)
+ self.assertEquals(self.ed.MarkerLineFromHandle(handle), -1)
+
+ def testMarkerBits(self):
+ self.assertEquals(self.ed.MarkerGet(0), 0)
+ self.ed.MarkerAdd(0,1)
+ self.assertEquals(self.ed.MarkerGet(0), 2)
+ self.ed.MarkerAdd(0,2)
+ self.assertEquals(self.ed.MarkerGet(0), 6)
+
+ def testMarkerAddSet(self):
+ self.assertEquals(self.ed.MarkerGet(0), 0)
+ self.ed.MarkerAddSet(0,5)
+ self.assertEquals(self.ed.MarkerGet(0), 5)
+ self.ed.MarkerDeleteAll(-1)
+
+ def testMarkerNext(self):
+ h1 = self.ed.MarkerAdd(0,1)
+ h2 = self.ed.MarkerAdd(2,1)
+ self.assertEquals(self.ed.MarkerNext(0, 2), 0)
+ self.assertEquals(self.ed.MarkerNext(1, 2), 2)
+ self.assertEquals(self.ed.MarkerNext(2, 2), 2)
+ self.assertEquals(self.ed.MarkerPrevious(0, 2), 0)
+ self.assertEquals(self.ed.MarkerPrevious(1, 2), 0)
+ self.assertEquals(self.ed.MarkerPrevious(2, 2), 2)
+
+ def testLineState(self):
+ self.assertEquals(self.ed.MaxLineState, 0)
+ self.assertEquals(self.ed.GetLineState(0), 0)
+ self.assertEquals(self.ed.GetLineState(1), 0)
+ self.assertEquals(self.ed.GetLineState(2), 0)
+ self.ed.SetLineState(1, 100)
+ self.assertNotEquals(self.ed.MaxLineState, 0)
+ self.assertEquals(self.ed.GetLineState(0), 0)
+ self.assertEquals(self.ed.GetLineState(1), 100)
+ self.assertEquals(self.ed.GetLineState(2), 0)
+
+ def testSymbolRetrieval(self):
+ self.ed.MarkerDefine(1,3)
+ self.assertEquals(self.ed.MarkerSymbolDefined(1), 3)
+
+class TestIndicators(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def testSetIndicator(self):
+ self.assertEquals(self.ed.IndicGetStyle(0), 1)
+ self.assertEquals(self.ed.IndicGetFore(0), 0x007f00)
+ self.ed.IndicSetStyle(0, 2)
+ self.ed.IndicSetFore(0, 0xff0080)
+ self.assertEquals(self.ed.IndicGetStyle(0), 2)
+ self.assertEquals(self.ed.IndicGetFore(0), 0xff0080)
+
+class TestScrolling(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ # 150 should be enough lines
+ self.ed.InsertText(0, b"a\n" * 150)
+
+ def testTop(self):
+ self.ed.GotoLine(0)
+ self.assertEquals(self.ed.FirstVisibleLine, 0)
+
+ def testLineScroll(self):
+ self.ed.GotoLine(0)
+ self.ed.LineScroll(0, 3)
+ self.assertEquals(self.ed.FirstVisibleLine, 3)
+
+ def testVisibleLine(self):
+ self.ed.FirstVisibleLine = 7
+ self.assertEquals(self.ed.FirstVisibleLine, 7)
+
+class TestSearch(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.ed.InsertText(0, b"a\tbig boat\t")
+
+ def testFind(self):
+ pos = self.ed.FindBytes(0, self.ed.Length, b"zzz", 0)
+ self.assertEquals(pos, -1)
+ pos = self.ed.FindBytes(0, self.ed.Length, b"big", 0)
+ self.assertEquals(pos, 2)
+
+ def testCaseFind(self):
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"big", 0), 2)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bIg", 0), 2)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bIg",
+ self.ed.SCFIND_MATCHCASE), -1)
+
+ def testWordFind(self):
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi",
+ self.ed.SCFIND_WHOLEWORD), -1)
+
+ def testWordStartFind(self):
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi",
+ self.ed.SCFIND_WORDSTART), 2)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"ig", 0), 3)
+ self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"ig",
+ self.ed.SCFIND_WORDSTART), -1)
+
+ def testREFind(self):
+ flags = self.ed.SCFIND_REGEXP
+ self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\<b.g\>", flags))
+ self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
+ flags | self.ed.SCFIND_MATCHCASE))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
+ self.assertEquals(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
+ self.assertEquals(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\([a]\).*\0", flags))
+
+ def testPosixREFind(self):
+ flags = self.ed.SCFIND_REGEXP | self.ed.SCFIND_POSIX
+ self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\<b.g\>", flags))
+ self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
+ flags | self.ed.SCFIND_MATCHCASE))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
+ self.assertEquals(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
+ self.assertEquals(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"([a]).*\0", flags))
+
+ def testPhilippeREFind(self):
+ # Requires 1.,72
+ flags = self.ed.SCFIND_REGEXP
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, "\w", flags))
+ self.assertEquals(1, self.ed.FindBytes(0, self.ed.Length, "\W", flags))
+ self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, "\d", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, "\D", flags))
+ self.assertEquals(1, self.ed.FindBytes(0, self.ed.Length, "\s", flags))
+ self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, "\S", flags))
+ self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, "\x62", flags))
+
+class TestProperties(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def testSet(self):
+ self.ed.SetProperty(b"test", b"12")
+ self.assertEquals(self.ed.GetPropertyInt(b"test"), 12)
+ result = b"\0" * 10
+ length = self.ed.GetProperty(b"test", result)
+ result = result[:length]
+ self.assertEquals(result, b"12")
+ self.ed.SetProperty(b"test.plus", b"[$(test)]")
+ result = b"\0" * 10
+ length = self.ed.GetPropertyExpanded(b"test.plus", result)
+ result = result[:length]
+ self.assertEquals(result, b"[12]")
+
+class TestTextMargin(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.txt = b"abcd"
+ self.ed.AddText(1, b"x")
+
+ def testAscent(self):
+ lineHeight = self.ed.TextHeight(0)
+ self.ed.ExtraAscent
+ self.assertEquals(self.ed.ExtraAscent, 0)
+ self.assertEquals(self.ed.ExtraDescent, 0)
+ self.ed.ExtraAscent = 1
+ self.assertEquals(self.ed.ExtraAscent, 1)
+ self.ed.ExtraDescent = 2
+ self.assertEquals(self.ed.ExtraDescent, 2)
+ # Allow line height to recalculate
+ self.xite.DoEvents()
+ lineHeightIncreased = self.ed.TextHeight(0)
+ self.assertEquals(lineHeightIncreased, lineHeight + 2 + 1)
+
+ def testTextMargin(self):
+ self.ed.MarginSetText(0, self.txt)
+ result = b"\0" * 10
+ length = self.ed.MarginGetText(0, result)
+ result = result[:length]
+ self.assertEquals(result, self.txt)
+ self.ed.MarginTextClearAll()
+
+ def testTextMarginStyle(self):
+ self.ed.MarginSetText(0, self.txt)
+ self.ed.MarginSetStyle(0, 33)
+ self.assertEquals(self.ed.MarginGetStyle(0), 33)
+ self.ed.MarginTextClearAll()
+
+ def testTextMarginStyles(self):
+ styles = b"\001\002\003\004"
+ self.ed.MarginSetText(0, self.txt)
+ self.ed.MarginSetStyles(0, styles)
+ result = b"\0" * 10
+ length = self.ed.MarginGetStyles(0, result)
+ result = result[:length]
+ self.assertEquals(result, styles)
+ self.ed.MarginTextClearAll()
+
+ def testTextMarginStyleOffset(self):
+ self.ed.MarginSetStyleOffset(300)
+ self.assertEquals(self.ed.MarginGetStyleOffset(), 300)
+
+class TestAnnotation(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ self.txt = b"abcd"
+ self.ed.AddText(1, b"x")
+
+ def testTextAnnotation(self):
+ self.assertEquals(self.ed.AnnotationGetLines(), 0)
+ self.ed.AnnotationSetText(0, self.txt)
+ self.assertEquals(self.ed.AnnotationGetLines(), 1)
+ result = b"\0" * 10
+ length = self.ed.AnnotationGetText(0, result)
+ self.assertEquals(length, 4)
+ result = result[:length]
+ self.assertEquals(result, self.txt)
+ self.ed.AnnotationClearAll()
+
+ def testTextAnnotationStyle(self):
+ self.ed.AnnotationSetText(0, self.txt)
+ self.ed.AnnotationSetStyle(0, 33)
+ self.assertEquals(self.ed.AnnotationGetStyle(0), 33)
+ self.ed.AnnotationClearAll()
+
+ def testTextAnnotationStyles(self):
+ styles = b"\001\002\003\004"
+ self.ed.AnnotationSetText(0, self.txt)
+ self.ed.AnnotationSetStyles(0, styles)
+ result = b"\0" * 10
+ length = self.ed.AnnotationGetStyles(0, result)
+ result = result[:length]
+ self.assertEquals(result, styles)
+ self.ed.AnnotationClearAll()
+
+ def testTextAnnotationStyleOffset(self):
+ self.ed.AnnotationSetStyleOffset(300)
+ self.assertEquals(self.ed.AnnotationGetStyleOffset(), 300)
+
+ def testTextAnnotationVisible(self):
+ self.assertEquals(self.ed.AnnotationGetVisible(), 0)
+ self.ed.AnnotationSetVisible(2)
+ self.assertEquals(self.ed.AnnotationGetVisible(), 2)
+ self.ed.AnnotationSetVisible(0)
+
+class TestMultiSelection(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ # 3 lines of 3 characters
+ t = b"xxx\nxxx\nxxx"
+ self.ed.AddText(len(t), t)
+
+ def testSelectionCleared(self):
+ self.ed.ClearSelections()
+ self.assertEquals(self.ed.Selections, 1)
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 0)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 0)
+
+ def test1Selection(self):
+ self.ed.SetSelection(1, 2)
+ self.assertEquals(self.ed.Selections, 1)
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
+ self.assertEquals(self.ed.GetSelectionNStart(0), 1)
+ self.assertEquals(self.ed.GetSelectionNEnd(0), 2)
+ self.ed.SwapMainAnchorCaret()
+ self.assertEquals(self.ed.Selections, 1)
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
+
+ def test1SelectionReversed(self):
+ self.ed.SetSelection(2, 1)
+ self.assertEquals(self.ed.Selections, 1)
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEquals(self.ed.GetSelectionNStart(0), 1)
+ self.assertEquals(self.ed.GetSelectionNEnd(0), 2)
+
+ def test1SelectionByStartEnd(self):
+ self.ed.SetSelectionNStart(0, 2)
+ self.ed.SetSelectionNEnd(0, 3)
+ self.assertEquals(self.ed.Selections, 1)
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
+ self.assertEquals(self.ed.GetSelectionNStart(0), 2)
+ self.assertEquals(self.ed.GetSelectionNEnd(0), 3)
+
+ def test2Selections(self):
+ self.ed.SetSelection(1, 2)
+ self.ed.AddSelection(4, 5)
+ self.assertEquals(self.ed.Selections, 2)
+ self.assertEquals(self.ed.MainSelection, 1)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
+ self.assertEquals(self.ed.GetSelectionNCaret(1), 4)
+ self.assertEquals(self.ed.GetSelectionNAnchor(1), 5)
+ self.assertEquals(self.ed.GetSelectionNStart(0), 1)
+ self.assertEquals(self.ed.GetSelectionNEnd(0), 2)
+ self.ed.MainSelection = 0
+ self.assertEquals(self.ed.MainSelection, 0)
+ self.ed.RotateSelection()
+ self.assertEquals(self.ed.MainSelection, 1)
+
+ def testRectangularSelection(self):
+ self.ed.RectangularSelectionAnchor = 1
+ self.assertEquals(self.ed.RectangularSelectionAnchor, 1)
+ self.ed.RectangularSelectionCaret = 10
+ self.assertEquals(self.ed.RectangularSelectionCaret, 10)
+ self.assertEquals(self.ed.Selections, 3)
+ self.assertEquals(self.ed.MainSelection, 2)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
+ self.assertEquals(self.ed.GetSelectionNAnchor(1), 5)
+ self.assertEquals(self.ed.GetSelectionNCaret(1), 6)
+ self.assertEquals(self.ed.GetSelectionNAnchor(2), 9)
+ self.assertEquals(self.ed.GetSelectionNCaret(2), 10)
+
+ def testVirtualSpace(self):
+ self.ed.SetSelection(3, 7)
+ self.ed.SetSelectionNCaretVirtualSpace(0, 3)
+ self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 3)
+ self.ed.SetSelectionNAnchorVirtualSpace(0, 2)
+ self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 2)
+ # Does not check that virtual space is valid by being at end of line
+ self.ed.SetSelection(1, 1)
+ self.ed.SetSelectionNCaretVirtualSpace(0, 3)
+ self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 3)
+
+ def testRectangularVirtualSpace(self):
+ self.ed.VirtualSpaceOptions=1
+ self.ed.RectangularSelectionAnchor = 3
+ self.assertEquals(self.ed.RectangularSelectionAnchor, 3)
+ self.ed.RectangularSelectionCaret = 7
+ self.assertEquals(self.ed.RectangularSelectionCaret, 7)
+ self.ed.RectangularSelectionAnchorVirtualSpace = 1
+ self.assertEquals(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
+ self.ed.RectangularSelectionCaretVirtualSpace = 10
+ self.assertEquals(self.ed.RectangularSelectionCaretVirtualSpace, 10)
+ self.assertEquals(self.ed.Selections, 2)
+ self.assertEquals(self.ed.MainSelection, 1)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
+ self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 1)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
+ self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 10)
+
+ def testRectangularVirtualSpaceOptionOff(self):
+ # Same as previous test but virtual space option off so no virtual space in result
+ self.ed.VirtualSpaceOptions=0
+ self.ed.RectangularSelectionAnchor = 3
+ self.assertEquals(self.ed.RectangularSelectionAnchor, 3)
+ self.ed.RectangularSelectionCaret = 7
+ self.assertEquals(self.ed.RectangularSelectionCaret, 7)
+ self.ed.RectangularSelectionAnchorVirtualSpace = 1
+ self.assertEquals(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
+ self.ed.RectangularSelectionCaretVirtualSpace = 10
+ self.assertEquals(self.ed.RectangularSelectionCaretVirtualSpace, 10)
+ self.assertEquals(self.ed.Selections, 2)
+ self.assertEquals(self.ed.MainSelection, 1)
+ self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
+ self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 0)
+ self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
+ self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 0)
+
+class TestCaseMapping(unittest.TestCase):
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def tearDown(self):
+ self.ed.SetCodePage(0)
+ self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)
+
+ def testEmpty(self):
+ # Trying to upper case an empty string caused a crash at one stage
+ t = b"x"
+ self.ed.SetText(len(t), t)
+ self.ed.UpperCase()
+ self.assertEquals(self.ed.Contents(), b"x")
+
+ def testASCII(self):
+ t = b"x"
+ self.ed.SetText(len(t), t)
+ self.ed.SetSel(0,1)
+ self.ed.UpperCase()
+ self.assertEquals(self.ed.Contents(), b"X")
+
+ def testLatin1(self):
+ t = "Ã¥".encode("Latin-1")
+ r = "Ã…".encode("Latin-1")
+ self.ed.SetText(len(t), t)
+ self.ed.SetSel(0,1)
+ self.ed.UpperCase()
+ self.assertEquals(self.ed.Contents(), r)
+
+ def testRussian(self):
+ self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
+ t = "Б".encode("Windows-1251")
+ r = "б".encode("Windows-1251")
+ self.ed.SetText(len(t), t)
+ self.ed.SetSel(0,1)
+ self.ed.LowerCase()
+ self.assertEquals(self.ed.Contents(), r)
+
+ def testUTF(self):
+ self.ed.SetCodePage(65001)
+ t = "Ã¥".encode("UTF-8")
+ r = "Ã…".encode("UTF-8")
+ self.ed.SetText(len(t), t)
+ self.ed.SetSel(0,2)
+ self.ed.UpperCase()
+ self.assertEquals(self.ed.Contents(), r)
+
+ def testUTFDifferentLength(self):
+ self.ed.SetCodePage(65001)
+ t = "ı".encode("UTF-8")
+ r = "I".encode("UTF-8")
+ self.ed.SetText(len(t), t)
+ self.assertEquals(self.ed.Length, 2)
+ self.ed.SetSel(0,2)
+ self.ed.UpperCase()
+ self.assertEquals(self.ed.Length, 1)
+ self.assertEquals(self.ed.Contents(), r)
+
+class TestCaseInsensitiveSearch(unittest.TestCase):
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def tearDown(self):
+ self.ed.SetCodePage(0)
+ self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)
+
+ def testEmpty(self):
+ text = b" x X"
+ searchString = b""
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(0, pos)
+
+ def testASCII(self):
+ text = b" x X"
+ searchString = b"X"
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(1, pos)
+
+ def testLatin1(self):
+ text = "Frånd Åå".encode("Latin-1")
+ searchString = "Ã…".encode("Latin-1")
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(2, pos)
+
+ def testRussian(self):
+ self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
+ text = "=(Б tex б)".encode("Windows-1251")
+ searchString = "б".encode("Windows-1251")
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(2, pos)
+
+ def testUTF(self):
+ self.ed.SetCodePage(65001)
+ text = "Frånd Åå".encode("UTF-8")
+ searchString = "Ã…".encode("UTF-8")
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(2, pos)
+
+ def testUTFDifferentLength(self):
+ # Searching for a two byte string "ı" finds a single byte "I"
+ self.ed.SetCodePage(65001)
+ text = "Fråndi Ååİ $".encode("UTF-8")
+ firstPosition = len("Frånd".encode("UTF-8"))
+ searchString = "İ".encode("UTF-8")
+ self.assertEquals(len(searchString), 2)
+ self.ed.SetText(len(text), text)
+ self.ed.TargetStart = 0
+ self.ed.TargetEnd = self.ed.Length-1
+ self.ed.SearchFlags = 0
+ pos = self.ed.SearchInTarget(len(searchString), searchString)
+ self.assertEquals(firstPosition, pos)
+ self.assertEquals(firstPosition+1, self.ed.TargetEnd)
+
+class TestLexer(unittest.TestCase):
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+
+ def testLexerNumber(self):
+ self.ed.Lexer = self.ed.SCLEX_CPP
+ self.assertEquals(self.ed.GetLexer(), self.ed.SCLEX_CPP)
+
+ def testLexerName(self):
+ self.ed.LexerLanguage = b"cpp"
+ self.assertEquals(self.ed.GetLexer(), self.ed.SCLEX_CPP)
+ name = b"-" * 100
+ length = self.ed.GetLexerLanguage(0, name)
+ name = name[:length]
+ self.assertEquals(name, b"cpp")
+
+class TestAutoComplete(unittest.TestCase):
+
+ def setUp(self):
+ self.xite = XiteWin.xiteFrame
+ self.ed = self.xite.ed
+ self.ed.ClearAll()
+ self.ed.EmptyUndoBuffer()
+ # 3 lines of 3 characters
+ t = b"xxx\n"
+ self.ed.AddText(len(t), t)
+
+ def testDefaults(self):
+ self.assertEquals(self.ed.AutoCGetSeparator(), ord(' '))
+ self.assertEquals(self.ed.AutoCGetMaxHeight(), 5)
+ self.assertEquals(self.ed.AutoCGetMaxWidth(), 0)
+ self.assertEquals(self.ed.AutoCGetTypeSeparator(), ord('?'))
+ self.assertEquals(self.ed.AutoCGetIgnoreCase(), 0)
+ self.assertEquals(self.ed.AutoCGetAutoHide(), 1)
+ self.assertEquals(self.ed.AutoCGetDropRestOfWord(), 0)
+
+ def testChangeDefaults(self):
+ self.ed.AutoCSetSeparator(ord('-'))
+ self.assertEquals(self.ed.AutoCGetSeparator(), ord('-'))
+ self.ed.AutoCSetSeparator(ord(' '))
+
+ self.ed.AutoCSetMaxHeight(100)
+ self.assertEquals(self.ed.AutoCGetMaxHeight(), 100)
+ self.ed.AutoCSetMaxHeight(5)
+
+ self.ed.AutoCSetMaxWidth(100)
+ self.assertEquals(self.ed.AutoCGetMaxWidth(), 100)
+ self.ed.AutoCSetMaxWidth(0)
+
+ self.ed.AutoCSetTypeSeparator(ord('@'))
+ self.assertEquals(self.ed.AutoCGetTypeSeparator(), ord('@'))
+ self.ed.AutoCSetTypeSeparator(ord('?'))
+
+ self.ed.AutoCSetIgnoreCase(1)
+ self.assertEquals(self.ed.AutoCGetIgnoreCase(), 1)
+ self.ed.AutoCSetIgnoreCase(0)
+
+ self.ed.AutoCSetAutoHide(0)
+ self.assertEquals(self.ed.AutoCGetAutoHide(), 0)
+ self.ed.AutoCSetAutoHide(1)
+
+ self.ed.AutoCSetDropRestOfWord(1)
+ self.assertEquals(self.ed.AutoCGetDropRestOfWord(), 1)
+ self.ed.AutoCSetDropRestOfWord(0)
+
+ def testAutoShow(self):
+ self.assertEquals(self.ed.AutoCActive(), 0)
+ self.ed.SetSel(0, 0)
+
+ self.ed.AutoCShow(0, b"za defn ghi")
+ self.assertEquals(self.ed.AutoCActive(), 1)
+ #~ time.sleep(2)
+ self.assertEquals(self.ed.AutoCPosStart(), 0)
+ self.assertEquals(self.ed.AutoCGetCurrent(), 0)
+ t = b"xxx"
+ l = self.ed.AutoCGetCurrentText(5, t)
+ #~ self.assertEquals(l, 3)
+ self.assertEquals(t, b"za\0")
+ self.ed.AutoCCancel()
+ self.assertEquals(self.ed.AutoCActive(), 0)
+
+ def testAutoShowComplete(self):
+ self.assertEquals(self.ed.AutoCActive(), 0)
+ self.ed.SetSel(0, 0)
+
+ self.ed.AutoCShow(0, b"za defn ghi")
+ self.ed.AutoCComplete()
+ self.assertEquals(self.ed.Contents(), b"zaxxx\n")
+
+ self.assertEquals(self.ed.AutoCActive(), 0)
+
+ def testAutoShowSelect(self):
+ self.assertEquals(self.ed.AutoCActive(), 0)
+ self.ed.SetSel(0, 0)
+
+ self.ed.AutoCShow(0, b"za defn ghi")
+ self.ed.AutoCSelect(0, b"d")
+ self.ed.AutoCComplete()
+ self.assertEquals(self.ed.Contents(), b"defnxxx\n")
+
+ self.assertEquals(self.ed.AutoCActive(), 0)
+
+
+#~ import os
+#~ for x in os.getenv("PATH").split(";"):
+ #~ n = "scilexer.dll"
+ #~ nf = x + "\\" + n
+ #~ print os.access(nf, os.R_OK), nf
+if __name__ == '__main__':
+ uu = XiteWin.main("simpleTests")
+ #~ for x in sorted(uu.keys()):
+ #~ print(x, uu[x])
+ #~ print()
diff --git a/scintilla/test/xite.py b/scintilla/test/xite.py
new file mode 100644
index 0000000..56b9c5f
--- /dev/null
+++ b/scintilla/test/xite.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+import XiteWin
+
+if __name__ == "__main__":
+ XiteWin.main("")
diff --git a/scintilla/tgzsrc b/scintilla/tgzsrc
new file mode 100644
index 0000000..a4d4ee0
--- /dev/null
+++ b/scintilla/tgzsrc
@@ -0,0 +1,4 @@
+cd ..
+rm -f scintilla.tgz
+tar --create --exclude \*.o --exclude \*.obj --exclude \*.dll --exclude \*.exe --exclude \*.a scintilla/* \
+ | gzip -c >scintilla.tgz
diff --git a/scintilla/vcbuild/SciLexer.dsp b/scintilla/vcbuild/SciLexer.dsp
new file mode 100644
index 0000000..74ebd48
--- /dev/null
+++ b/scintilla/vcbuild/SciLexer.dsp
@@ -0,0 +1,549 @@
+# Microsoft Developer Studio Project File - Name="SciLexer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=SciLexer - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "SciLexer.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "SciLexer.mak" CFG="SciLexer - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "SciLexer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "SciLexer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "SciLexer - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "../bin"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SciLexer_EXPORTS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O1 /I "..\include" /I "..\src" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SCI_LEXER" /D "_CRT_SECURE_NO_WARNINGS" /FD /c
+# SUBTRACT CPP /Fr /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib comctl32.lib /nologo /dll /pdb:none /map /machine:I386 /opt:nowin98
+
+!ELSEIF "$(CFG)" == "SciLexer - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "../bin"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SciLexer_EXPORTS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\src" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SCI_LEXER" /D "_CRT_SECURE_NO_WARNINGS" /FR /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib imm32.lib comctl32.lib /nologo /dll /debug /machine:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "SciLexer - Win32 Release"
+# Name "SciLexer - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\AutoComplete.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\CallTip.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\CellBuffer.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\CharClassify.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\ContractionState.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Decoration.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Document.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\DocumentAccessor.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Editor.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\ExternalLexer.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Indicator.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\KeyMap.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\KeyWords.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAbaqus.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAda.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAPDL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAsm.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAsn1.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexASY.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAU3.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexAVE.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexBaan.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexBash.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexBasic.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexBullant.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCaml.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCLW.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCmake.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCOBOL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexConf.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCPP.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCrontab.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCsound.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexCSS.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexD.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexEiffel.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexErlang.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexEScript.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexFlagship.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexForth.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexFortran.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexGAP.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexGui4Cli.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexHaskell.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexHTML.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexInno.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexKix.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexLisp.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexLout.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexLua.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMagik.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMarkdown.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMatlab.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMetapost.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMMIXAL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMPT.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMSSQL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexMySQL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexNimrod.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexNsis.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexOpal.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexOthers.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPascal.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPB.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPerl.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPLM.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPOV.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPowerPro.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPowerShell.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexProgress.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPS.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexPython.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexR.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexRebol.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexRuby.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexScriptol.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSmalltalk.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSML.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSorcus.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSpecman.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSpice.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexSQL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexTACL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexTADS3.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexTAL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexTCL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexTeX.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexVB.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexVerilog.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexVHDL.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LexYAML.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\LineMarker.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\PerLine.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32\PlatWin.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\PositionCache.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\PropSet.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\RESearch.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\RunStyles.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\ScintillaBase.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32\ScintillaWin.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32\ScintRes.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Selection.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\Style.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\StyleContext.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\UniConversion.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\ViewStyle.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\WindowAccessor.cxx
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\XPM.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\Platform.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=..\win32\Margin.cur
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/scintilla/version.txt b/scintilla/version.txt
new file mode 100644
index 0000000..1762b27
--- /dev/null
+++ b/scintilla/version.txt
@@ -0,0 +1 @@
+212
diff --git a/scintilla/win32/Margin.cur b/scintilla/win32/Margin.cur
new file mode 100644
index 0000000..9e0e790
--- /dev/null
+++ b/scintilla/win32/Margin.cur
Binary files differ
diff --git a/scintilla/win32/PlatWin.cxx b/scintilla/win32/PlatWin.cxx
new file mode 100644
index 0000000..10055c1
--- /dev/null
+++ b/scintilla/win32/PlatWin.cxx
@@ -0,0 +1,2293 @@
+// Scintilla source code edit control
+/** @file PlatWin.cxx
+ ** Implementation of platform facilities on Windows.
+ **/
+// 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 <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <windowsx.h>
+
+#include "Platform.h"
+#include "PlatformRes.h"
+#include "UniConversion.h"
+#include "XPM.h"
+#include "FontQuality.h"
+
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+// Take care of 32/64 bit pointers
+#ifdef GetWindowLongPtr
+static void *PointerFromWindow(HWND hWnd) {
+ return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
+}
+static void SetWindowPointer(HWND hWnd, void *ptr) {
+ ::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
+}
+#else
+static void *PointerFromWindow(HWND hWnd) {
+ return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
+}
+static void SetWindowPointer(HWND hWnd, void *ptr) {
+ ::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
+}
+
+#ifndef GWLP_USERDATA
+#define GWLP_USERDATA GWL_USERDATA
+#endif
+
+#ifndef GWLP_WNDPROC
+#define GWLP_WNDPROC GWL_WNDPROC
+#endif
+
+#ifndef LONG_PTR
+#define LONG_PTR LONG
+#endif
+
+static LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong) {
+ return ::SetWindowLong(hWnd, nIndex, dwNewLong);
+}
+
+static LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) {
+ return ::GetWindowLong(hWnd, nIndex);
+}
+#endif
+
+typedef BOOL (WINAPI *AlphaBlendSig)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
+
+static CRITICAL_SECTION crPlatformLock;
+static HINSTANCE hinstPlatformRes = 0;
+static bool onNT = false;
+static HMODULE hDLLImage = 0;
+static AlphaBlendSig AlphaBlendFn = 0;
+
+
+bool IsNT() {
+ return onNT;
+}
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+Point Point::FromLong(long lpoint) {
+ return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
+}
+
+static RECT RectFromPRectangle(PRectangle prc) {
+ RECT rc = {prc.left, prc.top, prc.right, prc.bottom};
+ return rc;
+}
+
+Palette::Palette() {
+ used = 0;
+ allowRealization = false;
+ hpal = 0;
+ size = 100;
+ entries = new ColourPair[size];
+}
+
+Palette::~Palette() {
+ Release();
+ delete []entries;
+ entries = 0;
+}
+
+void Palette::Release() {
+ used = 0;
+ if (hpal)
+ ::DeleteObject(hpal);
+ hpal = 0;
+ delete []entries;
+ size = 100;
+ entries = new ColourPair[size];
+}
+
+/**
+ * This method either adds a colour to the list of wanted colours (want==true)
+ * or retrieves the allocated colour back to the ColourPair.
+ * This is one method to make it easier to keep the code for wanting and retrieving in sync.
+ */
+void Palette::WantFind(ColourPair &cp, bool want) {
+ if (want) {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired)
+ return;
+ }
+
+ if (used >= size) {
+ int sizeNew = size * 2;
+ ColourPair *entriesNew = new ColourPair[sizeNew];
+ for (int j=0; j<size; j++) {
+ entriesNew[j] = entries[j];
+ }
+ delete []entries;
+ entries = entriesNew;
+ size = sizeNew;
+ }
+
+ entries[used].desired = cp.desired;
+ entries[used].allocated.Set(cp.desired.AsLong());
+ used++;
+ } else {
+ for (int i=0; i < used; i++) {
+ if (entries[i].desired == cp.desired) {
+ cp.allocated = entries[i].allocated;
+ return;
+ }
+ }
+ cp.allocated.Set(cp.desired.AsLong());
+ }
+}
+
+void Palette::Allocate(Window &) {
+ if (hpal)
+ ::DeleteObject(hpal);
+ hpal = 0;
+
+ if (allowRealization) {
+ char *pal = new char[sizeof(LOGPALETTE) + (used-1) * sizeof(PALETTEENTRY)];
+ LOGPALETTE *logpal = reinterpret_cast<LOGPALETTE *>(pal);
+ logpal->palVersion = 0x300;
+ logpal->palNumEntries = static_cast<WORD>(used);
+ for (int iPal=0;iPal<used;iPal++) {
+ ColourDesired desired = entries[iPal].desired;
+ logpal->palPalEntry[iPal].peRed = static_cast<BYTE>(desired.GetRed());
+ logpal->palPalEntry[iPal].peGreen = static_cast<BYTE>(desired.GetGreen());
+ logpal->palPalEntry[iPal].peBlue = static_cast<BYTE>(desired.GetBlue());
+ entries[iPal].allocated.Set(
+ PALETTERGB(desired.GetRed(), desired.GetGreen(), desired.GetBlue()));
+ // PC_NOCOLLAPSE means exact colours allocated even when in background this means other windows
+ // are less likely to get their colours and also flashes more when switching windows
+ logpal->palPalEntry[iPal].peFlags = PC_NOCOLLAPSE;
+ // 0 allows approximate colours when in background, yielding moe colours to other windows
+ //logpal->palPalEntry[iPal].peFlags = 0;
+ }
+ hpal = ::CreatePalette(logpal);
+ delete []pal;
+ }
+}
+
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+
+static BYTE Win32MapFontQuality(int extraFontFlag) {
+ switch (extraFontFlag & SC_EFF_QUALITY_MASK) {
+
+ case SC_EFF_QUALITY_NON_ANTIALIASED:
+ return NONANTIALIASED_QUALITY;
+
+ case SC_EFF_QUALITY_ANTIALIASED:
+ return ANTIALIASED_QUALITY;
+
+ case SC_EFF_QUALITY_LCD_OPTIMIZED:
+ return CLEARTYPE_QUALITY;
+
+ default:
+ return SC_EFF_QUALITY_DEFAULT;
+ }
+}
+
+static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+ memset(&lf, 0, sizeof(lf));
+ // The negative is to allow for leading
+ lf.lfHeight = -(abs(size));
+ lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
+ lf.lfCharSet = static_cast<BYTE>(characterSet);
+ lf.lfQuality = Win32MapFontQuality(extraFontFlag);
+ strncpy(lf.lfFaceName, faceName, sizeof(lf.lfFaceName));
+}
+
+/**
+ * Create a hash from the parameters for a font to allow easy checking for identity.
+ * If one font is the same as another, its hash will be the same, but if the hash is the
+ * same then they may still be different.
+ */
+static int HashFont(const char *faceName, int characterSet, int size, bool bold, bool italic, int extraFontFlag) {
+ return
+ size ^
+ (characterSet << 10) ^
+ ((extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
+ (bold ? 0x10000000 : 0) ^
+ (italic ? 0x20000000 : 0) ^
+ faceName[0];
+}
+
+class FontCached : Font {
+ FontCached *next;
+ int usage;
+ LOGFONTA lf;
+ int hash;
+ FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ ~FontCached() {}
+ bool SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ virtual void Release();
+
+ static FontCached *first;
+public:
+ static FontID FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_);
+ static void ReleaseId(FontID fid_);
+};
+
+FontCached *FontCached::first = 0;
+
+FontCached::FontCached(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) :
+ next(0), usage(0), hash(0) {
+ SetLogFont(lf, faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ hash = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ fid = ::CreateFontIndirectA(&lf);
+ usage = 1;
+}
+
+bool FontCached::SameAs(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+ return
+ (lf.lfHeight == -(abs(size_))) &&
+ (lf.lfWeight == (bold_ ? FW_BOLD : FW_NORMAL)) &&
+ (lf.lfItalic == static_cast<BYTE>(italic_ ? 1 : 0)) &&
+ (lf.lfCharSet == characterSet_) &&
+ (lf.lfQuality == Win32MapFontQuality(extraFontFlag_)) &&
+ 0 == strcmp(lf.lfFaceName,faceName_);
+}
+
+void FontCached::Release() {
+ if (fid)
+ ::DeleteObject(fid);
+ fid = 0;
+}
+
+FontID FontCached::FindOrCreate(const char *faceName_, int characterSet_, int size_, bool bold_, bool italic_, int extraFontFlag_) {
+ FontID ret = 0;
+ ::EnterCriticalSection(&crPlatformLock);
+ int hashFind = HashFont(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ for (FontCached *cur=first; cur; cur=cur->next) {
+ if ((cur->hash == hashFind) &&
+ cur->SameAs(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_)) {
+ cur->usage++;
+ ret = cur->fid;
+ }
+ }
+ if (ret == 0) {
+ FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_, extraFontFlag_);
+ if (fc) {
+ fc->next = first;
+ first = fc;
+ ret = fc->fid;
+ }
+ }
+ ::LeaveCriticalSection(&crPlatformLock);
+ return ret;
+}
+
+void FontCached::ReleaseId(FontID fid_) {
+ ::EnterCriticalSection(&crPlatformLock);
+ FontCached **pcur=&first;
+ for (FontCached *cur=first; cur; cur=cur->next) {
+ if (cur->fid == fid_) {
+ cur->usage--;
+ if (cur->usage == 0) {
+ *pcur = cur->next;
+ cur->Release();
+ cur->next = 0;
+ delete cur;
+ }
+ break;
+ }
+ pcur=&cur->next;
+ }
+ ::LeaveCriticalSection(&crPlatformLock);
+}
+
+Font::Font() {
+ fid = 0;
+}
+
+Font::~Font() {
+}
+
+#define FONTS_CACHED
+
+void Font::Create(const char *faceName, int characterSet, int size,
+ bool bold, bool italic, int extraFontFlag) {
+ Release();
+#ifndef FONTS_CACHED
+ LOGFONT lf;
+ SetLogFont(lf, faceName, characterSet, size, bold, italic, extraFontFlag);
+ fid = ::CreateFontIndirect(&lf);
+#else
+ if (faceName)
+ fid = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic, extraFontFlag);
+#endif
+}
+
+void Font::Release() {
+#ifndef FONTS_CACHED
+ if (fid)
+ ::DeleteObject(fid);
+#else
+ if (fid)
+ FontCached::ReleaseId(fid);
+#endif
+ fid = 0;
+}
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class SurfaceImpl : public Surface {
+ bool unicodeMode;
+ HDC hdc;
+ bool hdcOwned;
+ HPEN pen;
+ HPEN penOld;
+ HBRUSH brush;
+ HBRUSH brushOld;
+ HFONT font;
+ HFONT fontOld;
+ HBITMAP bitmap;
+ HBITMAP bitmapOld;
+ HPALETTE paletteOld;
+ int maxWidthMeasure;
+ int maxLenText;
+
+ int codePage;
+ // If 9x OS and current code page is same as ANSI code page.
+ bool win9xACPSame;
+
+ void BrushColor(ColourAllocated back);
+ void SetFont(Font &font_);
+
+ // Private so SurfaceImpl objects can not be copied
+ SurfaceImpl(const SurfaceImpl &);
+ SurfaceImpl &operator=(const SurfaceImpl &);
+public:
+ SurfaceImpl();
+ virtual ~SurfaceImpl();
+
+ void Init(WindowID wid);
+ void Init(SurfaceID sid, WindowID wid);
+ void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
+
+ void Release();
+ bool Initialised();
+ void PenColour(ColourAllocated fore);
+ int LogPixelsY();
+ int DeviceHeightFont(int points);
+ void MoveTo(int x_, int y_);
+ void LineTo(int x_, int y_);
+ void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
+ void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void FillRectangle(PRectangle rc, ColourAllocated back);
+ void FillRectangle(PRectangle rc, Surface &surfacePattern);
+ void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int flags);
+ void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
+ void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+ void DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions);
+ void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
+ void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
+ void MeasureWidths(Font &font_, const char *s, int len, int *positions);
+ int WidthText(Font &font_, const char *s, int len);
+ int WidthChar(Font &font_, char ch);
+ int Ascent(Font &font_);
+ int Descent(Font &font_);
+ int InternalLeading(Font &font_);
+ int ExternalLeading(Font &font_);
+ int Height(Font &font_);
+ int AverageCharWidth(Font &font_);
+
+ int SetPalette(Palette *pal, bool inBackGround);
+ void SetClip(PRectangle rc);
+ void FlushCachedState();
+
+ void SetUnicodeMode(bool unicodeMode_);
+ void SetDBCSMode(int codePage_);
+};
+
+#ifdef SCI_NAMESPACE
+} //namespace Scintilla
+#endif
+
+SurfaceImpl::SurfaceImpl() :
+ unicodeMode(false),
+ hdc(0), hdcOwned(false),
+ pen(0), penOld(0),
+ brush(0), brushOld(0),
+ font(0), fontOld(0),
+ bitmap(0), bitmapOld(0),
+ paletteOld(0) {
+ // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels
+ maxWidthMeasure = IsNT() ? 1000000 : 30000;
+ // There appears to be a 16 bit string length limit in GDI on NT and a limit of
+ // 8192 characters on Windows 95.
+ maxLenText = IsNT() ? 65535 : 8192;
+
+ codePage = 0;
+ win9xACPSame = false;
+}
+
+SurfaceImpl::~SurfaceImpl() {
+ Release();
+}
+
+void SurfaceImpl::Release() {
+ if (penOld) {
+ ::SelectObject(reinterpret_cast<HDC>(hdc), penOld);
+ ::DeleteObject(pen);
+ penOld = 0;
+ }
+ pen = 0;
+ if (brushOld) {
+ ::SelectObject(reinterpret_cast<HDC>(hdc), brushOld);
+ ::DeleteObject(brush);
+ brushOld = 0;
+ }
+ brush = 0;
+ if (fontOld) {
+ // Fonts are not deleted as they are owned by a Font object
+ ::SelectObject(reinterpret_cast<HDC>(hdc), fontOld);
+ fontOld = 0;
+ }
+ font = 0;
+ if (bitmapOld) {
+ ::SelectObject(reinterpret_cast<HDC>(hdc), bitmapOld);
+ ::DeleteObject(bitmap);
+ bitmapOld = 0;
+ }
+ bitmap = 0;
+ if (paletteOld) {
+ // Palettes are not deleted as they are owned by a Palette object
+ ::SelectPalette(reinterpret_cast<HDC>(hdc),
+ reinterpret_cast<HPALETTE>(paletteOld), TRUE);
+ paletteOld = 0;
+ }
+ if (hdcOwned) {
+ ::DeleteDC(reinterpret_cast<HDC>(hdc));
+ hdc = 0;
+ hdcOwned = false;
+ }
+}
+
+bool SurfaceImpl::Initialised() {
+ return hdc != 0;
+}
+
+void SurfaceImpl::Init(WindowID) {
+ Release();
+ hdc = ::CreateCompatibleDC(NULL);
+ hdcOwned = true;
+ ::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
+}
+
+void SurfaceImpl::Init(SurfaceID sid, WindowID) {
+ Release();
+ hdc = reinterpret_cast<HDC>(sid);
+ ::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
+}
+
+void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
+ Release();
+ hdc = ::CreateCompatibleDC(static_cast<SurfaceImpl *>(surface_)->hdc);
+ hdcOwned = true;
+ bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceImpl *>(surface_)->hdc, width, height);
+ bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
+ ::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
+}
+
+void SurfaceImpl::PenColour(ColourAllocated fore) {
+ if (pen) {
+ ::SelectObject(hdc, penOld);
+ ::DeleteObject(pen);
+ pen = 0;
+ penOld = 0;
+ }
+ pen = ::CreatePen(0,1,fore.AsLong());
+ penOld = static_cast<HPEN>(::SelectObject(reinterpret_cast<HDC>(hdc), pen));
+}
+
+void SurfaceImpl::BrushColor(ColourAllocated back) {
+ if (brush) {
+ ::SelectObject(hdc, brushOld);
+ ::DeleteObject(brush);
+ brush = 0;
+ brushOld = 0;
+ }
+ // Only ever want pure, non-dithered brushes
+ ColourAllocated colourNearest = ::GetNearestColor(hdc, back.AsLong());
+ brush = ::CreateSolidBrush(colourNearest.AsLong());
+ brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
+}
+
+void SurfaceImpl::SetFont(Font &font_) {
+ if (font_.GetID() != font) {
+ if (fontOld) {
+ ::SelectObject(hdc, font_.GetID());
+ } else {
+ fontOld = static_cast<HFONT>(::SelectObject(hdc, font_.GetID()));
+ }
+ font = reinterpret_cast<HFONT>(font_.GetID());
+ }
+}
+
+int SurfaceImpl::LogPixelsY() {
+ return ::GetDeviceCaps(hdc, LOGPIXELSY);
+}
+
+int SurfaceImpl::DeviceHeightFont(int points) {
+ return ::MulDiv(points, LogPixelsY(), 72);
+}
+
+void SurfaceImpl::MoveTo(int x_, int y_) {
+ ::MoveToEx(hdc, x_, y_, 0);
+}
+
+void SurfaceImpl::LineTo(int x_, int y_) {
+ ::LineTo(hdc, x_, y_);
+}
+
+void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Polygon(hdc, reinterpret_cast<POINT *>(pts), npts);
+}
+
+void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
+ // Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
+ // There is no need to allocate a brush either.
+ RECT rcw = RectFromPRectangle(rc);
+ ::SetBkColor(hdc, back.AsLong());
+ ::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL);
+}
+
+void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+ HBRUSH br;
+ if (static_cast<SurfaceImpl &>(surfacePattern).bitmap)
+ br = ::CreatePatternBrush(static_cast<SurfaceImpl &>(surfacePattern).bitmap);
+ else // Something is wrong so display in red
+ br = ::CreateSolidBrush(RGB(0xff, 0, 0));
+ RECT rcw = RectFromPRectangle(rc);
+ ::FillRect(hdc, &rcw, br);
+ ::DeleteObject(br);
+}
+
+void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::RoundRect(hdc,
+ rc.left + 1, rc.top,
+ rc.right - 1, rc.bottom,
+ 8, 8);
+}
+
+// Plot a point into a DWORD buffer symetrically to all 4 qudrants
+static void AllFour(DWORD *pixels, int width, int height, int x, int y, DWORD val) {
+ pixels[y*width+x] = val;
+ pixels[y*width+width-1-x] = val;
+ pixels[(height-1-y)*width+x] = val;
+ pixels[(height-1-y)*width+width-1-x] = val;
+}
+
+#ifndef AC_SRC_OVER
+#define AC_SRC_OVER 0x00
+#endif
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA 0x01
+#endif
+
+static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) {
+ union {
+ byte pixVal[4];
+ DWORD val;
+ } converter;
+ converter.pixVal[0] = b;
+ converter.pixVal[1] = g;
+ converter.pixVal[2] = r;
+ converter.pixVal[3] = a;
+ return converter.val;
+}
+
+void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
+ ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
+ if (AlphaBlendFn && rc.Width() > 0) {
+ HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
+ int width = rc.Width();
+ int height = rc.Height();
+ // Ensure not distorted too much by corners when small
+ cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
+ BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
+ void *image = 0;
+ HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih,
+ DIB_RGB_COLORS, &image, NULL, 0);
+
+ HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem);
+
+ DWORD valEmpty = dwordFromBGRA(0,0,0,0);
+ DWORD valFill = dwordFromBGRA(
+ static_cast<byte>(GetBValue(fill.AsLong()) * alphaFill / 255),
+ static_cast<byte>(GetGValue(fill.AsLong()) * alphaFill / 255),
+ static_cast<byte>(GetRValue(fill.AsLong()) * alphaFill / 255),
+ static_cast<byte>(alphaFill));
+ DWORD valOutline = dwordFromBGRA(
+ static_cast<byte>(GetBValue(outline.AsLong()) * alphaOutline / 255),
+ static_cast<byte>(GetGValue(outline.AsLong()) * alphaOutline / 255),
+ static_cast<byte>(GetRValue(outline.AsLong()) * alphaOutline / 255),
+ static_cast<byte>(alphaOutline));
+ DWORD *pixels = reinterpret_cast<DWORD *>(image);
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ if ((x==0) || (x==width-1) || (y == 0) || (y == height-1)) {
+ pixels[y*width+x] = valOutline;
+ } else {
+ pixels[y*width+x] = valFill;
+ }
+ }
+ }
+ for (int c=0;c<cornerSize; c++) {
+ for (int x=0;x<c+1; x++) {
+ AllFour(pixels, width, height, x, c-x, valEmpty);
+ }
+ }
+ for (int x=1;x<cornerSize; x++) {
+ AllFour(pixels, width, height, x, cornerSize-x, valOutline);
+ }
+
+ BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, width, height, hMemDC, 0, 0, width, height, merge);
+
+ SelectBitmap(hMemDC, hbmOld);
+ ::DeleteObject(hbmMem);
+ ::DeleteDC(hMemDC);
+ } else {
+ BrushColor(outline);
+ RECT rcw = RectFromPRectangle(rc);
+ FrameRect(hdc, &rcw, brush);
+ }
+}
+
+void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
+ PenColour(fore);
+ BrushColor(back);
+ ::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+ ::BitBlt(hdc,
+ rc.left, rc.top, rc.Width(), rc.Height(),
+ static_cast<SurfaceImpl &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
+}
+
+// Buffer to hold strings and string position arrays without always allocating on heap.
+// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
+// when less than safe size otherwise allocate on heap and free automatically.
+template<typename T, int lengthStandard>
+class VarBuffer {
+ T bufferStandard[lengthStandard];
+public:
+ T *buffer;
+ VarBuffer(size_t length) : buffer(0) {
+ if (length > lengthStandard) {
+ buffer = new T[length];
+ } else {
+ buffer = bufferStandard;
+ }
+ }
+ ~VarBuffer() {
+ if (buffer != bufferStandard) {
+ delete []buffer;
+ buffer = 0;
+ }
+ }
+};
+
+const int stackBufferLength = 10000;
+class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
+public:
+ int tlen;
+ TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
+ VarBuffer<wchar_t, stackBufferLength>(len) {
+ if (unicodeMode) {
+ tlen = UTF16FromUTF8(s, len, buffer, len);
+ } else {
+ // Support Asian string display in 9x English
+ tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
+ }
+ }
+};
+typedef VarBuffer<int, stackBufferLength> TextPositions;
+
+void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) {
+ SetFont(font_);
+ RECT rcw = RectFromPRectangle(rc);
+ SIZE sz={0,0};
+ int pos = 0;
+ int x = rc.left;
+
+ // Text drawing may fail if the text is too big.
+ // If it does fail, slice up into segments and draw each segment.
+ const int maxSegmentLength = 0x200;
+
+ if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
+ // Use ANSI calls
+ int lenDraw = Platform::Minimum(len, maxLenText);
+ if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s, lenDraw, NULL)) {
+ while (lenDraw > pos) {
+ int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos);
+ if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s+pos, seglen, NULL)) {
+ PLATFORM_ASSERT(false);
+ return;
+ }
+ ::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz);
+ x += sz.cx;
+ pos += seglen;
+ }
+ }
+ } else {
+ // Use Unicode calls
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL)) {
+ while (tbuf.tlen > pos) {
+ int seglen = Platform::Minimum(maxSegmentLength, tbuf.tlen - pos);
+ if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer+pos, seglen, NULL)) {
+ PLATFORM_ASSERT(false);
+ return;
+ }
+ ::GetTextExtentPoint32W(hdc, tbuf.buffer+pos, seglen, &sz);
+ x += sz.cx;
+ pos += seglen;
+ }
+ }
+ }
+}
+
+void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ ::SetTextColor(hdc, fore.AsLong());
+ ::SetBkColor(hdc, back.AsLong());
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
+}
+
+void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore, ColourAllocated back) {
+ ::SetTextColor(hdc, fore.AsLong());
+ ::SetBkColor(hdc, back.AsLong());
+ DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
+}
+
+void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
+ ColourAllocated fore) {
+ // Avoid drawing spaces in transparent mode
+ for (int i=0;i<len;i++) {
+ if (s[i] != ' ') {
+ ::SetTextColor(hdc, fore.AsLong());
+ ::SetBkMode(hdc, TRANSPARENT);
+ DrawTextCommon(rc, font_, ybase, s, len, 0);
+ ::SetBkMode(hdc, OPAQUE);
+ return;
+ }
+ }
+}
+
+int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
+ SetFont(font_);
+ SIZE sz={0,0};
+ if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
+ ::GetTextExtentPoint32A(hdc, s, Platform::Minimum(len, maxLenText), &sz);
+ } else {
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ ::GetTextExtentPoint32W(hdc, tbuf.buffer, tbuf.tlen, &sz);
+ }
+ return sz.cx;
+}
+
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+ SetFont(font_);
+ SIZE sz={0,0};
+ int fit = 0;
+ if (unicodeMode) {
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ TextPositions poses(tbuf.tlen);
+ fit = tbuf.tlen;
+ if (!::GetTextExtentExPointW(hdc, tbuf.buffer, tbuf.tlen, maxWidthMeasure, &fit, poses.buffer, &sz)) {
+ // Likely to have failed because on Windows 9x where function not available
+ // So measure the character widths by measuring each initial substring
+ // Turns a linear operation into a qudratic but seems fast enough on test files
+ for (int widthSS=0; widthSS < tbuf.tlen; widthSS++) {
+ ::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
+ poses.buffer[widthSS] = sz.cx;
+ }
+ }
+ // Map the widths given for UTF-16 characters back onto the UTF-8 input string
+ int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ int i=0;
+ while (ui<fit) {
+ unsigned char uch = us[i];
+ unsigned int lenChar = 1;
+ if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
+ lenChar = 4;
+ ui++;
+ } else if (uch >= (0x80 + 0x40 + 0x20)) {
+ lenChar = 3;
+ } else if (uch >= (0x80)) {
+ lenChar = 2;
+ }
+ for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
+ positions[i++] = poses.buffer[ui];
+ }
+ ui++;
+ }
+ int lastPos = 0;
+ if (i > 0)
+ lastPos = positions[i-1];
+ while (i<len) {
+ positions[i++] = lastPos;
+ }
+ } else if (IsNT() || (codePage==0) || win9xACPSame) {
+ // Zero positions to avoid random behaviour on failure.
+ memset(positions, 0, len * sizeof(*positions));
+ // len may be larger than platform supports so loop over segments small enough for platform
+ int startOffset = 0;
+ while (len > 0) {
+ int lenBlock = Platform::Minimum(len, maxLenText);
+ if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, positions, &sz)) {
+ // Eeek - a NULL DC or other foolishness could cause this.
+ return;
+ } else if (fit < lenBlock) {
+ // For some reason, such as an incomplete DBCS character
+ // Not all the positions are filled in so make them equal to end.
+ for (int i=fit;i<lenBlock;i++)
+ positions[i] = positions[fit-1];
+ } else if (startOffset > 0) {
+ for (int i=0;i<lenBlock;i++)
+ positions[i] += startOffset;
+ }
+ startOffset = positions[lenBlock-1];
+ len -= lenBlock;
+ positions += lenBlock;
+ s += lenBlock;
+ }
+ } else {
+ // Support Asian string display in 9x English
+ const TextWide tbuf(s, len, unicodeMode, codePage);
+ TextPositions poses(tbuf.tlen);
+ for (int widthSS=0; widthSS<tbuf.tlen; widthSS++) {
+ ::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
+ poses.buffer[widthSS] = sz.cx;
+ }
+
+ int ui = 0;
+ for (int i=0;i<len;) {
+ if (::IsDBCSLeadByteEx(codePage, s[i])) {
+ positions[i] = poses.buffer[ui];
+ positions[i+1] = poses.buffer[ui];
+ i += 2;
+ } else {
+ positions[i] = poses.buffer[ui];
+ i++;
+ }
+
+ ui++;
+ }
+ }
+}
+
+int SurfaceImpl::WidthChar(Font &font_, char ch) {
+ SetFont(font_);
+ SIZE sz;
+ ::GetTextExtentPoint32A(hdc, &ch, 1, &sz);
+ return sz.cx;
+}
+
+int SurfaceImpl::Ascent(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmAscent;
+}
+
+int SurfaceImpl::Descent(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmDescent;
+}
+
+int SurfaceImpl::InternalLeading(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmInternalLeading;
+}
+
+int SurfaceImpl::ExternalLeading(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmExternalLeading;
+}
+
+int SurfaceImpl::Height(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmHeight;
+}
+
+int SurfaceImpl::AverageCharWidth(Font &font_) {
+ SetFont(font_);
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ return tm.tmAveCharWidth;
+}
+
+int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
+ if (paletteOld) {
+ ::SelectPalette(hdc, paletteOld, TRUE);
+ }
+ paletteOld = 0;
+ int changes = 0;
+ if (pal->allowRealization) {
+ paletteOld = ::SelectPalette(hdc,
+ reinterpret_cast<HPALETTE>(pal->hpal), inBackGround);
+ changes = ::RealizePalette(hdc);
+ }
+ return changes;
+}
+
+void SurfaceImpl::SetClip(PRectangle rc) {
+ ::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void SurfaceImpl::FlushCachedState() {
+ pen = 0;
+ brush = 0;
+ font = 0;
+}
+
+void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
+ unicodeMode=unicodeMode_;
+}
+
+void SurfaceImpl::SetDBCSMode(int codePage_) {
+ // No action on window as automatically handled by system.
+ codePage = codePage_;
+ win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP());
+}
+
+Surface *Surface::Allocate() {
+ return new SurfaceImpl;
+}
+
+Window::~Window() {
+}
+
+void Window::Destroy() {
+ if (wid)
+ ::DestroyWindow(reinterpret_cast<HWND>(wid));
+ wid = 0;
+}
+
+bool Window::HasFocus() {
+ return ::GetFocus() == wid;
+}
+
+PRectangle Window::GetPosition() {
+ RECT rc;
+ ::GetWindowRect(reinterpret_cast<HWND>(wid), &rc);
+ return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Window::SetPosition(PRectangle rc) {
+ ::SetWindowPos(reinterpret_cast<HWND>(wid),
+ 0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER|SWP_NOACTIVATE);
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window w) {
+ LONG style = ::GetWindowLong(reinterpret_cast<HWND>(wid), GWL_STYLE);
+ if (style & WS_POPUP) {
+ RECT rcOther;
+ ::GetWindowRect(reinterpret_cast<HWND>(w.GetID()), &rcOther);
+ rc.Move(rcOther.left, rcOther.top);
+
+ // Retrieve desktop bounds and make sure window popup's origin isn't left-top of the screen.
+ RECT rcDesktop = {0, 0, 0, 0};
+#ifdef SM_XVIRTUALSCREEN
+ rcDesktop.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
+ rcDesktop.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
+ rcDesktop.right = rcDesktop.left + ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ rcDesktop.bottom = rcDesktop.top + ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
+#endif
+
+ if (rc.left < rcDesktop.left) {
+ rc.Move(rcDesktop.left - rc.left,0);
+ }
+ if (rc.top < rcDesktop.top) {
+ rc.Move(0,rcDesktop.top - rc.top);
+ }
+ }
+ SetPosition(rc);
+}
+
+PRectangle Window::GetClientPosition() {
+ RECT rc={0,0,0,0};
+ if (wid)
+ ::GetClientRect(reinterpret_cast<HWND>(wid), &rc);
+ return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
+}
+
+void Window::Show(bool show) {
+ if (show)
+ ::ShowWindow(reinterpret_cast<HWND>(wid), SW_SHOWNOACTIVATE);
+ else
+ ::ShowWindow(reinterpret_cast<HWND>(wid), SW_HIDE);
+}
+
+void Window::InvalidateAll() {
+ ::InvalidateRect(reinterpret_cast<HWND>(wid), NULL, FALSE);
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+ RECT rcw = RectFromPRectangle(rc);
+ ::InvalidateRect(reinterpret_cast<HWND>(wid), &rcw, FALSE);
+}
+
+static LRESULT Window_SendMessage(Window *w, UINT msg, WPARAM wParam=0, LPARAM lParam=0) {
+ return ::SendMessage(reinterpret_cast<HWND>(w->GetID()), msg, wParam, lParam);
+}
+
+void Window::SetFont(Font &font) {
+ Window_SendMessage(this, WM_SETFONT,
+ reinterpret_cast<WPARAM>(font.GetID()), 0);
+}
+
+void Window::SetCursor(Cursor curs) {
+ switch (curs) {
+ case cursorText:
+ ::SetCursor(::LoadCursor(NULL,IDC_IBEAM));
+ break;
+ case cursorUp:
+ ::SetCursor(::LoadCursor(NULL,IDC_UPARROW));
+ break;
+ case cursorWait:
+ ::SetCursor(::LoadCursor(NULL,IDC_WAIT));
+ break;
+ case cursorHoriz:
+ ::SetCursor(::LoadCursor(NULL,IDC_SIZEWE));
+ break;
+ case cursorVert:
+ ::SetCursor(::LoadCursor(NULL,IDC_SIZENS));
+ break;
+ case cursorHand:
+ ::SetCursor(::LoadCursor(NULL,IDC_HAND));
+ break;
+ case cursorReverseArrow: {
+ if (!hinstPlatformRes)
+ hinstPlatformRes = ::GetModuleHandle(TEXT("Scintilla"));
+ if (!hinstPlatformRes)
+ hinstPlatformRes = ::GetModuleHandle(TEXT("SciLexer"));
+ if (!hinstPlatformRes)
+ hinstPlatformRes = ::GetModuleHandle(NULL);
+ HCURSOR hcursor = ::LoadCursor(hinstPlatformRes, MAKEINTRESOURCE(IDC_MARGIN));
+ if (hcursor)
+ ::SetCursor(hcursor);
+ else
+ ::SetCursor(::LoadCursor(NULL,IDC_ARROW));
+ }
+ break;
+ case cursorArrow:
+ case cursorInvalid: // Should not occur, but just in case.
+ ::SetCursor(::LoadCursor(NULL,IDC_ARROW));
+ break;
+ }
+}
+
+void Window::SetTitle(const char *s) {
+ ::SetWindowTextA(reinterpret_cast<HWND>(wid), s);
+}
+
+/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
+ coordinates */
+#ifdef MULTIPLE_MONITOR_SUPPORT
+PRectangle Window::GetMonitorRect(Point pt) {
+ // MonitorFromPoint and GetMonitorInfo are not available on Windows 95 so are not used.
+ // There could be conditional code and dynamic loading in a future version
+ // so this would work on those platforms where they are available.
+ PRectangle rcPosition = GetPosition();
+ POINT ptDesktop = {pt.x + rcPosition.left, pt.y + rcPosition.top};
+ HMONITOR hMonitor = ::MonitorFromPoint(ptDesktop, MONITOR_DEFAULTTONEAREST);
+ MONITORINFOEX mi;
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ if (::GetMonitorInfo(hMonitor, &mi)) {
+ PRectangle rcMonitor(
+ mi.rcWork.left - rcPosition.left,
+ mi.rcWork.top - rcPosition.top,
+ mi.rcWork.right - rcPosition.left,
+ mi.rcWork.bottom - rcPosition.top);
+ return rcMonitor;
+ }
+}
+#else
+PRectangle Window::GetMonitorRect(Point) {
+ return PRectangle();
+}
+#endif
+
+struct ListItemData {
+ const char *text;
+ int pixId;
+};
+
+#define _ROUND2(n,pow2) \
+ ( ( (n) + (pow2) - 1) & ~((pow2) - 1) )
+
+class LineToItem {
+ char *words;
+ int wordsCount;
+ int wordsSize;
+
+ ListItemData *data;
+ int len;
+ int count;
+
+private:
+ void FreeWords() {
+ delete []words;
+ words = NULL;
+ wordsCount = 0;
+ wordsSize = 0;
+ }
+ char *AllocWord(const char *word);
+
+public:
+ LineToItem() : words(NULL), wordsCount(0), wordsSize(0), data(NULL), len(0), count(0) {
+ }
+ ~LineToItem() {
+ Clear();
+ }
+ void Clear() {
+ FreeWords();
+ delete []data;
+ data = NULL;
+ len = 0;
+ count = 0;
+ }
+
+ ListItemData *Append(const char *text, int value);
+
+ ListItemData Get(int index) const {
+ if (index >= 0 && index < count) {
+ return data[index];
+ } else {
+ ListItemData missing = {"", -1};
+ return missing;
+ }
+ }
+ int Count() const {
+ return count;
+ }
+
+ ListItemData *AllocItem();
+
+ void SetWords(char *s) {
+ words = s; // N.B. will be deleted on destruction
+ }
+};
+
+char *LineToItem::AllocWord(const char *text) {
+ int chars = strlen(text) + 1;
+ int newCount = wordsCount + chars;
+ if (newCount > wordsSize) {
+ wordsSize = _ROUND2(newCount * 2, 8192);
+ char *wordsNew = new char[wordsSize];
+ memcpy(wordsNew, words, wordsCount);
+ int offset = wordsNew - words;
+ for (int i=0; i<count; i++)
+ data[i].text += offset;
+ delete []words;
+ words = wordsNew;
+ }
+ char *s = &words[wordsCount];
+ wordsCount = newCount;
+ strncpy(s, text, chars);
+ return s;
+}
+
+ListItemData *LineToItem::AllocItem() {
+ if (count >= len) {
+ int lenNew = _ROUND2((count+1) * 2, 1024);
+ ListItemData *dataNew = new ListItemData[lenNew];
+ memcpy(dataNew, data, count * sizeof(ListItemData));
+ delete []data;
+ data = dataNew;
+ len = lenNew;
+ }
+ ListItemData *item = &data[count];
+ count++;
+ return item;
+}
+
+ListItemData *LineToItem::Append(const char *text, int imageIndex) {
+ ListItemData *item = AllocItem();
+ item->text = AllocWord(text);
+ item->pixId = imageIndex;
+ return item;
+}
+
+const TCHAR ListBoxX_ClassName[] = TEXT("ListBoxX");
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+class ListBoxX : public ListBox {
+ int lineHeight;
+ FontID fontCopy;
+ XPMSet xset;
+ LineToItem lti;
+ HWND lb;
+ bool unicodeMode;
+ int desiredVisibleRows;
+ unsigned int maxItemCharacters;
+ unsigned int aveCharWidth;
+ Window *parent;
+ int ctrlID;
+ CallBackAction doubleClickAction;
+ void *doubleClickActionData;
+ const char *widestItem;
+ unsigned int maxCharWidth;
+ int resizeHit;
+ PRectangle rcPreSize;
+ Point dragOffset;
+ Point location; // Caret location at which the list is opened
+
+ HWND GetHWND() const;
+ void AppendListItem(const char *startword, const char *numword);
+ void AdjustWindowRect(PRectangle *rc) const;
+ int ItemHeight() const;
+ int MinClientWidth() const;
+ int TextOffset() const;
+ Point GetClientExtent() const;
+ POINT MinTrackSize() const;
+ POINT MaxTrackSize() const;
+ void SetRedraw(bool on);
+ void OnDoubleClick();
+ void ResizeToCursor();
+ void StartResize(WPARAM);
+ int NcHitTest(WPARAM, LPARAM) const;
+ void CentreItem(int);
+ void Paint(HDC);
+ void Erase(HDC);
+ static LRESULT PASCAL ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+
+ static const Point ItemInset; // Padding around whole item
+ static const Point TextInset; // Padding around text
+ static const Point ImageInset; // Padding around image
+
+public:
+ ListBoxX() : lineHeight(10), fontCopy(0), lb(0), unicodeMode(false),
+ desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8),
+ parent(NULL), ctrlID(0), doubleClickAction(NULL), doubleClickActionData(NULL),
+ widestItem(NULL), maxCharWidth(1), resizeHit(0) {
+ }
+ virtual ~ListBoxX() {
+ if (fontCopy) {
+ ::DeleteObject(fontCopy);
+ fontCopy = 0;
+ }
+ }
+ virtual void SetFont(Font &font);
+ 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);
+ virtual int Length();
+ virtual void Select(int n);
+ virtual int GetSelection();
+ virtual int Find(const char *prefix);
+ virtual void GetValue(int n, char *value, int len);
+ virtual void RegisterImage(int type, const char *xpm_data);
+ virtual void ClearRegisteredImages();
+ virtual void SetDoubleClickAction(CallBackAction action, void *data) {
+ doubleClickAction = action;
+ doubleClickActionData = data;
+ }
+ virtual void SetList(const char *list, char separator, char typesep);
+ void Draw(DRAWITEMSTRUCT *pDrawItem);
+ LRESULT WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+ static LRESULT PASCAL StaticWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+};
+
+const Point ListBoxX::ItemInset(0, 0);
+const Point ListBoxX::TextInset(2, 0);
+const Point ListBoxX::ImageInset(1, 0);
+
+ListBox *ListBox::Allocate() {
+ ListBoxX *lb = new ListBoxX();
+ return lb;
+}
+
+void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_) {
+ parent = &parent_;
+ ctrlID = ctrlID_;
+ location = location_;
+ lineHeight = lineHeight_;
+ unicodeMode = unicodeMode_;
+ HWND hwndParent = reinterpret_cast<HWND>(parent->GetID());
+ HINSTANCE hinstanceParent = GetWindowInstance(hwndParent);
+ // Window created as popup so not clipped within parent client area
+ wid = ::CreateWindowEx(
+ WS_EX_WINDOWEDGE, ListBoxX_ClassName, TEXT(""),
+ WS_POPUP | WS_THICKFRAME,
+ 100,100, 150,80, hwndParent,
+ NULL,
+ hinstanceParent,
+ this);
+
+ ::MapWindowPoints(hwndParent, NULL, reinterpret_cast<POINT*>(&location), 1);
+}
+
+void ListBoxX::SetFont(Font &font) {
+ LOGFONT lf;
+ if (0 != ::GetObject(font.GetID(), sizeof(lf), &lf)) {
+ if (fontCopy) {
+ ::DeleteObject(fontCopy);
+ fontCopy = 0;
+ }
+ fontCopy = ::CreateFontIndirect(&lf);
+ ::SendMessage(lb, WM_SETFONT, reinterpret_cast<WPARAM>(fontCopy), 0);
+ }
+}
+
+void ListBoxX::SetAverageCharWidth(int width) {
+ aveCharWidth = width;
+}
+
+void ListBoxX::SetVisibleRows(int rows) {
+ desiredVisibleRows = rows;
+}
+
+int ListBoxX::GetVisibleRows() const {
+ return desiredVisibleRows;
+}
+
+HWND ListBoxX::GetHWND() const {
+ return reinterpret_cast<HWND>(GetID());
+}
+
+PRectangle ListBoxX::GetDesiredRect() {
+ PRectangle rcDesired = GetPosition();
+
+ int rows = Length();
+ if ((rows == 0) || (rows > desiredVisibleRows))
+ rows = desiredVisibleRows;
+ rcDesired.bottom = rcDesired.top + ItemHeight() * rows;
+
+ int width = MinClientWidth();
+ HDC hdc = ::GetDC(lb);
+ HFONT oldFont = SelectFont(hdc, fontCopy);
+ SIZE textSize = {0, 0};
+ int len = widestItem ? strlen(widestItem) : 0;
+ if (unicodeMode) {
+ const TextWide tbuf(widestItem, len, unicodeMode);
+ ::GetTextExtentPoint32W(hdc, tbuf.buffer, tbuf.tlen, &textSize);
+ } else {
+ ::GetTextExtentPoint32A(hdc, widestItem, len, &textSize);
+ }
+ TEXTMETRIC tm;
+ ::GetTextMetrics(hdc, &tm);
+ maxCharWidth = tm.tmMaxCharWidth;
+ SelectFont(hdc, oldFont);
+ ::ReleaseDC(lb, hdc);
+
+ int widthDesired = Platform::Maximum(textSize.cx, (len + 1) * tm.tmAveCharWidth);
+ if (width < widthDesired)
+ width = widthDesired;
+
+ rcDesired.right = rcDesired.left + TextOffset() + width + (TextInset.x * 2);
+ if (Length() > rows)
+ rcDesired.right += ::GetSystemMetrics(SM_CXVSCROLL);
+
+ AdjustWindowRect(&rcDesired);
+ return rcDesired;
+}
+
+int ListBoxX::TextOffset() const {
+ int pixWidth = const_cast<XPMSet*>(&xset)->GetWidth();
+ return pixWidth == 0 ? ItemInset.x : ItemInset.x + pixWidth + (ImageInset.x * 2);
+}
+
+int ListBoxX::CaretFromEdge() {
+ PRectangle rc;
+ AdjustWindowRect(&rc);
+ return TextOffset() + TextInset.x + (0 - rc.left) - 1;
+}
+
+void ListBoxX::Clear() {
+ ::SendMessage(lb, LB_RESETCONTENT, 0, 0);
+ maxItemCharacters = 0;
+ widestItem = NULL;
+ lti.Clear();
+}
+
+void ListBoxX::Append(char *s, int type) {
+ int index = ::SendMessage(lb, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(s));
+ if (index < 0)
+ return;
+ ListItemData *newItem = lti.Append(s, type);
+ unsigned int len = static_cast<unsigned int>(strlen(s));
+ if (maxItemCharacters < len) {
+ maxItemCharacters = len;
+ widestItem = newItem->text;
+ }
+}
+
+int ListBoxX::Length() {
+ return lti.Count();
+}
+
+void ListBoxX::Select(int n) {
+ // We are going to scroll to centre on the new selection and then select it, so disable
+ // redraw to avoid flicker caused by a painting new selection twice in unselected and then
+ // selected states
+ SetRedraw(false);
+ CentreItem(n);
+ ::SendMessage(lb, LB_SETCURSEL, n, 0);
+ SetRedraw(true);
+}
+
+int ListBoxX::GetSelection() {
+ return ::SendMessage(lb, LB_GETCURSEL, 0, 0);
+}
+
+// This is not actually called at present
+int ListBoxX::Find(const char *) {
+ return LB_ERR;
+}
+
+void ListBoxX::GetValue(int n, char *value, int len) {
+ ListItemData item = lti.Get(n);
+ strncpy(value, item.text, len);
+ value[len-1] = '\0';
+}
+
+void ListBoxX::RegisterImage(int type, const char *xpm_data) {
+ xset.Add(type, xpm_data);
+}
+
+void ListBoxX::ClearRegisteredImages() {
+ xset.Clear();
+}
+
+void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
+ if ((pDrawItem->itemAction == ODA_SELECT) || (pDrawItem->itemAction == ODA_DRAWENTIRE)) {
+ RECT rcBox = pDrawItem->rcItem;
+ rcBox.left += TextOffset();
+ if (pDrawItem->itemState & ODS_SELECTED) {
+ RECT rcImage = pDrawItem->rcItem;
+ rcImage.right = rcBox.left;
+ // The image is not highlighted
+ ::FillRect(pDrawItem->hDC, &rcImage, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
+ ::FillRect(pDrawItem->hDC, &rcBox, reinterpret_cast<HBRUSH>(COLOR_HIGHLIGHT+1));
+ ::SetBkColor(pDrawItem->hDC, ::GetSysColor(COLOR_HIGHLIGHT));
+ ::SetTextColor(pDrawItem->hDC, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
+ } else {
+ ::FillRect(pDrawItem->hDC, &pDrawItem->rcItem, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
+ ::SetBkColor(pDrawItem->hDC, ::GetSysColor(COLOR_WINDOW));
+ ::SetTextColor(pDrawItem->hDC, ::GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ ListItemData item = lti.Get(pDrawItem->itemID);
+ int pixId = item.pixId;
+ const char *text = item.text;
+ int len = strlen(text);
+
+ RECT rcText = rcBox;
+ ::InsetRect(&rcText, TextInset.x, TextInset.y);
+
+ if (unicodeMode) {
+ const TextWide tbuf(text, len, unicodeMode);
+ ::DrawTextW(pDrawItem->hDC, tbuf.buffer, tbuf.tlen, &rcText, DT_NOPREFIX|DT_END_ELLIPSIS|DT_SINGLELINE|DT_NOCLIP);
+ } else {
+ ::DrawTextA(pDrawItem->hDC, text, len, &rcText, DT_NOPREFIX|DT_END_ELLIPSIS|DT_SINGLELINE|DT_NOCLIP);
+ }
+ if (pDrawItem->itemState & ODS_SELECTED) {
+ ::DrawFocusRect(pDrawItem->hDC, &rcBox);
+ }
+
+ // Draw the image, if any
+ XPM *pxpm = xset.Get(pixId);
+ if (pxpm) {
+ Surface *surfaceItem = Surface::Allocate();
+ if (surfaceItem) {
+ surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
+ //surfaceItem->SetUnicodeMode(unicodeMode);
+ //surfaceItem->SetDBCSMode(codePage);
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + xset.GetWidth(), pDrawItem->rcItem.bottom);
+ pxpm->Draw(surfaceItem, rcImage);
+ delete surfaceItem;
+ ::SetTextAlign(pDrawItem->hDC, TA_TOP);
+ }
+ }
+ }
+}
+
+void ListBoxX::AppendListItem(const char *startword, const char *numword) {
+ ListItemData *item = lti.AllocItem();
+ item->text = startword;
+ if (numword) {
+ int pixId = 0;
+ char ch;
+ while ((ch = *++numword) != '\0') {
+ pixId = 10 * pixId + (ch - '0');
+ }
+ item->pixId = pixId;
+ } else {
+ item->pixId = -1;
+ }
+
+ unsigned int len = static_cast<unsigned int>(strlen(item->text));
+ if (maxItemCharacters < len) {
+ maxItemCharacters = len;
+ widestItem = item->text;
+ }
+}
+
+void ListBoxX::SetList(const char *list, char separator, char typesep) {
+ // Turn off redraw while populating the list - this has a significant effect, even if
+ // the listbox is not visible.
+ SetRedraw(false);
+ Clear();
+ int size = strlen(list) + 1;
+ char *words = new char[size];
+ lti.SetWords(words);
+ memcpy(words, list, size);
+ char *startword = words;
+ char *numword = NULL;
+ int i = 0;
+ for (; words[i]; i++) {
+ if (words[i] == separator) {
+ words[i] = '\0';
+ if (numword)
+ *numword = '\0';
+ AppendListItem(startword, numword);
+ startword = words + i + 1;
+ numword = NULL;
+ } else if (words[i] == typesep) {
+ numword = words + i;
+ }
+ }
+ if (startword) {
+ if (numword)
+ *numword = '\0';
+ AppendListItem(startword, numword);
+ }
+
+ // Finally populate the listbox itself with the correct number of items
+ int count = lti.Count();
+ ::SendMessage(lb, LB_INITSTORAGE, count, 0);
+ for (int j=0; j<count; j++) {
+ ::SendMessage(lb, LB_ADDSTRING, 0, j+1);
+ }
+ SetRedraw(true);
+}
+
+void ListBoxX::AdjustWindowRect(PRectangle *rc) const {
+ ::AdjustWindowRectEx(reinterpret_cast<RECT*>(rc), WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
+}
+
+int ListBoxX::ItemHeight() const {
+ int itemHeight = lineHeight + (TextInset.y * 2);
+ int pixHeight = const_cast<XPMSet*>(&xset)->GetHeight() + (ImageInset.y * 2);
+ if (itemHeight < pixHeight) {
+ itemHeight = pixHeight;
+ }
+ return itemHeight;
+}
+
+int ListBoxX::MinClientWidth() const {
+ return 12 * (aveCharWidth+aveCharWidth/3);
+}
+
+POINT ListBoxX::MinTrackSize() const {
+ PRectangle rc(0, 0, MinClientWidth(), ItemHeight());
+ AdjustWindowRect(&rc);
+ POINT ret = {rc.Width(), rc.Height()};
+ return ret;
+}
+
+POINT ListBoxX::MaxTrackSize() const {
+ PRectangle rc(0, 0,
+ maxCharWidth * maxItemCharacters + TextInset.x * 2 +
+ TextOffset() + ::GetSystemMetrics(SM_CXVSCROLL),
+ ItemHeight() * lti.Count());
+ AdjustWindowRect(&rc);
+ POINT ret = {rc.Width(), rc.Height()};
+ return ret;
+}
+
+void ListBoxX::SetRedraw(bool on) {
+ ::SendMessage(lb, WM_SETREDRAW, static_cast<BOOL>(on), 0);
+ if (on)
+ ::InvalidateRect(lb, NULL, TRUE);
+}
+
+void ListBoxX::ResizeToCursor() {
+ PRectangle rc = GetPosition();
+ Point pt;
+ ::GetCursorPos(reinterpret_cast<POINT*>(&pt));
+ pt.x += dragOffset.x;
+ pt.y += dragOffset.y;
+
+ switch (resizeHit) {
+ case HTLEFT:
+ rc.left = pt.x;
+ break;
+ case HTRIGHT:
+ rc.right = pt.x;
+ break;
+ case HTTOP:
+ rc.top = pt.y;
+ break;
+ case HTTOPLEFT:
+ rc.top = pt.y;
+ rc.left = pt.x;
+ break;
+ case HTTOPRIGHT:
+ rc.top = pt.y;
+ rc.right = pt.x;
+ break;
+ case HTBOTTOM:
+ rc.bottom = pt.y;
+ break;
+ case HTBOTTOMLEFT:
+ rc.bottom = pt.y;
+ rc.left = pt.x;
+ break;
+ case HTBOTTOMRIGHT:
+ rc.bottom = pt.y;
+ rc.right = pt.x;
+ break;
+ }
+
+ POINT ptMin = MinTrackSize();
+ POINT ptMax = MaxTrackSize();
+ // We don't allow the left edge to move at present, but just in case
+ rc.left = Platform::Maximum(Platform::Minimum(rc.left, rcPreSize.right - ptMin.x), rcPreSize.right - ptMax.x);
+ rc.top = Platform::Maximum(Platform::Minimum(rc.top, rcPreSize.bottom - ptMin.y), rcPreSize.bottom - ptMax.y);
+ rc.right = Platform::Maximum(Platform::Minimum(rc.right, rcPreSize.left + ptMax.x), rcPreSize.left + ptMin.x);
+ rc.bottom = Platform::Maximum(Platform::Minimum(rc.bottom, rcPreSize.top + ptMax.y), rcPreSize.top + ptMin.y);
+
+ SetPosition(rc);
+}
+
+void ListBoxX::StartResize(WPARAM hitCode) {
+ rcPreSize = GetPosition();
+ POINT cursorPos;
+ ::GetCursorPos(&cursorPos);
+
+ switch (hitCode) {
+ case HTRIGHT:
+ case HTBOTTOM:
+ case HTBOTTOMRIGHT:
+ dragOffset.x = rcPreSize.right - cursorPos.x;
+ dragOffset.y = rcPreSize.bottom - cursorPos.y;
+ break;
+
+ case HTTOPRIGHT:
+ dragOffset.x = rcPreSize.right - cursorPos.x;
+ dragOffset.y = rcPreSize.top - cursorPos.y;
+ break;
+
+ // Note that the current hit test code prevents the left edge cases ever firing
+ // as we don't want the left edge to be moveable
+ case HTLEFT:
+ case HTTOP:
+ case HTTOPLEFT:
+ dragOffset.x = rcPreSize.left - cursorPos.x;
+ dragOffset.y = rcPreSize.top - cursorPos.y;
+ break;
+ case HTBOTTOMLEFT:
+ dragOffset.x = rcPreSize.left - cursorPos.x;
+ dragOffset.y = rcPreSize.bottom - cursorPos.y;
+ break;
+
+ default:
+ return;
+ }
+
+ ::SetCapture(GetHWND());
+ resizeHit = hitCode;
+}
+
+int ListBoxX::NcHitTest(WPARAM wParam, LPARAM lParam) const {
+ int hit = ::DefWindowProc(GetHWND(), WM_NCHITTEST, wParam, lParam);
+ // There is an apparent bug in the DefWindowProc hit test code whereby it will
+ // return HTTOPXXX if the window in question is shorter than the default
+ // window caption height + frame, even if one is hovering over the bottom edge of
+ // the frame, so workaround that here
+ if (hit >= HTTOP && hit <= HTTOPRIGHT) {
+ int minHeight = GetSystemMetrics(SM_CYMINTRACK);
+ PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
+ int yPos = GET_Y_LPARAM(lParam);
+ if ((rc.Height() < minHeight) && (yPos > ((rc.top + rc.bottom)/2))) {
+ hit += HTBOTTOM - HTTOP;
+ }
+ }
+
+ // Nerver permit resizing that moves the left edge. Allow movement of top or bottom edge
+ // depending on whether the list is above or below the caret
+ switch (hit) {
+ case HTLEFT:
+ case HTTOPLEFT:
+ case HTBOTTOMLEFT:
+ hit = HTERROR;
+ break;
+
+ case HTTOP:
+ case HTTOPRIGHT: {
+ PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
+ // Valid only if caret below list
+ if (location.y < rc.top)
+ hit = HTERROR;
+ }
+ break;
+
+ case HTBOTTOM:
+ case HTBOTTOMRIGHT: {
+ PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
+ // Valid only if caret above list
+ if (rc.bottom < location.y)
+ hit = HTERROR;
+ }
+ break;
+ }
+
+ return hit;
+}
+
+void ListBoxX::OnDoubleClick() {
+
+ if (doubleClickAction != NULL) {
+ doubleClickAction(doubleClickActionData);
+ }
+}
+
+Point ListBoxX::GetClientExtent() const {
+ PRectangle rc = const_cast<ListBoxX*>(this)->GetClientPosition();
+ return Point(rc.Width(), rc.Height());
+}
+
+void ListBoxX::CentreItem(int n) {
+ // If below mid point, scroll up to centre, but with more items below if uneven
+ if (n >= 0) {
+ Point extent = GetClientExtent();
+ int visible = extent.y/ItemHeight();
+ if (visible < Length()) {
+ int top = ::SendMessage(lb, LB_GETTOPINDEX, 0, 0);
+ int half = (visible - 1) / 2;
+ if (n > (top + half))
+ ::SendMessage(lb, LB_SETTOPINDEX, n - half , 0);
+ }
+ }
+}
+
+// Performs a double-buffered paint operation to avoid flicker
+void ListBoxX::Paint(HDC hDC) {
+ Point extent = GetClientExtent();
+ HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, extent.x, extent.y);
+ HDC bitmapDC = ::CreateCompatibleDC(hDC);
+ HBITMAP hBitmapOld = SelectBitmap(bitmapDC, hBitmap);
+ // The list background is mainly erased during painting, but can be a small
+ // unpainted area when at the end of a non-integrally sized list with a
+ // vertical scroll bar
+ RECT rc = { 0, 0, extent.x, extent.y };
+ ::FillRect(bitmapDC, &rc, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
+ // Paint the entire client area and vertical scrollbar
+ ::SendMessage(lb, WM_PRINT, reinterpret_cast<WPARAM>(bitmapDC), PRF_CLIENT|PRF_NONCLIENT);
+ ::BitBlt(hDC, 0, 0, extent.x, extent.y, bitmapDC, 0, 0, SRCCOPY);
+ // Select a stock brush to prevent warnings from BoundsChecker
+ ::SelectObject(bitmapDC, GetStockFont(WHITE_BRUSH));
+ SelectBitmap(bitmapDC, hBitmapOld);
+ ::DeleteDC(bitmapDC);
+ ::DeleteObject(hBitmap);
+}
+
+LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ try {
+ switch (uMsg) {
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hDC = ::BeginPaint(hWnd, &ps);
+ ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(::GetParent(hWnd)));
+ if (lbx)
+ lbx->Paint(hDC);
+ ::EndPaint(hWnd, &ps);
+ }
+ return 0;
+
+ case WM_MOUSEACTIVATE:
+ // This prevents the view activating when the scrollbar is clicked
+ return MA_NOACTIVATE;
+
+ case WM_LBUTTONDOWN: {
+ // We must take control of selection to prevent the ListBox activating
+ // the popup
+ LRESULT lResult = ::SendMessage(hWnd, LB_ITEMFROMPOINT, 0, lParam);
+ int item = LOWORD(lResult);
+ if (HIWORD(lResult) == 0 && item >= 0) {
+ ::SendMessage(hWnd, LB_SETCURSEL, item, 0);
+ }
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ return 0;
+
+ case WM_LBUTTONDBLCLK: {
+ ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(::GetParent(hWnd)));
+ if (lbx) {
+ lbx->OnDoubleClick();
+ }
+ }
+ return 0;
+ }
+
+ WNDPROC prevWndProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ if (prevWndProc) {
+ return ::CallWindowProc(prevWndProc, hWnd, uMsg, wParam, lParam);
+ } else {
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+ } catch (...) {
+ }
+ return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ switch (iMessage) {
+ case WM_CREATE: {
+ HINSTANCE hinstanceParent = GetWindowInstance(reinterpret_cast<HWND>(parent->GetID()));
+ // Note that LBS_NOINTEGRALHEIGHT is specified to fix cosmetic issue when resizing the list
+ // but has useful side effect of speeding up list population significantly
+ lb = ::CreateWindowEx(
+ 0, TEXT("listbox"), TEXT(""),
+ WS_CHILD | WS_VSCROLL | WS_VISIBLE |
+ LBS_OWNERDRAWFIXED | LBS_NODATA | LBS_NOINTEGRALHEIGHT,
+ 0, 0, 150,80, hWnd,
+ reinterpret_cast<HMENU>(ctrlID),
+ hinstanceParent,
+ 0);
+ WNDPROC prevWndProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(lb, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ControlWndProc)));
+ ::SetWindowLongPtr(lb, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(prevWndProc));
+ }
+ break;
+
+ case WM_SIZE:
+ if (lb) {
+ SetRedraw(false);
+ ::SetWindowPos(lb, 0, 0,0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
+ // Ensure the selection remains visible
+ CentreItem(GetSelection());
+ SetRedraw(true);
+ }
+ break;
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ ::BeginPaint(hWnd, &ps);
+ ::EndPaint(hWnd, &ps);
+ }
+ break;
+
+ case WM_COMMAND:
+ // This is not actually needed now - the registered double click action is used
+ // directly to action a choice from the list.
+ ::SendMessage(reinterpret_cast<HWND>(parent->GetID()), iMessage, wParam, lParam);
+ break;
+
+ case WM_MEASUREITEM: {
+ MEASUREITEMSTRUCT *pMeasureItem = reinterpret_cast<MEASUREITEMSTRUCT *>(lParam);
+ pMeasureItem->itemHeight = static_cast<unsigned int>(ItemHeight());
+ }
+ break;
+
+ case WM_DRAWITEM:
+ Draw(reinterpret_cast<DRAWITEMSTRUCT *>(lParam));
+ break;
+
+ case WM_DESTROY:
+ lb = 0;
+ ::SetWindowLong(hWnd, 0, 0);
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+
+ case WM_ERASEBKGND:
+ // To reduce flicker we can elide background erasure since this window is
+ // completely covered by its child.
+ return TRUE;
+
+ case WM_GETMINMAXINFO: {
+ MINMAXINFO *minMax = reinterpret_cast<MINMAXINFO*>(lParam);
+ minMax->ptMaxTrackSize = MaxTrackSize();
+ minMax->ptMinTrackSize = MinTrackSize();
+ }
+ break;
+
+ case WM_MOUSEACTIVATE:
+ return MA_NOACTIVATE;
+
+ case WM_NCHITTEST:
+ return NcHitTest(wParam, lParam);
+
+ case WM_NCLBUTTONDOWN:
+ // We have to implement our own window resizing because the DefWindowProc
+ // implementation insists on activating the resized window
+ StartResize(wParam);
+ return 0;
+
+ case WM_MOUSEMOVE: {
+ if (resizeHit == 0) {
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else {
+ ResizeToCursor();
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_CANCELMODE:
+ if (resizeHit != 0) {
+ resizeHit = 0;
+ ::ReleaseCapture();
+ }
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+
+ default:
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+
+ return 0;
+}
+
+LRESULT PASCAL ListBoxX::StaticWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+ if (iMessage == WM_CREATE) {
+ CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
+ SetWindowPointer(hWnd, pCreate->lpCreateParams);
+ }
+ // Find C++ object associated with window.
+ ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(hWnd));
+ if (lbx) {
+ return lbx->WndProc(hWnd, iMessage, wParam, lParam);
+ } else {
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+}
+
+static bool ListBoxX_Register() {
+ WNDCLASSEX wndclassc;
+ wndclassc.cbSize = sizeof(wndclassc);
+ // We need CS_HREDRAW and CS_VREDRAW because of the ellipsis that might be drawn for
+ // truncated items in the list and the appearance/disappearance of the vertical scroll bar.
+ // The list repaint is double-buffered to avoid the flicker this would otherwise cause.
+ wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclassc.cbClsExtra = 0;
+ wndclassc.cbWndExtra = sizeof(ListBoxX *);
+ wndclassc.hInstance = hinstPlatformRes;
+ wndclassc.hIcon = NULL;
+ wndclassc.hbrBackground = NULL;
+ wndclassc.lpszMenuName = NULL;
+ wndclassc.lpfnWndProc = ListBoxX::StaticWndProc;
+ wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ wndclassc.lpszClassName = ListBoxX_ClassName;
+ wndclassc.hIconSm = 0;
+
+ return ::RegisterClassEx(&wndclassc) != 0;
+}
+
+bool ListBoxX_Unregister() {
+ return ::UnregisterClass(ListBoxX_ClassName, hinstPlatformRes) != 0;
+}
+
+Menu::Menu() : mid(0) {
+}
+
+void Menu::CreatePopUp() {
+ Destroy();
+ mid = ::CreatePopupMenu();
+}
+
+void Menu::Destroy() {
+ if (mid)
+ ::DestroyMenu(reinterpret_cast<HMENU>(mid));
+ mid = 0;
+}
+
+void Menu::Show(Point pt, Window &w) {
+ ::TrackPopupMenu(reinterpret_cast<HMENU>(mid),
+ 0, pt.x - 4, pt.y, 0,
+ reinterpret_cast<HWND>(w.GetID()), NULL);
+ Destroy();
+}
+
+static bool initialisedET = false;
+static bool usePerformanceCounter = false;
+static LARGE_INTEGER frequency;
+
+ElapsedTime::ElapsedTime() {
+ if (!initialisedET) {
+ usePerformanceCounter = ::QueryPerformanceFrequency(&frequency) != 0;
+ initialisedET = true;
+ }
+ if (usePerformanceCounter) {
+ LARGE_INTEGER timeVal;
+ ::QueryPerformanceCounter(&timeVal);
+ bigBit = timeVal.HighPart;
+ littleBit = timeVal.LowPart;
+ } else {
+ bigBit = clock();
+ }
+}
+
+double ElapsedTime::Duration(bool reset) {
+ double result;
+ long endBigBit;
+ long endLittleBit;
+
+ if (usePerformanceCounter) {
+ LARGE_INTEGER lEnd;
+ ::QueryPerformanceCounter(&lEnd);
+ endBigBit = lEnd.HighPart;
+ endLittleBit = lEnd.LowPart;
+ LARGE_INTEGER lBegin;
+ lBegin.HighPart = bigBit;
+ lBegin.LowPart = littleBit;
+ double elapsed = lEnd.QuadPart - lBegin.QuadPart;
+ result = elapsed / static_cast<double>(frequency.QuadPart);
+ } else {
+ endBigBit = clock();
+ endLittleBit = 0;
+ double elapsed = endBigBit - bigBit;
+ result = elapsed / CLOCKS_PER_SEC;
+ }
+ if (reset) {
+ bigBit = endBigBit;
+ littleBit = endLittleBit;
+ }
+ return result;
+}
+
+class DynamicLibraryImpl : public DynamicLibrary {
+protected:
+ HMODULE h;
+public:
+ DynamicLibraryImpl(const char *modulePath) {
+ h = ::LoadLibraryA(modulePath);
+ }
+
+ virtual ~DynamicLibraryImpl() {
+ if (h != NULL)
+ ::FreeLibrary(h);
+ }
+
+ // Use GetProcAddress to get a pointer to the relevant function.
+ virtual Function FindFunction(const char *name) {
+ if (h != NULL) {
+ // C++ standard doesn't like casts betwen function pointers and void pointers so use a union
+ union {
+ FARPROC fp;
+ Function f;
+ } fnConv;
+ fnConv.fp = ::GetProcAddress(h, name);
+ return fnConv.f;
+ } else
+ return NULL;
+ }
+
+ virtual bool IsValid() {
+ return h != NULL;
+ }
+};
+
+DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
+ return static_cast<DynamicLibrary *>(new DynamicLibraryImpl(modulePath));
+}
+
+ColourDesired Platform::Chrome() {
+ return ::GetSysColor(COLOR_3DFACE);
+}
+
+ColourDesired Platform::ChromeHighlight() {
+ return ::GetSysColor(COLOR_3DHIGHLIGHT);
+}
+
+const char *Platform::DefaultFont() {
+ return "Verdana";
+}
+
+int Platform::DefaultFontSize() {
+ return 8;
+}
+
+unsigned int Platform::DoubleClickTime() {
+ return ::GetDoubleClickTime();
+}
+
+bool Platform::MouseButtonBounce() {
+ return false;
+}
+
+void Platform::DebugDisplay(const char *s) {
+ ::OutputDebugStringA(s);
+}
+
+bool Platform::IsKeyDown(int key) {
+ return (::GetKeyState(key) & 0x80000000) != 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));
+}
+
+bool Platform::IsDBCSLeadByte(int codePage, char ch) {
+ return ::IsDBCSLeadByteEx(codePage, ch) != 0;
+}
+
+int Platform::DBCSCharLength(int codePage, const char *s) {
+ return (::IsDBCSLeadByteEx(codePage, s[0]) != 0) ? 2 : 1;
+}
+
+int Platform::DBCSCharMaxLength() {
+ return 2;
+}
+
+// These are utility functions not really tied to a platform
+
+int Platform::Minimum(int a, int b) {
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int Platform::Maximum(int a, int b) {
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+//#define TRACE
+
+#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
+
+static bool assertionPopUps = true;
+
+bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
+ bool ret = assertionPopUps;
+ assertionPopUps = assertionPopUps_;
+ return ret;
+}
+
+void Platform::Assert(const char *c, const char *file, int line) {
+ char buffer[2000];
+ sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
+ if (assertionPopUps) {
+ int idButton = ::MessageBoxA(0, buffer, "Assertion failure",
+ MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
+ if (idButton == IDRETRY) {
+ ::DebugBreak();
+ } else if (idButton == IDIGNORE) {
+ // all OK
+ } else {
+ abort();
+ }
+ } else {
+ strcat(buffer, "\r\n");
+ Platform::DebugDisplay(buffer);
+ ::DebugBreak();
+ abort();
+ }
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+ if (val > maxVal)
+ val = maxVal;
+ if (val < minVal)
+ val = minVal;
+ return val;
+}
+
+void Platform_Initialise(void *hInstance) {
+ OSVERSIONINFO osv = {sizeof(OSVERSIONINFO),0,0,0,0,TEXT("")};
+ ::GetVersionEx(&osv);
+ onNT = osv.dwPlatformId == VER_PLATFORM_WIN32_NT;
+ ::InitializeCriticalSection(&crPlatformLock);
+ hinstPlatformRes = reinterpret_cast<HINSTANCE>(hInstance);
+ // This may be called from DllMain, in which case the call to LoadLibrary
+ // is bad because it can upset the DLL load order.
+ if (!hDLLImage) {
+ hDLLImage = ::LoadLibrary(TEXT("Msimg32"));
+ }
+ if (hDLLImage) {
+ AlphaBlendFn = (AlphaBlendSig)::GetProcAddress(hDLLImage, "AlphaBlend");
+ }
+ ListBoxX_Register();
+}
+
+void Platform_Finalise() {
+ ListBoxX_Unregister();
+ ::DeleteCriticalSection(&crPlatformLock);
+}
diff --git a/scintilla/win32/PlatformRes.h b/scintilla/win32/PlatformRes.h
new file mode 100644
index 0000000..6a3c23f
--- /dev/null
+++ b/scintilla/win32/PlatformRes.h
@@ -0,0 +1,8 @@
+// Scintilla source code edit control
+/** @file PlatformRes.h
+ ** Defines IDs of resources used by Scintilla on Windows platform.
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#define IDC_MARGIN 400
diff --git a/scintilla/win32/SciTE.properties b/scintilla/win32/SciTE.properties
new file mode 100644
index 0000000..d90fa09
--- /dev/null
+++ b/scintilla/win32/SciTE.properties
@@ -0,0 +1,21 @@
+command.build.SConstruct=scons.bat .
+command.name.1.SConstruct=scons clean
+command.1.SConstruct=scons.bat --clean .
+
+command.build.*.mak=nmake -f $(FileNameExt) DEBUG=1 QUIET=1
+command.name.1.*.mak=nmake clean
+command.1.*.mak=nmake -f $(FileNameExt) clean
+command.name.2.*.mak=Borland Make
+command.2.*.mak=make -f $(FileNameExt)
+command.subsystem.2.*.mak=0
+command.name.3.*.mak=make clean
+command.3.*.mak=make -f $(FileNameExt) clean
+command.name.4.*.mak=make debug
+command.4.*.mak=make DEBUG=1 -f $(FileNameExt)
+command.name.5.*.mak=nmake debug
+command.5.*.mak=nmake DEBUG=1 -f $(FileNameExt)
+# SciTE.properties is the per directory local options file and can be used to override
+# settings made in SciTEGlobal.properties
+command.build.*.cxx=nmake -f scintilla.mak DEBUG=1 QUIET=1
+command.build.*.h=nmake -f scintilla.mak DEBUG=1 QUIET=1
+command.build.*.rc=nmake -f scintilla.mak DEBUG=1 QUIET=1
diff --git a/scintilla/win32/ScintRes.rc b/scintilla/win32/ScintRes.rc
new file mode 100644
index 0000000..24d39b7
--- /dev/null
+++ b/scintilla/win32/ScintRes.rc
@@ -0,0 +1,40 @@
+// Resource file for Scintilla
+// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef __BORLANDC__
+#include <windows.h>
+#endif
+
+#include "PlatformRes.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 2, 1, 2, 0
+PRODUCTVERSION 2, 1, 2, 0
+FILEFLAGSMASK 0x3fL
+FILEFLAGS 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Neil Hodgson neilh@scintilla.org\0"
+ VALUE "FileDescription", "Scintilla.DLL - a Source Editing Component\0"
+ VALUE "FileVersion", "2.12\0"
+ VALUE "InternalName", "Scintilla\0"
+ VALUE "LegalCopyright", "Copyright 1998-2010 by Neil Hodgson\0"
+ VALUE "OriginalFilename", "Scintilla.DLL\0"
+ VALUE "ProductName", "Scintilla\0"
+ VALUE "ProductVersion", "2.12\0"
+ END
+ END
+END
+
+IDC_MARGIN CURSOR DISCARDABLE "Margin.cur"
diff --git a/scintilla/win32/Scintilla.def b/scintilla/win32/Scintilla.def
new file mode 100644
index 0000000..9ddb3c5
--- /dev/null
+++ b/scintilla/win32/Scintilla.def
@@ -0,0 +1,2 @@
+EXPORTS
+ Scintilla_DirectFunction \ No newline at end of file
diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx
new file mode 100644
index 0000000..2aa17f8
--- /dev/null
+++ b/scintilla/win32/ScintillaWin.cxx
@@ -0,0 +1,2722 @@
+// Scintilla source code edit control
+/** @file ScintillaWin.cxx
+ ** Windows specific subclass of ScintillaBase.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <new>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+
+#include <string>
+#include <vector>
+
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <windowsx.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "PropSetSimple.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "AutoComplete.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+#include "UniConversion.h"
+
+#ifdef SCI_LEXER
+#include "ExternalLexer.h"
+#endif
+
+#ifndef SPI_GETWHEELSCROLLLINES
+#define SPI_GETWHEELSCROLLLINES 104
+#endif
+
+#ifndef WM_UNICHAR
+#define WM_UNICHAR 0x0109
+#endif
+
+#ifndef UNICODE_NOCHAR
+#define UNICODE_NOCHAR 0xFFFF
+#endif
+
+#ifndef WM_IME_STARTCOMPOSITION
+#include <imm.h>
+#endif
+
+#include <commctrl.h>
+#ifndef __BORLANDC__
+#ifndef __DMC__
+#include <zmouse.h>
+#endif
+#endif
+#include <ole2.h>
+
+#ifndef MK_ALT
+#define MK_ALT 32
+#endif
+
+#define SC_WIN_IDLE 5001
+
+// Functions imported from PlatWin
+extern bool IsNT();
+extern void Platform_Initialise(void *hInstance);
+extern void Platform_Finalise();
+
+typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT);
+
+// GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.
+
+const TCHAR scintillaClassName[] = TEXT("Scintilla");
+const TCHAR callClassName[] = TEXT("CallTip");
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+class ScintillaWin; // Forward declaration for COM interface subobjects
+
+typedef void VFunction(void);
+
+/**
+ */
+class FormatEnumerator {
+public:
+ VFunction **vtbl;
+ int ref;
+ int pos;
+ CLIPFORMAT formats[2];
+ int formatsLen;
+ FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_);
+};
+
+/**
+ */
+class DropSource {
+public:
+ VFunction **vtbl;
+ ScintillaWin *sci;
+ DropSource();
+};
+
+/**
+ */
+class DataObject {
+public:
+ VFunction **vtbl;
+ ScintillaWin *sci;
+ DataObject();
+};
+
+/**
+ */
+class DropTarget {
+public:
+ VFunction **vtbl;
+ ScintillaWin *sci;
+ DropTarget();
+};
+
+/**
+ */
+class ScintillaWin :
+ public ScintillaBase {
+
+ bool lastKeyDownConsumed;
+
+ bool capturedMouse;
+ bool trackedMouseLeave;
+ TrackMouseEventSig TrackMouseEventFn;
+
+ unsigned int linesPerScroll; ///< Intellimouse support
+ int wheelDelta; ///< Wheel delta from roll
+
+ HRGN hRgnUpdate;
+
+ bool hasOKText;
+
+ CLIPFORMAT cfColumnSelect;
+ CLIPFORMAT cfLineSelect;
+
+ HRESULT hrOle;
+ DropSource ds;
+ DataObject dob;
+ DropTarget dt;
+
+ static HINSTANCE hInstance;
+
+ ScintillaWin(HWND hwnd);
+ ScintillaWin(const ScintillaWin &);
+ virtual ~ScintillaWin();
+ ScintillaWin &operator=(const ScintillaWin &);
+
+ virtual void Initialise();
+ virtual void Finalise();
+ HWND MainHWND();
+
+ static sptr_t DirectFunction(
+ ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam);
+ static sptr_t PASCAL SWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);
+ static sptr_t PASCAL CTWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);
+
+ enum { invalidTimerID, standardTimerID, idleTimerID };
+
+ virtual bool DragThreshold(Point ptStart, Point ptNow);
+ virtual void StartDrag();
+ sptr_t WndPaint(uptr_t wParam);
+ sptr_t HandleComposition(uptr_t wParam, sptr_t lParam);
+ UINT CodePageOfDocument();
+ virtual bool ValidCodePage(int codePage) const;
+ virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+ virtual bool SetIdle(bool on);
+ virtual void SetTicking(bool on);
+ virtual void SetMouseCapture(bool on);
+ virtual bool HaveMouseCapture();
+ virtual void SetTrackMouseLeaveEvent(bool on);
+ virtual bool PaintContains(PRectangle rc);
+ virtual void ScrollText(int linesToMove);
+ virtual void UpdateSystemCaret();
+ virtual void SetVerticalScrollPos();
+ virtual void SetHorizontalScrollPos();
+ virtual bool ModifyScrollBars(int nMax, int nPage);
+ virtual void NotifyChange();
+ virtual void NotifyFocus(bool focus);
+ virtual int GetCtrlID();
+ virtual void NotifyParent(SCNotification scn);
+ virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
+ virtual CaseFolder *CaseFolderForEncoding();
+ virtual std::string CaseMapString(const std::string &s, int caseMapping);
+ virtual void Copy();
+ virtual void CopyAllowLine();
+ virtual bool CanPaste();
+ virtual void Paste();
+ virtual void CreateCallTipWindow(PRectangle rc);
+ virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+ virtual void ClaimSelection();
+
+ // DBCS
+ void ImeStartComposition();
+ void ImeEndComposition();
+
+ void AddCharBytes(char b0, char b1);
+
+ void GetIntelliMouseParameters();
+ virtual void CopyToClipboard(const SelectionText &selectedText);
+ void ScrollMessage(WPARAM wParam);
+ void HorizontalScrollMessage(WPARAM wParam);
+ void RealizeWindowPalette(bool inBackGround);
+ void FullPaint();
+ void FullPaintDC(HDC dc);
+ bool IsCompatibleDC(HDC dc);
+ DWORD EffectFromState(DWORD grfKeyState);
+
+ virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw);
+ virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi);
+ void ChangeScrollPos(int barType, int pos);
+
+ void InsertPasteText(const char *text, int len, SelectionPosition selStart, bool isRectangular, bool isLine);
+
+public:
+ // Public for benefit of Scintilla_DirectFunction
+ virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+
+ /// Implement IUnknown
+ STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
+ STDMETHODIMP_(ULONG)AddRef();
+ STDMETHODIMP_(ULONG)Release();
+
+ /// Implement IDropTarget
+ STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect);
+ STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect);
+ STDMETHODIMP DragLeave();
+ STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect);
+
+ /// Implement important part of IDataObject
+ STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);
+
+ static bool Register(HINSTANCE hInstance_);
+ static bool Unregister();
+
+ friend class DropSource;
+ friend class DataObject;
+ friend class DropTarget;
+ bool DragIsRectangularOK(CLIPFORMAT fmt) {
+ return drag.rectangular && (fmt == cfColumnSelect);
+ }
+
+private:
+ // For use in creating a system caret
+ bool HasCaretSizeChanged();
+ BOOL CreateSystemCaret();
+ BOOL DestroySystemCaret();
+ HBITMAP sysCaretBitmap;
+ int sysCaretWidth;
+ int sysCaretHeight;
+ bool keysAlwaysUnicode;
+};
+
+HINSTANCE ScintillaWin::hInstance = 0;
+
+ScintillaWin::ScintillaWin(HWND hwnd) {
+
+ lastKeyDownConsumed = false;
+
+ capturedMouse = false;
+ trackedMouseLeave = false;
+ TrackMouseEventFn = 0;
+
+ linesPerScroll = 0;
+ wheelDelta = 0; // Wheel delta from roll
+
+ hRgnUpdate = 0;
+
+ hasOKText = false;
+
+ // There does not seem to be a real standard for indicating that the clipboard
+ // contains a rectangular selection, so copy Developer Studio.
+ cfColumnSelect = static_cast<CLIPFORMAT>(
+ ::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));
+
+ // Likewise for line-copy (copies a full line when no text is selected)
+ cfLineSelect = static_cast<CLIPFORMAT>(
+ ::RegisterClipboardFormat(TEXT("MSDEVLineSelect")));
+
+ hrOle = E_FAIL;
+
+ wMain = hwnd;
+
+ dob.sci = this;
+ ds.sci = this;
+ dt.sci = this;
+
+ sysCaretBitmap = 0;
+ sysCaretWidth = 0;
+ sysCaretHeight = 0;
+
+ keysAlwaysUnicode = false;
+
+ Initialise();
+}
+
+ScintillaWin::~ScintillaWin() {}
+
+void ScintillaWin::Initialise() {
+ // Initialize COM. If the app has already done this it will have
+ // no effect. If the app hasnt, we really shouldnt ask them to call
+ // it just so this internal feature works.
+ hrOle = ::OleInitialize(NULL);
+
+ // Find TrackMouseEvent which is available on Windows > 95
+ HMODULE user32 = ::GetModuleHandle(TEXT("user32.dll"));
+ TrackMouseEventFn = (TrackMouseEventSig)::GetProcAddress(user32, "TrackMouseEvent");
+ if (TrackMouseEventFn == NULL) {
+ // Windows 95 has an emulation in comctl32.dll:_TrackMouseEvent
+ HMODULE commctrl32 = ::LoadLibrary(TEXT("comctl32.dll"));
+ if (commctrl32 != NULL) {
+ TrackMouseEventFn = (TrackMouseEventSig)
+ ::GetProcAddress(commctrl32, "_TrackMouseEvent");
+ }
+ }
+}
+
+void ScintillaWin::Finalise() {
+ ScintillaBase::Finalise();
+ SetTicking(false);
+ SetIdle(false);
+ ::RevokeDragDrop(MainHWND());
+ if (SUCCEEDED(hrOle)) {
+ ::OleUninitialize();
+ }
+}
+
+HWND ScintillaWin::MainHWND() {
+ return reinterpret_cast<HWND>(wMain.GetID());
+}
+
+bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) {
+ int xMove = abs(ptStart.x - ptNow.x);
+ int yMove = abs(ptStart.y - ptNow.y);
+ return (xMove > ::GetSystemMetrics(SM_CXDRAG)) ||
+ (yMove > ::GetSystemMetrics(SM_CYDRAG));
+}
+
+void ScintillaWin::StartDrag() {
+ inDragDrop = ddDragging;
+ DWORD dwEffect = 0;
+ dropWentOutside = true;
+ IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob);
+ IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds);
+ //Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
+ HRESULT hr = ::DoDragDrop(
+ pDataObject,
+ pDropSource,
+ DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
+ //Platform::DebugPrintf("DoDragDrop = %x\n", hr);
+ if (SUCCEEDED(hr)) {
+ if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) {
+ // Remove dragged out text
+ ClearSelection();
+ }
+ }
+ inDragDrop = ddNone;
+ SetDragPosition(SelectionPosition(invalidPosition));
+}
+
+// Avoid warnings everywhere for old style casts by concentrating them here
+static WORD LoWord(DWORD l) {
+ return LOWORD(l);
+}
+
+static WORD HiWord(DWORD l) {
+ return HIWORD(l);
+}
+
+static int InputCodePage() {
+ HKL inputLocale = ::GetKeyboardLayout(0);
+ LANGID inputLang = LOWORD(inputLocale);
+ char sCodePage[10];
+ int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT),
+ LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage));
+ if (!res)
+ return 0;
+ return atoi(sCodePage);
+}
+
+#ifndef VK_OEM_2
+static const int VK_OEM_2=0xbf;
+static const int VK_OEM_3=0xc0;
+static const int VK_OEM_4=0xdb;
+static const int VK_OEM_5=0xdc;
+static const int VK_OEM_6=0xdd;
+#endif
+
+/** Map the key codes to their equivalent SCK_ form. */
+static int KeyTranslate(int keyIn) {
+//PLATFORM_ASSERT(!keyIn);
+ switch (keyIn) {
+ case VK_DOWN: return SCK_DOWN;
+ case VK_UP: return SCK_UP;
+ case VK_LEFT: return SCK_LEFT;
+ case VK_RIGHT: return SCK_RIGHT;
+ case VK_HOME: return SCK_HOME;
+ case VK_END: return SCK_END;
+ case VK_PRIOR: return SCK_PRIOR;
+ case VK_NEXT: return SCK_NEXT;
+ case VK_DELETE: return SCK_DELETE;
+ case VK_INSERT: return SCK_INSERT;
+ case VK_ESCAPE: return SCK_ESCAPE;
+ case VK_BACK: return SCK_BACK;
+ case VK_TAB: return SCK_TAB;
+ case VK_RETURN: return SCK_RETURN;
+ case VK_ADD: return SCK_ADD;
+ case VK_SUBTRACT: return SCK_SUBTRACT;
+ case VK_DIVIDE: return SCK_DIVIDE;
+ case VK_LWIN: return SCK_WIN;
+ case VK_RWIN: return SCK_RWIN;
+ case VK_APPS: return SCK_MENU;
+ case VK_OEM_2: return '/';
+ case VK_OEM_3: return '`';
+ case VK_OEM_4: return '[';
+ case VK_OEM_5: return '\\';
+ case VK_OEM_6: return ']';
+ default: return keyIn;
+ }
+}
+
+LRESULT ScintillaWin::WndPaint(uptr_t wParam) {
+ //ElapsedTime et;
+
+ // Redirect assertions to debug output and save current state
+ bool assertsPopup = Platform::ShowAssertionPopUps(false);
+ paintState = painting;
+ PAINTSTRUCT ps;
+ PAINTSTRUCT *pps;
+
+ bool IsOcxCtrl = (wParam != 0); // if wParam != 0, it contains
+ // a PAINSTRUCT* from the OCX
+ // Removed since this interferes with reporting other assertions as it occurs repeatedly
+ //PLATFORM_ASSERT(hRgnUpdate == NULL);
+ hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0);
+ if (IsOcxCtrl) {
+ pps = reinterpret_cast<PAINTSTRUCT*>(wParam);
+ } else {
+ ::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE);
+ pps = &ps;
+ ::BeginPaint(MainHWND(), pps);
+ }
+ AutoSurface surfaceWindow(pps->hdc, this);
+ if (surfaceWindow) {
+ rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+ if (paintingAllText) {
+ //Platform::DebugPrintf("Performing full text paint\n");
+ } else {
+ //Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom);
+ }
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ }
+ if (hRgnUpdate) {
+ ::DeleteRgn(hRgnUpdate);
+ hRgnUpdate = 0;
+ }
+
+ if (!IsOcxCtrl)
+ ::EndPaint(MainHWND(), pps);
+ if (paintState == paintAbandoned) {
+ // Painting area was insufficient to cover new styling or brace highlight positions
+ FullPaint();
+ }
+ paintState = notPainting;
+
+ // Restore debug output state
+ Platform::ShowAssertionPopUps(assertsPopup);
+
+ //Platform::DebugPrintf("Paint took %g\n", et.Duration());
+ return 0l;
+}
+
+sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) {
+#ifdef __DMC__
+ // Digital Mars compiler does not include Imm library
+ return 0;
+#else
+ if (lParam & GCS_RESULTSTR) {
+ HIMC hIMC = ::ImmGetContext(MainHWND());
+ if (hIMC) {
+ const int maxLenInputIME = 200;
+ wchar_t wcs[maxLenInputIME];
+ LONG bytes = ::ImmGetCompositionStringW(hIMC,
+ GCS_RESULTSTR, wcs, (maxLenInputIME-1)*2);
+ int wides = bytes / 2;
+ if (IsUnicodeMode()) {
+ char utfval[maxLenInputIME * 3];
+ unsigned int len = UTF8Length(wcs, wides);
+ UTF8FromUTF16(wcs, wides, utfval, len);
+ utfval[len] = '\0';
+ AddCharUTF(utfval, len);
+ } else {
+ char dbcsval[maxLenInputIME * 2];
+ int size = ::WideCharToMultiByte(InputCodePage(),
+ 0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
+ for (int i=0; i<size; i++) {
+ AddChar(dbcsval[i]);
+ }
+ }
+ // Set new position after converted
+ Point pos = PointMainCaret();
+ COMPOSITIONFORM CompForm;
+ CompForm.dwStyle = CFS_POINT;
+ CompForm.ptCurrentPos.x = pos.x;
+ CompForm.ptCurrentPos.y = pos.y;
+ ::ImmSetCompositionWindow(hIMC, &CompForm);
+ ::ImmReleaseContext(MainHWND(), hIMC);
+ }
+ return 0;
+ }
+ return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam);
+#endif
+}
+
+// Translate message IDs from WM_* and EM_* to SCI_* so can partly emulate Windows Edit control
+static unsigned int SciMessageFromEM(unsigned int iMessage) {
+ switch (iMessage) {
+ case EM_CANPASTE: return SCI_CANPASTE;
+ case EM_CANUNDO: return SCI_CANUNDO;
+ case EM_EMPTYUNDOBUFFER: return SCI_EMPTYUNDOBUFFER;
+ case EM_FINDTEXTEX: return SCI_FINDTEXT;
+ case EM_FORMATRANGE: return SCI_FORMATRANGE;
+ case EM_GETFIRSTVISIBLELINE: return SCI_GETFIRSTVISIBLELINE;
+ case EM_GETLINECOUNT: return SCI_GETLINECOUNT;
+ case EM_GETSELTEXT: return SCI_GETSELTEXT;
+ case EM_GETTEXTRANGE: return SCI_GETTEXTRANGE;
+ case EM_HIDESELECTION: return SCI_HIDESELECTION;
+ case EM_LINEINDEX: return SCI_POSITIONFROMLINE;
+ case EM_LINESCROLL: return SCI_LINESCROLL;
+ case EM_REPLACESEL: return SCI_REPLACESEL;
+ case EM_SCROLLCARET: return SCI_SCROLLCARET;
+ case EM_SETREADONLY: return SCI_SETREADONLY;
+ case WM_CLEAR: return SCI_CLEAR;
+ case WM_COPY: return SCI_COPY;
+ case WM_CUT: return SCI_CUT;
+ case WM_GETTEXT: return SCI_GETTEXT;
+ case WM_SETTEXT: return SCI_SETTEXT;
+ case WM_GETTEXTLENGTH: return SCI_GETTEXTLENGTH;
+ case WM_PASTE: return SCI_PASTE;
+ case WM_UNDO: return SCI_UNDO;
+ }
+ return iMessage;
+}
+
+static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {
+ if (documentCodePage == SC_CP_UTF8) {
+ // The system calls here are a little slow so avoid if known case.
+ return SC_CP_UTF8;
+ }
+ CHARSETINFO ci = { 0, 0, { { 0, 0, 0, 0 }, { 0, 0 } } };
+ BOOL bci = ::TranslateCharsetInfo((DWORD*)characterSet,
+ &ci, TCI_SRCCHARSET);
+
+ UINT cp;
+ if (bci)
+ cp = ci.ciACP;
+ else
+ cp = documentCodePage;
+
+ CPINFO cpi;
+ if (!IsValidCodePage(cp) && !GetCPInfo(cp, &cpi))
+ cp = CP_ACP;
+
+ return cp;
+}
+
+UINT ScintillaWin::CodePageOfDocument() {
+ return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage);
+}
+
+sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ try {
+ //Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam);
+ iMessage = SciMessageFromEM(iMessage);
+ switch (iMessage) {
+
+ case WM_CREATE:
+ ctrlID = ::GetDlgCtrlID(reinterpret_cast<HWND>(wMain.GetID()));
+ // Get Intellimouse scroll line parameters
+ GetIntelliMouseParameters();
+ ::RegisterDragDrop(MainHWND(), reinterpret_cast<IDropTarget *>(&dt));
+ break;
+
+ case WM_COMMAND:
+ Command(LoWord(wParam));
+ break;
+
+ case WM_PAINT:
+ return WndPaint(wParam);
+
+ case WM_PRINTCLIENT: {
+ HDC hdc = reinterpret_cast<HDC>(wParam);
+ if (!IsCompatibleDC(hdc)) {
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+ }
+ FullPaintDC(hdc);
+ }
+ break;
+
+ case WM_VSCROLL:
+ ScrollMessage(wParam);
+ break;
+
+ case WM_HSCROLL:
+ HorizontalScrollMessage(wParam);
+ break;
+
+ case WM_SIZE: {
+ //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam));
+ ChangeSize();
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ // Don't handle datazoom.
+ // (A good idea for datazoom would be to "fold" or "unfold" details.
+ // i.e. if datazoomed out only class structures are visible, when datazooming in the control
+ // structures appear, then eventually the individual statements...)
+ if (wParam & MK_SHIFT) {
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+ }
+
+ // Either SCROLL or ZOOM. We handle the wheel steppings calculation
+ wheelDelta -= static_cast<short>(HiWord(wParam));
+ if (abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) {
+ int linesToScroll = linesPerScroll;
+ if (linesPerScroll == WHEEL_PAGESCROLL)
+ linesToScroll = LinesOnScreen() - 1;
+ if (linesToScroll == 0) {
+ linesToScroll = 1;
+ }
+ linesToScroll *= (wheelDelta / WHEEL_DELTA);
+ if (wheelDelta >= 0)
+ wheelDelta = wheelDelta % WHEEL_DELTA;
+ else
+ wheelDelta = - (-wheelDelta % WHEEL_DELTA);
+
+ if (wParam & MK_CONTROL) {
+ // Zoom! We play with the font sizes in the styles.
+ // Number of steps/line is ignored, we just care if sizing up or down
+ if (linesToScroll < 0) {
+ KeyCommand(SCI_ZOOMIN);
+ } else {
+ KeyCommand(SCI_ZOOMOUT);
+ }
+ } else {
+ // Scroll
+ ScrollTo(topLine + linesToScroll);
+ }
+ }
+ return 0;
+
+ case WM_TIMER:
+ if (wParam == standardTimerID && timer.ticking) {
+ Tick();
+ } else if (wParam == idleTimerID && idler.state) {
+ SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1);
+ } else {
+ return 1;
+ }
+ break;
+
+ case SC_WIN_IDLE:
+ // wParam=dwTickCountInitial, or 0 to initialize. lParam=bSkipUserInputTest
+ if (idler.state) {
+ if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, 0, 0, 0, QS_INPUT|QS_HOTKEY))) {
+ if (Idle()) {
+ // User input was given priority above, but all events do get a turn. Other
+ // messages, notifications, etc. will get interleaved with the idle messages.
+
+ // However, some things like WM_PAINT are a lower priority, and will not fire
+ // when there's a message posted. So, several times a second, we stop and let
+ // the low priority events have a turn (after which the timer will fire again).
+
+ DWORD dwCurrent = GetTickCount();
+ DWORD dwStart = wParam ? wParam : dwCurrent;
+
+ if (dwCurrent >= dwStart && dwCurrent > 200 && dwCurrent - 200 < dwStart)
+ PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0);
+ } else {
+ SetIdle(false);
+ }
+ }
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_LBUTTONDOWN: {
+#ifndef __DMC__
+ // Digital Mars compiler does not include Imm library
+ // For IME, set the composition string as the result string.
+ HIMC hIMC = ::ImmGetContext(MainHWND());
+ ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ ::ImmReleaseContext(MainHWND(), hIMC);
+#endif
+ //
+ //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam,
+ // Platform::IsKeyDown(VK_SHIFT),
+ // Platform::IsKeyDown(VK_CONTROL),
+ // Platform::IsKeyDown(VK_MENU));
+ ButtonDown(Point::FromLong(lParam), ::GetMessageTime(),
+ (wParam & MK_SHIFT) != 0,
+ (wParam & MK_CONTROL) != 0,
+ Platform::IsKeyDown(VK_MENU));
+ ::SetFocus(MainHWND());
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ SetTrackMouseLeaveEvent(true);
+ ButtonMove(Point::FromLong(lParam));
+ break;
+
+ case WM_MOUSELEAVE:
+ SetTrackMouseLeaveEvent(false);
+ MouseLeave();
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_LBUTTONUP:
+ ButtonUp(Point::FromLong(lParam),
+ ::GetMessageTime(),
+ (wParam & MK_CONTROL) != 0);
+ break;
+
+ case WM_RBUTTONDOWN:
+ if (!PointInSelection(Point::FromLong(lParam)))
+ SetEmptySelection(PositionFromLocation(Point::FromLong(lParam)));
+ break;
+
+ case WM_SETCURSOR:
+ if (LoWord(lParam) == HTCLIENT) {
+ if (inDragDrop == ddDragging) {
+ DisplayCursor(Window::cursorUp);
+ } else {
+ // Display regular (drag) cursor over selection
+ POINT pt;
+ ::GetCursorPos(&pt);
+ ::ScreenToClient(MainHWND(), &pt);
+ if (PointInSelMargin(Point(pt.x, pt.y))) {
+ DisplayCursor(Window::cursorReverseArrow);
+ } else if (PointInSelection(Point(pt.x, pt.y)) && !SelectionEmpty()) {
+ DisplayCursor(Window::cursorArrow);
+ } else if (PointIsHotspot(Point(pt.x, pt.y))) {
+ DisplayCursor(Window::cursorHand);
+ } else {
+ DisplayCursor(Window::cursorText);
+ }
+ }
+ return TRUE;
+ } else {
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+ }
+
+ case WM_CHAR:
+ if (((wParam >= 128) || !iscntrl(wParam)) || !lastKeyDownConsumed) {
+ if (::IsWindowUnicode(MainHWND()) || keysAlwaysUnicode) {
+ wchar_t wcs[2] = {wParam, 0};
+ if (IsUnicodeMode()) {
+ // For a wide character version of the window:
+ char utfval[4];
+ unsigned int len = UTF8Length(wcs, 1);
+ UTF8FromUTF16(wcs, 1, utfval, len);
+ AddCharUTF(utfval, len);
+ } else {
+ UINT cpDest = CodePageOfDocument();
+ char inBufferCP[20];
+ int size = ::WideCharToMultiByte(cpDest,
+ 0, wcs, 1, inBufferCP, sizeof(inBufferCP) - 1, 0, 0);
+ AddCharUTF(inBufferCP, size);
+ }
+ } else {
+ if (IsUnicodeMode()) {
+ AddCharBytes('\0', LOBYTE(wParam));
+ } else {
+ AddChar(LOBYTE(wParam));
+ }
+ }
+ }
+ return 0;
+
+ case WM_UNICHAR:
+ if (wParam == UNICODE_NOCHAR) {
+ return IsUnicodeMode() ? 1 : 0;
+ } else if (lastKeyDownConsumed) {
+ return 1;
+ } else {
+ if (IsUnicodeMode()) {
+ char utfval[4];
+ wchar_t wcs[2] = {static_cast<wchar_t>(wParam), 0};
+ unsigned int len = UTF8Length(wcs, 1);
+ UTF8FromUTF16(wcs, 1, utfval, len);
+ AddCharUTF(utfval, len);
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN: {
+ //Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL));
+ lastKeyDownConsumed = false;
+ int ret = KeyDown(KeyTranslate(wParam),
+ Platform::IsKeyDown(VK_SHIFT),
+ Platform::IsKeyDown(VK_CONTROL),
+ Platform::IsKeyDown(VK_MENU),
+ &lastKeyDownConsumed);
+ if (!ret && !lastKeyDownConsumed) {
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+ }
+ break;
+ }
+
+ case WM_IME_KEYDOWN:
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_KEYUP:
+ //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam);
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_SETTINGCHANGE:
+ //Platform::DebugPrintf("Setting Changed\n");
+ InvalidateStyleData();
+ // Get Intellimouse scroll line parameters
+ GetIntelliMouseParameters();
+ break;
+
+ case WM_GETDLGCODE:
+ return DLGC_HASSETSEL | DLGC_WANTALLKEYS;
+
+ case WM_KILLFOCUS: {
+ HWND wOther = reinterpret_cast<HWND>(wParam);
+ HWND wThis = MainHWND();
+ HWND wCT = reinterpret_cast<HWND>(ct.wCallTip.GetID());
+ if (!wParam ||
+ !(::IsChild(wThis, wOther) || (wOther == wCT))) {
+ SetFocusState(false);
+ DestroySystemCaret();
+ }
+ }
+ //RealizeWindowPalette(true);
+ break;
+
+ case WM_SETFOCUS:
+ SetFocusState(true);
+ RealizeWindowPalette(false);
+ DestroySystemCaret();
+ CreateSystemCaret();
+ break;
+
+ case WM_SYSCOLORCHANGE:
+ //Platform::DebugPrintf("Setting Changed\n");
+ InvalidateStyleData();
+ break;
+
+ case WM_PALETTECHANGED:
+ if (wParam != reinterpret_cast<uptr_t>(MainHWND())) {
+ //Platform::DebugPrintf("** Palette Changed\n");
+ RealizeWindowPalette(true);
+ }
+ break;
+
+ case WM_QUERYNEWPALETTE:
+ //Platform::DebugPrintf("** Query palette\n");
+ RealizeWindowPalette(false);
+ break;
+
+ case WM_IME_STARTCOMPOSITION: // dbcs
+ ImeStartComposition();
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_IME_ENDCOMPOSITION: // dbcs
+ ImeEndComposition();
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_IME_COMPOSITION:
+ return HandleComposition(wParam, lParam);
+
+ case WM_IME_CHAR: {
+ AddCharBytes(HIBYTE(wParam), LOBYTE(wParam));
+ return 0;
+ }
+
+ case WM_CONTEXTMENU:
+ if (displayPopupMenu) {
+ Point pt = Point::FromLong(lParam);
+ if ((pt.x == -1) && (pt.y == -1)) {
+ // Caused by keyboard so display menu near caret
+ pt = PointMainCaret();
+ POINT spt = {pt.x, pt.y};
+ ::ClientToScreen(MainHWND(), &spt);
+ pt = Point(spt.x, spt.y);
+ }
+ ContextMenu(pt);
+ return 0;
+ }
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_INPUTLANGCHANGE:
+ //::SetThreadLocale(LOWORD(lParam));
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_INPUTLANGCHANGEREQUEST:
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case WM_ERASEBKGND:
+ return 1; // Avoid any background erasure as whole window painted.
+
+ case WM_CAPTURECHANGED:
+ capturedMouse = false;
+ return 0;
+
+ // These are not handled in Scintilla and its faster to dispatch them here.
+ // Also moves time out to here so profile doesn't count lots of empty message calls.
+
+ case WM_MOVE:
+ case WM_MOUSEACTIVATE:
+ case WM_NCHITTEST:
+ case WM_NCCALCSIZE:
+ case WM_NCPAINT:
+ case WM_NCMOUSEMOVE:
+ case WM_NCLBUTTONDOWN:
+ case WM_IME_SETCONTEXT:
+ case WM_IME_NOTIFY:
+ case WM_SYSCOMMAND:
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+
+ case EM_LINEFROMCHAR:
+ if (static_cast<int>(wParam) < 0) {
+ wParam = SelectionStart().Position();
+ }
+ return pdoc->LineFromPosition(wParam);
+
+ case EM_EXLINEFROMCHAR:
+ return pdoc->LineFromPosition(lParam);
+
+ case EM_GETSEL:
+ if (wParam) {
+ *reinterpret_cast<int *>(wParam) = SelectionStart().Position();
+ }
+ if (lParam) {
+ *reinterpret_cast<int *>(lParam) = SelectionEnd().Position();
+ }
+ return MAKELONG(SelectionStart().Position(), SelectionEnd().Position());
+
+ case EM_EXGETSEL: {
+ if (lParam == 0) {
+ return 0;
+ }
+ Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam);
+ pCR->cpMin = SelectionStart().Position();
+ pCR->cpMax = SelectionEnd().Position();
+ }
+ break;
+
+ case EM_SETSEL: {
+ int nStart = static_cast<int>(wParam);
+ int nEnd = static_cast<int>(lParam);
+ if (nStart == 0 && nEnd == -1) {
+ nEnd = pdoc->Length();
+ }
+ if (nStart == -1) {
+ nStart = nEnd; // Remove selection
+ }
+ if (nStart > nEnd) {
+ SetSelection(nEnd, nStart);
+ } else {
+ SetSelection(nStart, nEnd);
+ }
+ EnsureCaretVisible();
+ }
+ break;
+
+ case EM_EXSETSEL: {
+ if (lParam == 0) {
+ return 0;
+ }
+ Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam);
+ sel.selType = Selection::selStream;
+ if (pCR->cpMin == 0 && pCR->cpMax == -1) {
+ SetSelection(pCR->cpMin, pdoc->Length());
+ } else {
+ SetSelection(pCR->cpMin, pCR->cpMax);
+ }
+ EnsureCaretVisible();
+ return pdoc->LineFromPosition(SelectionStart().Position());
+ }
+
+ case SCI_GETDIRECTFUNCTION:
+ return reinterpret_cast<sptr_t>(DirectFunction);
+
+ case SCI_GETDIRECTPOINTER:
+ return reinterpret_cast<sptr_t>(this);
+
+ case SCI_GRABFOCUS:
+ ::SetFocus(MainHWND());
+ break;
+
+ case SCI_SETKEYSUNICODE:
+ keysAlwaysUnicode = wParam != 0;
+ break;
+
+ case SCI_GETKEYSUNICODE:
+ return keysAlwaysUnicode;
+
+#ifdef SCI_LEXER
+ case SCI_LOADLEXERLIBRARY:
+ LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
+ break;
+#endif
+
+ default:
+ return ScintillaBase::WndProc(iMessage, wParam, lParam);
+ }
+ } catch (std::bad_alloc &) {
+ errorStatus = SC_STATUS_BADALLOC;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return 0l;
+}
+
+bool ScintillaWin::ValidCodePage(int codePage) const {
+ return codePage == 0 || codePage == SC_CP_UTF8 ||
+ codePage == 932 || codePage == 936 || codePage == 949 ||
+ codePage == 950 || codePage == 1361;
+}
+
+sptr_t ScintillaWin::DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
+}
+
+void ScintillaWin::SetTicking(bool on) {
+ if (timer.ticking != on) {
+ timer.ticking = on;
+ if (timer.ticking) {
+ timer.tickerID = ::SetTimer(MainHWND(), standardTimerID, timer.tickSize, NULL)
+ ? reinterpret_cast<TickerID>(standardTimerID) : 0;
+ } else {
+ ::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(timer.tickerID));
+ timer.tickerID = 0;
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+bool ScintillaWin::SetIdle(bool on) {
+ // On Win32 the Idler is implemented as a Timer on the Scintilla window. This
+ // takes advantage of the fact that WM_TIMER messages are very low priority,
+ // and are only posted when the message queue is empty, i.e. during idle time.
+ if (idler.state != on) {
+ if (on) {
+ idler.idlerID = ::SetTimer(MainHWND(), idleTimerID, 10, NULL)
+ ? reinterpret_cast<IdlerID>(idleTimerID) : 0;
+ } else {
+ ::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(idler.idlerID));
+ idler.idlerID = 0;
+ }
+ idler.state = idler.idlerID != 0;
+ }
+ return idler.state;
+}
+
+void ScintillaWin::SetMouseCapture(bool on) {
+ if (mouseDownCaptures) {
+ if (on) {
+ ::SetCapture(MainHWND());
+ } else {
+ ::ReleaseCapture();
+ }
+ }
+ capturedMouse = on;
+}
+
+bool ScintillaWin::HaveMouseCapture() {
+ // Cannot just see if GetCapture is this window as the scroll bar also sets capture for the window
+ return capturedMouse;
+ //return capturedMouse && (::GetCapture() == MainHWND());
+}
+
+void ScintillaWin::SetTrackMouseLeaveEvent(bool on) {
+ if (on && TrackMouseEventFn && !trackedMouseLeave) {
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = MainHWND();
+ TrackMouseEventFn(&tme);
+ }
+ trackedMouseLeave = on;
+}
+
+bool ScintillaWin::PaintContains(PRectangle rc) {
+ bool contains = true;
+ if ((paintState == painting) && (!rc.Empty())) {
+ if (!rcPaint.Contains(rc)) {
+ contains = false;
+ } else {
+ // In bounding rectangle so check more accurately using region
+ HRGN hRgnRange = ::CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
+ if (hRgnRange) {
+ HRGN hRgnDest = ::CreateRectRgn(0, 0, 0, 0);
+ if (hRgnDest) {
+ int combination = ::CombineRgn(hRgnDest, hRgnRange, hRgnUpdate, RGN_DIFF);
+ if (combination != NULLREGION) {
+ contains = false;
+ }
+ ::DeleteRgn(hRgnDest);
+ }
+ ::DeleteRgn(hRgnRange);
+ }
+ }
+ }
+ return contains;
+}
+
+void ScintillaWin::ScrollText(int linesToMove) {
+ //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
+ ::ScrollWindow(MainHWND(), 0,
+ vs.lineHeight * linesToMove, 0, 0);
+ ::UpdateWindow(MainHWND());
+}
+
+void ScintillaWin::UpdateSystemCaret() {
+ if (hasFocus) {
+ if (HasCaretSizeChanged()) {
+ DestroySystemCaret();
+ CreateSystemCaret();
+ }
+ Point pos = PointMainCaret();
+ ::SetCaretPos(pos.x, pos.y);
+ }
+}
+
+int ScintillaWin::SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) {
+ return ::SetScrollInfo(MainHWND(), nBar, lpsi, bRedraw);
+}
+
+bool ScintillaWin::GetScrollInfo(int nBar, LPSCROLLINFO lpsi) {
+ return ::GetScrollInfo(MainHWND(), nBar, lpsi) ? true : false;
+}
+
+// Change the scroll position but avoid repaint if changing to same value
+void ScintillaWin::ChangeScrollPos(int barType, int pos) {
+ SCROLLINFO sci = {
+ sizeof(sci), 0, 0, 0, 0, 0, 0
+ };
+ sci.fMask = SIF_POS;
+ GetScrollInfo(barType, &sci);
+ if (sci.nPos != pos) {
+ DwellEnd(true);
+ sci.nPos = pos;
+ SetScrollInfo(barType, &sci, TRUE);
+ }
+}
+
+void ScintillaWin::SetVerticalScrollPos() {
+ ChangeScrollPos(SB_VERT, topLine);
+}
+
+void ScintillaWin::SetHorizontalScrollPos() {
+ ChangeScrollPos(SB_HORZ, xOffset);
+}
+
+bool ScintillaWin::ModifyScrollBars(int nMax, int nPage) {
+ bool modified = false;
+ SCROLLINFO sci = {
+ sizeof(sci), 0, 0, 0, 0, 0, 0
+ };
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ GetScrollInfo(SB_VERT, &sci);
+ int vertEndPreferred = nMax;
+ if (!verticalScrollBarVisible)
+ vertEndPreferred = 0;
+ if ((sci.nMin != 0) ||
+ (sci.nMax != vertEndPreferred) ||
+ (sci.nPage != static_cast<unsigned int>(nPage)) ||
+ (sci.nPos != 0)) {
+ //Platform::DebugPrintf("Scroll info changed %d %d %d %d %d\n",
+ // sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ sci.nMin = 0;
+ sci.nMax = vertEndPreferred;
+ sci.nPage = nPage;
+ sci.nPos = 0;
+ sci.nTrackPos = 1;
+ SetScrollInfo(SB_VERT, &sci, TRUE);
+ modified = true;
+ }
+
+ PRectangle rcText = GetTextRectangle();
+ int horizEndPreferred = scrollWidth;
+ if (horizEndPreferred < 0)
+ horizEndPreferred = 0;
+ if (!horizontalScrollBarVisible || (wrapState != eWrapNone))
+ horizEndPreferred = 0;
+ unsigned int pageWidth = rcText.Width();
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ GetScrollInfo(SB_HORZ, &sci);
+ if ((sci.nMin != 0) ||
+ (sci.nMax != horizEndPreferred) ||
+ (sci.nPage != pageWidth) ||
+ (sci.nPos != 0)) {
+ sci.fMask = SIF_PAGE | SIF_RANGE;
+ sci.nMin = 0;
+ sci.nMax = horizEndPreferred;
+ sci.nPage = pageWidth;
+ sci.nPos = 0;
+ sci.nTrackPos = 1;
+ SetScrollInfo(SB_HORZ, &sci, TRUE);
+ modified = true;
+ if (scrollWidth < static_cast<int>(pageWidth)) {
+ HorizontalScrollTo(0);
+ }
+ }
+ return modified;
+}
+
+void ScintillaWin::NotifyChange() {
+ ::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
+ MAKELONG(GetCtrlID(), SCEN_CHANGE),
+ reinterpret_cast<LPARAM>(MainHWND()));
+}
+
+void ScintillaWin::NotifyFocus(bool focus) {
+ ::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
+ MAKELONG(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
+ reinterpret_cast<LPARAM>(MainHWND()));
+}
+
+int ScintillaWin::GetCtrlID() {
+ return ::GetDlgCtrlID(reinterpret_cast<HWND>(wMain.GetID()));
+}
+
+void ScintillaWin::NotifyParent(SCNotification scn) {
+ scn.nmhdr.hwndFrom = MainHWND();
+ scn.nmhdr.idFrom = GetCtrlID();
+ ::SendMessage(::GetParent(MainHWND()), WM_NOTIFY,
+ GetCtrlID(), reinterpret_cast<LPARAM>(&scn));
+}
+
+void ScintillaWin::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
+ //Platform::DebugPrintf("ScintillaWin Double click 0\n");
+ ScintillaBase::NotifyDoubleClick(pt, shift, ctrl, alt);
+ // Send myself a WM_LBUTTONDBLCLK, so the container can handle it too.
+ ::SendMessage(MainHWND(),
+ WM_LBUTTONDBLCLK,
+ shift ? MK_SHIFT : 0,
+ MAKELPARAM(pt.x, pt.y));
+}
+
+class CaseFolderUTF8 : public CaseFolderTable {
+ // Allocate the expandable storage here so that it does not need to be reallocated
+ // for each call to Fold.
+ std::vector<wchar_t> utf16Mixed;
+ std::vector<wchar_t> utf16Folded;
+public:
+ CaseFolderUTF8() {
+ StandardASCII();
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if ((lenMixed == 1) && (sizeFolded > 0)) {
+ folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
+ return 1;
+ } else {
+ if (lenMixed > utf16Mixed.size()) {
+ utf16Mixed.resize(lenMixed + 8);
+ }
+ size_t nUtf16Mixed = ::MultiByteToWideChar(65001, 0, mixed, lenMixed,
+ &utf16Mixed[0], utf16Mixed.size());
+
+ if (nUtf16Mixed * 4 > utf16Folded.size()) { // Maximum folding expansion factor of 4
+ utf16Folded.resize(nUtf16Mixed * 4 + 8);
+ }
+ int lenFlat = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
+ LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
+ &utf16Mixed[0], nUtf16Mixed, &utf16Folded[0], utf16Folded.size());
+
+ size_t lenOut = UTF8Length(&utf16Folded[0], lenFlat);
+ if (lenOut < sizeFolded) {
+ UTF8FromUTF16(&utf16Folded[0], lenFlat, folded, lenOut);
+ return lenOut;
+ } else {
+ return 0;
+ }
+ }
+ }
+};
+
+CaseFolder *ScintillaWin::CaseFolderForEncoding() {
+ UINT cpDest = CodePageOfDocument();
+ if (cpDest == SC_CP_UTF8) {
+ return new CaseFolderUTF8();
+ } else {
+ CaseFolderTable *pcf = new CaseFolderTable();
+ if (pdoc->dbcsCodePage == 0) {
+ pcf->StandardASCII();
+ // Only for single byte encodings
+ UINT cpDoc = CodePageOfDocument();
+ for (int i=0x80; i<0x100; i++) {
+ char sCharacter[2] = "A";
+ sCharacter[0] = static_cast<char>(i);
+ wchar_t wCharacter[20];
+ unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, sCharacter, 1,
+ wCharacter, sizeof(wCharacter)/sizeof(wCharacter[0]));
+ if (lengthUTF16 == 1) {
+ wchar_t wLower[20];
+ int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
+ LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
+ wCharacter, lengthUTF16, wLower, sizeof(wLower)/sizeof(wLower[0]));
+ char sCharacterLowered[20];
+ unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
+ wLower, charsConverted,
+ sCharacterLowered, sizeof(sCharacterLowered), NULL, 0);
+ if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
+ pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
+ }
+ }
+ }
+ }
+ return pcf;
+ }
+}
+
+std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) {
+ if (s.size() == 0)
+ return std::string();
+
+ if (caseMapping == cmSame)
+ return s;
+
+ UINT cpDoc = CodePageOfDocument();
+
+ unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), NULL, 0);
+ if (lengthUTF16 == 0) // Failed to convert
+ return s;
+
+ DWORD mapFlags = LCMAP_LINGUISTIC_CASING |
+ ((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE);
+
+ // Many conversions performed by search function are short so optimize this case.
+ enum { shortSize=20 };
+
+ if (s.size() > shortSize) {
+ // Use dynamic allocations for long strings
+
+ // Change text to UTF-16
+ std::vector<wchar_t> vwcText(lengthUTF16);
+ ::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), &vwcText[0], lengthUTF16);
+
+ // Change case
+ int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
+ &vwcText[0], lengthUTF16, NULL, 0);
+ std::vector<wchar_t> vwcConverted(charsConverted);
+ ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
+ &vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted);
+
+ // Change back to document encoding
+ unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
+ &vwcConverted[0], vwcConverted.size(),
+ NULL, 0, NULL, 0);
+ std::vector<char> vcConverted(lengthConverted);
+ ::WideCharToMultiByte(cpDoc, 0,
+ &vwcConverted[0], vwcConverted.size(),
+ &vcConverted[0], vcConverted.size(), NULL, 0);
+
+ return std::string(&vcConverted[0], vcConverted.size());
+
+ } else {
+ // Use static allocations for short strings as much faster
+ // A factor of 15 for single character strings
+
+ // Change text to UTF-16
+ wchar_t vwcText[shortSize];
+ ::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), vwcText, lengthUTF16);
+
+ // Change case
+ int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
+ vwcText, lengthUTF16, NULL, 0);
+ // Full mapping may produce up to 3 characters per input character
+ wchar_t vwcConverted[shortSize*3];
+ ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, vwcText, lengthUTF16,
+ vwcConverted, charsConverted);
+
+ // Change back to document encoding
+ unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
+ vwcConverted, charsConverted,
+ NULL, 0, NULL, 0);
+ // Each UTF-16 code unit may need up to 3 bytes in UTF-8
+ char vcConverted[shortSize * 3 * 3];
+ ::WideCharToMultiByte(cpDoc, 0,
+ vwcConverted, charsConverted,
+ vcConverted, lengthConverted, NULL, 0);
+
+ return std::string(vcConverted, lengthConverted);
+ }
+}
+
+void ScintillaWin::Copy() {
+ //Platform::DebugPrintf("Copy\n");
+ if (!sel.Empty()) {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText);
+ CopyToClipboard(selectedText);
+ }
+}
+
+void ScintillaWin::CopyAllowLine() {
+ SelectionText selectedText;
+ CopySelectionRange(&selectedText, true);
+ CopyToClipboard(selectedText);
+}
+
+bool ScintillaWin::CanPaste() {
+ if (!Editor::CanPaste())
+ return false;
+ if (::IsClipboardFormatAvailable(CF_TEXT))
+ return true;
+ if (IsUnicodeMode())
+ return ::IsClipboardFormatAvailable(CF_UNICODETEXT) != 0;
+ return false;
+}
+
+class GlobalMemory {
+ HGLOBAL hand;
+public:
+ void *ptr;
+ GlobalMemory() : hand(0), ptr(0) {
+ }
+ GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) {
+ if (hand) {
+ ptr = ::GlobalLock(hand);
+ }
+ }
+ ~GlobalMemory() {
+ PLATFORM_ASSERT(!ptr);
+ }
+ void Allocate(size_t bytes) {
+ hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes);
+ if (hand) {
+ ptr = ::GlobalLock(hand);
+ }
+ }
+ HGLOBAL Unlock() {
+ PLATFORM_ASSERT(ptr);
+ HGLOBAL handCopy = hand;
+ ::GlobalUnlock(hand);
+ ptr = 0;
+ hand = 0;
+ return handCopy;
+ }
+ void SetClip(UINT uFormat) {
+ ::SetClipboardData(uFormat, Unlock());
+ }
+ operator bool() const {
+ return ptr != 0;
+ }
+ SIZE_T Size() {
+ return ::GlobalSize(hand);
+ }
+};
+
+void ScintillaWin::InsertPasteText(const char *text, int len, SelectionPosition selStart, bool isRectangular, bool isLine) {
+ if (isRectangular) {
+ PasteRectangular(selStart, text, len);
+ } else {
+ char *convertedText = 0;
+ if (convertPastes) {
+ // Convert line endings of the paste into our local line-endings mode
+ convertedText = Document::TransformLineEnds(&len, text, len, pdoc->eolMode);
+ text = convertedText;
+ }
+ if (isLine) {
+ int insertPos = pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()));
+ pdoc->InsertString(insertPos, text, len);
+ // add the newline if necessary
+ if ((len > 0) && (text[len-1] != '\n' && text[len-1] != '\r')) {
+ const char *endline = StringFromEOLMode(pdoc->eolMode);
+ pdoc->InsertString(insertPos + len, endline, strlen(endline));
+ len += strlen(endline);
+ }
+ if (sel.MainCaret() == insertPos) {
+ SetEmptySelection(sel.MainCaret() + len);
+ }
+ } else {
+ InsertPaste(selStart, text, len);
+ }
+ delete []convertedText;
+ }
+}
+
+void ScintillaWin::Paste() {
+ if (!::OpenClipboard(MainHWND()))
+ return;
+ UndoGroup ug(pdoc);
+ bool isLine = SelectionEmpty() && (::IsClipboardFormatAvailable(cfLineSelect) != 0);
+ ClearSelection();
+ SelectionPosition selStart = sel.IsRectangular() ?
+ sel.Rectangular().Start() :
+ sel.Range(sel.Main()).Start();
+ bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
+
+ // Always use CF_UNICODETEXT if available
+ GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT));
+ if (memUSelection) {
+ wchar_t *uptr = static_cast<wchar_t *>(memUSelection.ptr);
+ if (uptr) {
+ unsigned int len;
+ char *putf;
+ // Default Scintilla behaviour in Unicode mode
+ if (IsUnicodeMode()) {
+ unsigned int bytes = memUSelection.Size();
+ len = UTF8Length(uptr, bytes / 2);
+ putf = new char[len + 1];
+ UTF8FromUTF16(uptr, bytes / 2, putf, len);
+ } else {
+ // CF_UNICODETEXT available, but not in Unicode mode
+ // Convert from Unicode to current Scintilla code page
+ UINT cpDest = CodePageOfDocument();
+ len = ::WideCharToMultiByte(cpDest, 0, uptr, -1,
+ NULL, 0, NULL, NULL) - 1; // subtract 0 terminator
+ putf = new char[len + 1];
+ ::WideCharToMultiByte(cpDest, 0, uptr, -1,
+ putf, len + 1, NULL, NULL);
+ }
+
+ InsertPasteText(putf, len, selStart, isRectangular, isLine);
+ delete []putf;
+ }
+ memUSelection.Unlock();
+ } else {
+ // CF_UNICODETEXT not available, paste ANSI text
+ GlobalMemory memSelection(::GetClipboardData(CF_TEXT));
+ if (memSelection) {
+ char *ptr = static_cast<char *>(memSelection.ptr);
+ if (ptr) {
+ unsigned int bytes = memSelection.Size();
+ unsigned int len = bytes;
+ for (unsigned int i = 0; i < bytes; i++) {
+ if ((len == bytes) && (0 == ptr[i]))
+ len = i;
+ }
+
+ // In Unicode mode, convert clipboard text to UTF-8
+ if (IsUnicodeMode()) {
+ wchar_t *uptr = new wchar_t[len+1];
+
+ unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0,
+ ptr, len, uptr, len+1);
+
+ unsigned int mlen = UTF8Length(uptr, ulen);
+ char *putf = new char[mlen + 1];
+ if (putf) {
+ // CP_UTF8 not available on Windows 95, so use UTF8FromUTF16()
+ UTF8FromUTF16(uptr, ulen, putf, mlen);
+ }
+
+ delete []uptr;
+
+ if (putf) {
+ InsertPasteText(putf, mlen, selStart, isRectangular, isLine);
+ delete []putf;
+ }
+ } else {
+ InsertPasteText(ptr, len, selStart, isRectangular, isLine);
+ }
+ }
+ memSelection.Unlock();
+ }
+ }
+ ::CloseClipboard();
+ Redraw();
+}
+
+void ScintillaWin::CreateCallTipWindow(PRectangle) {
+ if (!ct.wCallTip.Created()) {
+ ct.wCallTip = ::CreateWindow(callClassName, TEXT("ACallTip"),
+ WS_POPUP, 100, 100, 150, 20,
+ MainHWND(), 0,
+ GetWindowInstance(MainHWND()),
+ this);
+ ct.wDraw = ct.wCallTip;
+ }
+}
+
+void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) {
+ HMENU hmenuPopup = reinterpret_cast<HMENU>(popup.GetID());
+ if (!label[0])
+ ::AppendMenuA(hmenuPopup, MF_SEPARATOR, 0, "");
+ else if (enabled)
+ ::AppendMenuA(hmenuPopup, MF_STRING, cmd, label);
+ else
+ ::AppendMenuA(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
+}
+
+void ScintillaWin::ClaimSelection() {
+ // Windows does not have a primary selection
+}
+
+/// Implement IUnknown
+
+STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
+STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("EFE QI");
+ *ppv = NULL;
+ if (riid == IID_IUnknown)
+ *ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
+ if (riid == IID_IEnumFORMATETC)
+ *ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
+ if (!*ppv)
+ return E_NOINTERFACE;
+ FormatEnumerator_AddRef(fe);
+ return S_OK;
+}
+STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
+ return ++fe->ref;
+}
+STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
+ fe->ref--;
+ if (fe->ref > 0)
+ return fe->ref;
+ delete fe;
+ return 0;
+}
+/// Implement IEnumFORMATETC
+STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
+ //Platform::DebugPrintf("EFE Next %d %d", fe->pos, celt);
+ if (rgelt == NULL) return E_POINTER;
+ // We only support one format, so this is simple.
+ unsigned int putPos = 0;
+ while ((fe->pos < fe->formatsLen) && (putPos < celt)) {
+ rgelt->cfFormat = fe->formats[fe->pos];
+ rgelt->ptd = 0;
+ rgelt->dwAspect = DVASPECT_CONTENT;
+ rgelt->lindex = -1;
+ rgelt->tymed = TYMED_HGLOBAL;
+ fe->pos++;
+ putPos++;
+ }
+ if (pceltFetched)
+ *pceltFetched = putPos;
+ return putPos ? S_OK : S_FALSE;
+}
+STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
+ fe->pos += celt;
+ return S_OK;
+}
+STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
+ fe->pos = 0;
+ return S_OK;
+}
+STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
+ FormatEnumerator *pfe;
+ try {
+ pfe = new FormatEnumerator(fe->pos, fe->formats, fe->formatsLen);
+ } catch (...) {
+ return E_OUTOFMEMORY;
+ }
+ return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
+ reinterpret_cast<void **>(ppenum));
+}
+
+static VFunction *vtFormatEnumerator[] = {
+ (VFunction *)(FormatEnumerator_QueryInterface),
+ (VFunction *)(FormatEnumerator_AddRef),
+ (VFunction *)(FormatEnumerator_Release),
+ (VFunction *)(FormatEnumerator_Next),
+ (VFunction *)(FormatEnumerator_Skip),
+ (VFunction *)(FormatEnumerator_Reset),
+ (VFunction *)(FormatEnumerator_Clone)
+};
+
+FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_) {
+ vtbl = vtFormatEnumerator;
+ ref = 0; // First QI adds first reference...
+ pos = pos_;
+ formatsLen = formatsLen_;
+ for (int i=0; i<formatsLen; i++)
+ formats[i] = formats_[i];
+}
+
+/// Implement IUnknown
+STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
+ return ds->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
+ return ds->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
+ return ds->sci->Release();
+}
+
+/// Implement IDropSource
+STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
+ if (fEsc)
+ return DRAGDROP_S_CANCEL;
+ if (!(grfKeyState & MK_LBUTTON))
+ return DRAGDROP_S_DROP;
+ return S_OK;
+}
+
+STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
+ return DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+static VFunction *vtDropSource[] = {
+ (VFunction *)(DropSource_QueryInterface),
+ (VFunction *)(DropSource_AddRef),
+ (VFunction *)(DropSource_Release),
+ (VFunction *)(DropSource_QueryContinueDrag),
+ (VFunction *)(DropSource_GiveFeedback)
+};
+
+DropSource::DropSource() {
+ vtbl = vtDropSource;
+ sci = 0;
+}
+
+/// Implement IUnkown
+STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("DO QI %x\n", pd);
+ return pd->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
+ return pd->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
+ return pd->sci->Release();
+}
+/// Implement IDataObject
+STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
+ return pd->sci->GetData(pFEIn, pSTM);
+}
+
+STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
+ //Platform::DebugPrintf("DOB GetDataHere\n");
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
+ if (pd->sci->DragIsRectangularOK(pFE->cfFormat) &&
+ pFE->ptd == 0 &&
+ (pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
+ pFE->lindex == -1 &&
+ (pFE->tymed & TYMED_HGLOBAL) != 0
+ ) {
+ return S_OK;
+ }
+
+ bool formatOK = (pFE->cfFormat == CF_TEXT) ||
+ ((pFE->cfFormat == CF_UNICODETEXT) && pd->sci->IsUnicodeMode());
+ if (!formatOK ||
+ pFE->ptd != 0 ||
+ (pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
+ pFE->lindex != -1 ||
+ (pFE->tymed & TYMED_HGLOBAL) == 0
+ ) {
+ //Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
+ //return DATA_E_FORMATETC;
+ return S_FALSE;
+ }
+ //Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
+ return S_OK;
+}
+
+STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *pd, FORMATETC *, FORMATETC *pFEOut) {
+ //Platform::DebugPrintf("DOB GetCanon\n");
+ if (pd->sci->IsUnicodeMode())
+ pFEOut->cfFormat = CF_UNICODETEXT;
+ else
+ pFEOut->cfFormat = CF_TEXT;
+ pFEOut->ptd = 0;
+ pFEOut->dwAspect = DVASPECT_CONTENT;
+ pFEOut->lindex = -1;
+ pFEOut->tymed = TYMED_HGLOBAL;
+ return S_OK;
+}
+
+STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
+ //Platform::DebugPrintf("DOB SetData\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
+ try {
+ //Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
+ if (dwDirection != DATADIR_GET) {
+ *ppEnum = 0;
+ return E_FAIL;
+ }
+ FormatEnumerator *pfe;
+ if (pd->sci->IsUnicodeMode()) {
+ CLIPFORMAT formats[] = {CF_UNICODETEXT, CF_TEXT};
+ pfe = new FormatEnumerator(0, formats, 2);
+ } else {
+ CLIPFORMAT formats[] = {CF_TEXT};
+ pfe = new FormatEnumerator(0, formats, 1);
+ }
+ return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
+ reinterpret_cast<void **>(ppEnum));
+ } catch (std::bad_alloc &) {
+ pd->sci->errorStatus = SC_STATUS_BADALLOC;
+ return E_OUTOFMEMORY;
+ } catch (...) {
+ pd->sci->errorStatus = SC_STATUS_FAILURE;
+ return E_FAIL;
+ }
+}
+
+STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
+ //Platform::DebugPrintf("DOB DAdvise\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
+ //Platform::DebugPrintf("DOB DUnadvise\n");
+ return E_FAIL;
+}
+
+STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
+ //Platform::DebugPrintf("DOB EnumDAdvise\n");
+ return E_FAIL;
+}
+
+static VFunction *vtDataObject[] = {
+ (VFunction *)(DataObject_QueryInterface),
+ (VFunction *)(DataObject_AddRef),
+ (VFunction *)(DataObject_Release),
+ (VFunction *)(DataObject_GetData),
+ (VFunction *)(DataObject_GetDataHere),
+ (VFunction *)(DataObject_QueryGetData),
+ (VFunction *)(DataObject_GetCanonicalFormatEtc),
+ (VFunction *)(DataObject_SetData),
+ (VFunction *)(DataObject_EnumFormatEtc),
+ (VFunction *)(DataObject_DAdvise),
+ (VFunction *)(DataObject_DUnadvise),
+ (VFunction *)(DataObject_EnumDAdvise)
+};
+
+DataObject::DataObject() {
+ vtbl = vtDataObject;
+ sci = 0;
+}
+
+/// Implement IUnknown
+STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
+ //Platform::DebugPrintf("DT QI %x\n", dt);
+ return dt->sci->QueryInterface(riid, ppv);
+}
+STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
+ return dt->sci->AddRef();
+}
+STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
+ return dt->sci->Release();
+}
+
+/// Implement IDropTarget by forwarding to Scintilla
+STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ try {
+ return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
+ } catch (...) {
+ dt->sci->errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
+ try {
+ return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
+ } catch (...) {
+ dt->sci->errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
+ try {
+ return dt->sci->DragLeave();
+ } catch (...) {
+ dt->sci->errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ try {
+ return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
+ } catch (...) {
+ dt->sci->errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+
+static VFunction *vtDropTarget[] = {
+ (VFunction *)(DropTarget_QueryInterface),
+ (VFunction *)(DropTarget_AddRef),
+ (VFunction *)(DropTarget_Release),
+ (VFunction *)(DropTarget_DragEnter),
+ (VFunction *)(DropTarget_DragOver),
+ (VFunction *)(DropTarget_DragLeave),
+ (VFunction *)(DropTarget_Drop)
+};
+
+DropTarget::DropTarget() {
+ vtbl = vtDropTarget;
+ sci = 0;
+}
+
+/**
+ * DBCS: support Input Method Editor (IME).
+ * Called when IME Window opened.
+ */
+void ScintillaWin::ImeStartComposition() {
+#ifndef __DMC__
+ // Digital Mars compiler does not include Imm library
+ if (caret.active) {
+ // Move IME Window to current caret position
+ HIMC hIMC = ::ImmGetContext(MainHWND());
+ Point pos = PointMainCaret();
+ COMPOSITIONFORM CompForm;
+ CompForm.dwStyle = CFS_POINT;
+ CompForm.ptCurrentPos.x = pos.x;
+ CompForm.ptCurrentPos.y = pos.y;
+
+ ::ImmSetCompositionWindow(hIMC, &CompForm);
+
+ // Set font of IME window to same as surrounded text.
+ if (stylesValid) {
+ // Since the style creation code has been made platform independent,
+ // The logfont for the IME is recreated here.
+ int styleHere = (pdoc->StyleAt(sel.MainCaret())) & 31;
+ LOGFONTA lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""};
+ int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;
+ if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2;
+ AutoSurface surface(this);
+ int deviceHeight = sizeZoomed;
+ if (surface) {
+ deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72;
+ }
+ // The negative is to allow for leading
+ lf.lfHeight = -(abs(deviceHeight));
+ lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfFaceName[0] = '\0';
+ if (vs.styles[styleHere].fontName)
+ strcpy(lf.lfFaceName, vs.styles[styleHere].fontName);
+
+ ::ImmSetCompositionFontA(hIMC, &lf);
+ }
+ ::ImmReleaseContext(MainHWND(), hIMC);
+ // Caret is displayed in IME window. So, caret in Scintilla is useless.
+ DropCaret();
+ }
+#endif
+}
+
+/** Called when IME Window closed. */
+void ScintillaWin::ImeEndComposition() {
+ ShowCaretAtCurrentPosition();
+}
+
+void ScintillaWin::AddCharBytes(char b0, char b1) {
+
+ int inputCodePage = InputCodePage();
+ if (inputCodePage && IsUnicodeMode()) {
+ char utfval[4] = "\0\0\0";
+ char ansiChars[3];
+ wchar_t wcs[2];
+ if (b0) { // Two bytes from IME
+ ansiChars[0] = b0;
+ ansiChars[1] = b1;
+ ansiChars[2] = '\0';
+ ::MultiByteToWideChar(inputCodePage, 0, ansiChars, 2, wcs, 1);
+ } else {
+ ansiChars[0] = b1;
+ ansiChars[1] = '\0';
+ ::MultiByteToWideChar(inputCodePage, 0, ansiChars, 1, wcs, 1);
+ }
+ unsigned int len = UTF8Length(wcs, 1);
+ UTF8FromUTF16(wcs, 1, utfval, len);
+ utfval[len] = '\0';
+ AddCharUTF(utfval, len ? len : 1);
+ } else if (b0) {
+ char dbcsChars[3];
+ dbcsChars[0] = b0;
+ dbcsChars[1] = b1;
+ dbcsChars[2] = '\0';
+ AddCharUTF(dbcsChars, 2, true);
+ } else {
+ AddChar(b1);
+ }
+}
+
+void ScintillaWin::GetIntelliMouseParameters() {
+ // This retrieves the number of lines per scroll as configured inthe Mouse Properties sheet in Control Panel
+ ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
+}
+
+void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
+ if (!::OpenClipboard(MainHWND()))
+ return ;
+ ::EmptyClipboard();
+
+ GlobalMemory uniText;
+
+ // Default Scintilla behaviour in Unicode mode
+ if (IsUnicodeMode()) {
+ int uchars = UTF16Length(selectedText.s, selectedText.len);
+ uniText.Allocate(2 * uchars);
+ if (uniText) {
+ UTF16FromUTF8(selectedText.s, selectedText.len, static_cast<wchar_t *>(uniText.ptr), uchars);
+ }
+ } else {
+ // Not Unicode mode
+ // Convert to Unicode using the current Scintilla code page
+ UINT cpSrc = CodePageFromCharSet(
+ selectedText.characterSet, selectedText.codePage);
+ int uLen = ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len, 0, 0);
+ uniText.Allocate(2 * uLen);
+ if (uniText) {
+ ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len,
+ static_cast<wchar_t *>(uniText.ptr), uLen);
+ }
+ }
+
+ if (uniText) {
+ if (!IsNT()) {
+ // Copy ANSI text to clipboard on Windows 9x
+ // Convert from Unicode text, so other ANSI programs can
+ // paste the text
+ // Windows NT, 2k, XP automatically generates CF_TEXT
+ GlobalMemory ansiText;
+ ansiText.Allocate(selectedText.len);
+ if (ansiText) {
+ ::WideCharToMultiByte(CP_ACP, 0, static_cast<wchar_t *>(uniText.ptr), -1,
+ static_cast<char *>(ansiText.ptr), selectedText.len, NULL, NULL);
+ ansiText.SetClip(CF_TEXT);
+ }
+ }
+ uniText.SetClip(CF_UNICODETEXT);
+ } else {
+ // There was a failure - try to copy at least ANSI text
+ GlobalMemory ansiText;
+ ansiText.Allocate(selectedText.len);
+ if (ansiText) {
+ memcpy(static_cast<char *>(ansiText.ptr), selectedText.s, selectedText.len);
+ ansiText.SetClip(CF_TEXT);
+ }
+ }
+
+ if (selectedText.rectangular) {
+ ::SetClipboardData(cfColumnSelect, 0);
+ }
+
+ if (selectedText.lineCopy) {
+ ::SetClipboardData(cfLineSelect, 0);
+ }
+
+ ::CloseClipboard();
+}
+
+void ScintillaWin::ScrollMessage(WPARAM wParam) {
+ //DWORD dwStart = timeGetTime();
+ //Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
+
+ SCROLLINFO sci;
+ memset(&sci, 0, sizeof(sci));
+ sci.cbSize = sizeof(sci);
+ sci.fMask = SIF_ALL;
+
+ GetScrollInfo(SB_VERT, &sci);
+
+ //Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
+ //sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
+
+ int topLineNew = topLine;
+ switch (LoWord(wParam)) {
+ case SB_LINEUP:
+ topLineNew -= 1;
+ break;
+ case SB_LINEDOWN:
+ topLineNew += 1;
+ break;
+ case SB_PAGEUP:
+ topLineNew -= LinesToScroll(); break;
+ case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
+ case SB_TOP: topLineNew = 0; break;
+ case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
+ case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
+ case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
+ }
+ ScrollTo(topLineNew);
+}
+
+void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
+ int xPos = xOffset;
+ PRectangle rcText = GetTextRectangle();
+ int pageWidth = rcText.Width() * 2 / 3;
+ switch (LoWord(wParam)) {
+ case SB_LINEUP:
+ xPos -= 20;
+ break;
+ case SB_LINEDOWN: // May move past the logical end
+ xPos += 20;
+ break;
+ case SB_PAGEUP:
+ xPos -= pageWidth;
+ break;
+ case SB_PAGEDOWN:
+ xPos += pageWidth;
+ if (xPos > scrollWidth - rcText.Width()) { // Hit the end exactly
+ xPos = scrollWidth - rcText.Width();
+ }
+ break;
+ case SB_TOP:
+ xPos = 0;
+ break;
+ case SB_BOTTOM:
+ xPos = scrollWidth;
+ break;
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK: {
+ // Do NOT use wParam, its 16 bit and not enough for very long lines. Its still possible to overflow the 32 bit but you have to try harder =]
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_TRACKPOS;
+ if (GetScrollInfo(SB_HORZ, &si)) {
+ xPos = si.nTrackPos;
+ }
+ }
+ break;
+ }
+ HorizontalScrollTo(xPos);
+}
+
+void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
+ RefreshStyleData();
+ HDC hdc = ::GetDC(MainHWND());
+ // Select a stock font to prevent warnings from BoundsChecker
+ ::SelectObject(hdc, GetStockFont(DEFAULT_GUI_FONT));
+ AutoSurface surfaceWindow(hdc, this);
+ if (surfaceWindow) {
+ int changes = surfaceWindow->SetPalette(&palette, inBackGround);
+ if (changes > 0)
+ Redraw();
+ surfaceWindow->Release();
+ }
+ ::ReleaseDC(MainHWND(), hdc);
+}
+
+/**
+ * Redraw all of text area.
+ * This paint will not be abandoned.
+ */
+void ScintillaWin::FullPaint() {
+ HDC hdc = ::GetDC(MainHWND());
+ FullPaintDC(hdc);
+ ::ReleaseDC(MainHWND(), hdc);
+}
+
+/**
+ * Redraw all of text area on the specified DC.
+ * This paint will not be abandoned.
+ */
+void ScintillaWin::FullPaintDC(HDC hdc) {
+ paintState = painting;
+ rcPaint = GetClientRectangle();
+ paintingAllText = true;
+ AutoSurface surfaceWindow(hdc, this);
+ if (surfaceWindow) {
+ Paint(surfaceWindow, rcPaint);
+ surfaceWindow->Release();
+ }
+ paintState = notPainting;
+}
+
+static bool CompareDevCap(HDC hdc, HDC hOtherDC, int nIndex) {
+ return ::GetDeviceCaps(hdc, nIndex) == ::GetDeviceCaps(hOtherDC, nIndex);
+}
+
+bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) {
+ HDC hdc = ::GetDC(MainHWND());
+ bool isCompatible =
+ CompareDevCap(hdc, hOtherDC, TECHNOLOGY) &&
+ CompareDevCap(hdc, hOtherDC, LOGPIXELSY) &&
+ CompareDevCap(hdc, hOtherDC, LOGPIXELSX) &&
+ CompareDevCap(hdc, hOtherDC, BITSPIXEL) &&
+ CompareDevCap(hdc, hOtherDC, PLANES);
+ ::ReleaseDC(MainHWND(), hdc);
+ return isCompatible;
+}
+
+DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) {
+ // These are the Wordpad semantics.
+ DWORD dwEffect;
+ if (inDragDrop == ddDragging) // Internal defaults to move
+ dwEffect = DROPEFFECT_MOVE;
+ else
+ dwEffect = DROPEFFECT_COPY;
+ if (grfKeyState & MK_ALT)
+ dwEffect = DROPEFFECT_MOVE;
+ if (grfKeyState & MK_CONTROL)
+ dwEffect = DROPEFFECT_COPY;
+ return dwEffect;
+}
+
+/// Implement IUnknown
+STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
+ *ppv = NULL;
+ if (riid == IID_IUnknown)
+ *ppv = reinterpret_cast<IDropTarget *>(&dt);
+ if (riid == IID_IDropSource)
+ *ppv = reinterpret_cast<IDropSource *>(&ds);
+ if (riid == IID_IDropTarget)
+ *ppv = reinterpret_cast<IDropTarget *>(&dt);
+ if (riid == IID_IDataObject)
+ *ppv = reinterpret_cast<IDataObject *>(&dob);
+ if (!*ppv)
+ return E_NOINTERFACE;
+ return S_OK;
+}
+
+STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
+ return 1;
+}
+
+STDMETHODIMP_(ULONG) ScintillaWin::Release() {
+ return 1;
+}
+
+/// Implement IDropTarget
+STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL, PDWORD pdwEffect) {
+ if (pIDataSource == NULL)
+ return E_POINTER;
+ FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
+ hasOKText = (hrHasUText == S_OK);
+ if (!hasOKText) {
+ FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ HRESULT hrHasText = pIDataSource->QueryGetData(&fmte);
+ hasOKText = (hrHasText == S_OK);
+ }
+ if (!hasOKText) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return S_OK;
+ }
+
+ *pdwEffect = EffectFromState(grfKeyState);
+ return S_OK;
+}
+
+STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
+ try {
+ if (!hasOKText || pdoc->IsReadOnly()) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return S_OK;
+ }
+
+ *pdwEffect = EffectFromState(grfKeyState);
+
+ // Update the cursor.
+ POINT rpt = {pt.x, pt.y};
+ ::ScreenToClient(MainHWND(), &rpt);
+ SetDragPosition(SPositionFromLocation(Point(rpt.x, rpt.y), false, false, UserVirtualSpace()));
+
+ return S_OK;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+
+STDMETHODIMP ScintillaWin::DragLeave() {
+ try {
+ SetDragPosition(SelectionPosition(invalidPosition));
+ return S_OK;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+
+STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
+ POINTL pt, PDWORD pdwEffect) {
+ try {
+ *pdwEffect = EffectFromState(grfKeyState);
+
+ if (pIDataSource == NULL)
+ return E_POINTER;
+
+ SetDragPosition(SelectionPosition(invalidPosition));
+
+ STGMEDIUM medium = {0, {0}, 0};
+
+ char *data = 0;
+ bool dataAllocated = false;
+
+ FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ HRESULT hr = pIDataSource->GetData(&fmtu, &medium);
+ if (SUCCEEDED(hr) && medium.hGlobal) {
+ wchar_t *udata = static_cast<wchar_t *>(::GlobalLock(medium.hGlobal));
+ if (IsUnicodeMode()) {
+ int tlen = ::GlobalSize(medium.hGlobal);
+ // Convert UTF-16 to UTF-8
+ int dataLen = UTF8Length(udata, tlen/2);
+ data = new char[dataLen+1];
+ UTF8FromUTF16(udata, tlen/2, data, dataLen);
+ dataAllocated = true;
+ } else {
+ // Convert UTF-16 to ANSI
+ //
+ // Default Scintilla behavior in Unicode mode
+ // CF_UNICODETEXT available, but not in Unicode mode
+ // Convert from Unicode to current Scintilla code page
+ UINT cpDest = CodePageOfDocument();
+ int tlen = ::WideCharToMultiByte(cpDest, 0, udata, -1,
+ NULL, 0, NULL, NULL) - 1; // subtract 0 terminator
+ data = new char[tlen + 1];
+ memset(data, 0, (tlen+1));
+ ::WideCharToMultiByte(cpDest, 0, udata, -1,
+ data, tlen + 1, NULL, NULL);
+ dataAllocated = true;
+ }
+ }
+
+ if (!data) {
+ FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ hr = pIDataSource->GetData(&fmte, &medium);
+ if (SUCCEEDED(hr) && medium.hGlobal) {
+ data = static_cast<char *>(::GlobalLock(medium.hGlobal));
+ }
+ }
+
+ if (data && convertPastes) {
+ // Convert line endings of the drop into our local line-endings mode
+ int len = strlen(data);
+ char *convertedText = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
+ if (dataAllocated)
+ delete []data;
+ data = convertedText;
+ dataAllocated = true;
+ }
+
+ if (!data) {
+ //Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
+ return hr;
+ }
+
+ FORMATETC fmtr = {cfColumnSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
+
+ POINT rpt = {pt.x, pt.y};
+ ::ScreenToClient(MainHWND(), &rpt);
+ SelectionPosition movePos = SPositionFromLocation(Point(rpt.x, rpt.y), false, false, UserVirtualSpace());
+
+ DropAt(movePos, data, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);
+
+ ::GlobalUnlock(medium.hGlobal);
+
+ // Free data
+ if (medium.pUnkForRelease != NULL)
+ medium.pUnkForRelease->Release();
+ else
+ ::GlobalFree(medium.hGlobal);
+
+ if (dataAllocated)
+ delete []data;
+
+ return S_OK;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return E_FAIL;
+}
+
+/// Implement important part of IDataObject
+STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
+ bool formatOK = (pFEIn->cfFormat == CF_TEXT) ||
+ ((pFEIn->cfFormat == CF_UNICODETEXT) && IsUnicodeMode());
+ if (!formatOK ||
+ pFEIn->ptd != 0 ||
+ (pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
+ pFEIn->lindex != -1 ||
+ (pFEIn->tymed & TYMED_HGLOBAL) == 0
+ ) {
+ //Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
+ return DATA_E_FORMATETC;
+ }
+ pSTM->tymed = TYMED_HGLOBAL;
+ //Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
+
+ GlobalMemory text;
+ if (pFEIn->cfFormat == CF_UNICODETEXT) {
+ int uchars = UTF16Length(drag.s, drag.len);
+ text.Allocate(2 * uchars);
+ if (text) {
+ UTF16FromUTF8(drag.s, drag.len, static_cast<wchar_t *>(text.ptr), uchars);
+ }
+ } else {
+ text.Allocate(drag.len);
+ if (text) {
+ memcpy(static_cast<char *>(text.ptr), drag.s, drag.len);
+ }
+ }
+ pSTM->hGlobal = text ? text.Unlock() : 0;
+ pSTM->pUnkForRelease = 0;
+ return S_OK;
+}
+
+bool ScintillaWin::Register(HINSTANCE hInstance_) {
+
+ hInstance = hInstance_;
+ bool result;
+
+ // Register the Scintilla class
+ if (IsNT()) {
+
+ // Register Scintilla as a wide character window
+ WNDCLASSEXW wndclass;
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = ScintillaWin::SWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = sizeof(ScintillaWin *);
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = NULL;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = L"Scintilla";
+ wndclass.hIconSm = 0;
+ result = ::RegisterClassExW(&wndclass) != 0;
+ } else {
+
+ // Register Scintilla as a normal character window
+ WNDCLASSEX wndclass;
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = ScintillaWin::SWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = sizeof(ScintillaWin *);
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = NULL;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = scintillaClassName;
+ wndclass.hIconSm = 0;
+ result = ::RegisterClassEx(&wndclass) != 0;
+ }
+
+ if (result) {
+ // Register the CallTip class
+ WNDCLASSEX wndclassc;
+ wndclassc.cbSize = sizeof(wndclassc);
+ wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclassc.cbClsExtra = 0;
+ wndclassc.cbWndExtra = sizeof(ScintillaWin *);
+ wndclassc.hInstance = hInstance;
+ wndclassc.hIcon = NULL;
+ wndclassc.hbrBackground = NULL;
+ wndclassc.lpszMenuName = NULL;
+ wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
+ wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ wndclassc.lpszClassName = callClassName;
+ wndclassc.hIconSm = 0;
+
+ result = ::RegisterClassEx(&wndclassc) != 0;
+ }
+
+ return result;
+}
+
+bool ScintillaWin::Unregister() {
+ bool result = ::UnregisterClass(scintillaClassName, hInstance) != 0;
+ if (::UnregisterClass(callClassName, hInstance) == 0)
+ result = false;
+ return result;
+}
+
+bool ScintillaWin::HasCaretSizeChanged() {
+ if (
+ ( (0 != vs.caretWidth) && (sysCaretWidth != vs.caretWidth) )
+ || ((0 != vs.lineHeight) && (sysCaretHeight != vs.lineHeight))
+ ) {
+ return true;
+ }
+ return false;
+}
+
+BOOL ScintillaWin::CreateSystemCaret() {
+ sysCaretWidth = vs.caretWidth;
+ if (0 == sysCaretWidth) {
+ sysCaretWidth = 1;
+ }
+ sysCaretHeight = vs.lineHeight;
+ int bitmapSize = (((sysCaretWidth + 15) & ~15) >> 3) *
+ sysCaretHeight;
+ char *bits = new char[bitmapSize];
+ memset(bits, 0, bitmapSize);
+ sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1,
+ 1, reinterpret_cast<BYTE *>(bits));
+ delete []bits;
+ BOOL retval = ::CreateCaret(
+ MainHWND(), sysCaretBitmap,
+ sysCaretWidth, sysCaretHeight);
+ ::ShowCaret(MainHWND());
+ return retval;
+}
+
+BOOL ScintillaWin::DestroySystemCaret() {
+ ::HideCaret(MainHWND());
+ BOOL retval = ::DestroyCaret();
+ if (sysCaretBitmap) {
+ ::DeleteObject(sysCaretBitmap);
+ sysCaretBitmap = 0;
+ }
+ return retval;
+}
+
+// Take care of 32/64 bit pointers
+#ifdef GetWindowLongPtr
+static void *PointerFromWindow(HWND hWnd) {
+ return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
+}
+static void SetWindowPointer(HWND hWnd, void *ptr) {
+ ::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
+}
+#else
+static void *PointerFromWindow(HWND hWnd) {
+ return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
+}
+static void SetWindowPointer(HWND hWnd, void *ptr) {
+ ::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
+}
+#endif
+
+sptr_t PASCAL ScintillaWin::CTWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
+ // Find C++ object associated with window.
+ ScintillaWin *sciThis = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
+ try {
+ // ctp will be zero if WM_CREATE not seen yet
+ if (sciThis == 0) {
+ if (iMessage == WM_CREATE) {
+ // Associate CallTip object with window
+ CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
+ SetWindowPointer(hWnd, pCreate->lpCreateParams);
+ return 0;
+ } else {
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+ } else {
+ if (iMessage == WM_NCDESTROY) {
+ ::SetWindowLong(hWnd, 0, 0);
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else if (iMessage == WM_PAINT) {
+ PAINTSTRUCT ps;
+ ::BeginPaint(hWnd, &ps);
+ Surface *surfaceWindow = Surface::Allocate();
+ if (surfaceWindow) {
+ surfaceWindow->Init(ps.hdc, hWnd);
+ surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage);
+ surfaceWindow->SetDBCSMode(sciThis->ct.codePage);
+ sciThis->ct.PaintCT(surfaceWindow);
+ surfaceWindow->Release();
+ delete surfaceWindow;
+ }
+ ::EndPaint(hWnd, &ps);
+ return 0;
+ } else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) {
+ POINT pt;
+ pt.x = static_cast<short>(LOWORD(lParam));
+ pt.y = static_cast<short>(HIWORD(lParam));
+ ScreenToClient(hWnd, &pt);
+ sciThis->ct.MouseClick(Point(pt.x, pt.y));
+ sciThis->CallTipClick();
+ return 0;
+ } else if (iMessage == WM_LBUTTONDOWN) {
+ // This does not fire due to the hit test code
+ sciThis->ct.MouseClick(Point::FromLong(lParam));
+ sciThis->CallTipClick();
+ return 0;
+ } else if (iMessage == WM_SETCURSOR) {
+ ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
+ return 0;
+ } else if (iMessage == WM_NCHITTEST) {
+ return HTCAPTION;
+ } else {
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ }
+ }
+ } catch (...) {
+ sciThis->errorStatus = SC_STATUS_FAILURE;
+ }
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+}
+
+sptr_t ScintillaWin::DirectFunction(
+ ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
+ PLATFORM_ASSERT(::GetCurrentThreadId() == ::GetWindowThreadProcessId(sci->MainHWND(), NULL));
+ return sci->WndProc(iMessage, wParam, lParam);
+}
+
+extern "C"
+#ifndef STATIC_BUILD
+__declspec(dllexport)
+#endif
+sptr_t __stdcall Scintilla_DirectFunction(
+ ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
+ return sci->WndProc(iMessage, wParam, lParam);
+}
+
+sptr_t PASCAL ScintillaWin::SWndProc(
+ HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
+ //Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);
+
+ // Find C++ object associated with window.
+ ScintillaWin *sci = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
+ // sci will be zero if WM_CREATE not seen yet
+ if (sci == 0) {
+ try {
+ if (iMessage == WM_CREATE) {
+ // Create C++ object associated with window
+ sci = new ScintillaWin(hWnd);
+ SetWindowPointer(hWnd, sci);
+ return sci->WndProc(iMessage, wParam, lParam);
+ }
+ } catch (...) {
+ }
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else {
+ if (iMessage == WM_NCDESTROY) {
+ try {
+ sci->Finalise();
+ delete sci;
+ } catch (...) {
+ }
+ ::SetWindowLong(hWnd, 0, 0);
+ return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
+ } else {
+ return sci->WndProc(iMessage, wParam, lParam);
+ }
+ }
+}
+
+// This function is externally visible so it can be called from container when building statically.
+// Must be called once only.
+int Scintilla_RegisterClasses(void *hInstance) {
+ Platform_Initialise(hInstance);
+ bool result = ScintillaWin::Register(reinterpret_cast<HINSTANCE>(hInstance));
+#ifdef SCI_LEXER
+ Scintilla_LinkLexers();
+#endif
+ return result;
+}
+
+// This function is externally visible so it can be called from container when building statically.
+int Scintilla_ReleaseResources() {
+ bool result = ScintillaWin::Unregister();
+ Platform_Finalise();
+ return result;
+}
+
+#ifndef STATIC_BUILD
+extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) {
+ //Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason);
+ if (dwReason == DLL_PROCESS_ATTACH) {
+ if (!Scintilla_RegisterClasses(hInstance))
+ return FALSE;
+ } else if (dwReason == DLL_PROCESS_DETACH) {
+ Scintilla_ReleaseResources();
+ }
+ return TRUE;
+}
+#endif
diff --git a/scintilla/win32/deps.mak b/scintilla/win32/deps.mak
new file mode 100644
index 0000000..98f4f84
--- /dev/null
+++ b/scintilla/win32/deps.mak
@@ -0,0 +1,282 @@
+PlatWin.o: PlatWin.cxx ../include/Platform.h PlatformRes.h \
+ ../src/UniConversion.h ../src/XPM.h
+ScintillaWin.o: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/UniConversion.h
+AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/AutoComplete.h
+CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/CallTip.h
+CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h
+CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h
+ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \
+ ../src/ContractionState.h
+Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Decoration.h
+Document.o: ../src/Document.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/RESearch.h
+DocumentAccessor.o: ../src/DocumentAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/SVector.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../include/Scintilla.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h
+Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h
+ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../include/KeyWords.h ../src/ExternalLexer.h
+Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Indicator.h
+KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/KeyMap.h
+KeyWords.o: ../src/KeyWords.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAda.o: ../src/LexAda.cxx ../include/Platform.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/PropSet.h \
+ ../include/KeyWords.h ../include/SciLexer.h
+LexAPDL.o: ../src/LexAPDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAsm.o: ../src/LexAsm.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAsn1.o: ../src/LexAsn1.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAU3.o: ../src/LexAU3.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexAVE.o: ../src/LexAVE.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexBaan.o: ../src/LexBaan.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexBash.o: ../src/LexBash.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexBasic.o: ../src/LexBasic.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexBullant.o: ../src/LexBullant.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCaml.o: ../src/LexCaml.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCLW.o: ../src/LexCLW.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCmake.o: ../src/LexCmake.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexConf.o: ../src/LexConf.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexCPP.o: ../src/LexCPP.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCrontab.o: ../src/LexCrontab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexCsound.o: ../src/LexCsound.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexCSS.o: ../src/LexCSS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexD.o: ../src/LexD.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexEiffel.o: ../src/LexEiffel.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexErlang.o: ../src/LexErlang.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexEScript.o: ../src/LexEScript.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexFlagship.o: ../src/LexFlagship.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexForth.o: ../src/LexForth.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexFortran.o: ../src/LexFortran.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexGui4Cli.o: ../src/LexGui4Cli.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexHaskell.o: ../src/LexHaskell.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexHTML.o: ../src/LexHTML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexInno.o: ../src/LexInno.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexKix.o: ../src/LexKix.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexLisp.o: ../src/LexLisp.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexLout.o: ../src/LexLout.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexLua.o: ../src/LexLua.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexMatlab.o: ../src/LexMatlab.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexMetapost.o: ../src/LexMetapost.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \
+ ../src/StyleContext.h
+LexMMIXAL.o: ../src/LexMMIXAL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexMPT.o: ../src/LexMPT.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexMSSQL.o: ../src/LexMSSQL.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexNsis.o: ../src/LexNsis.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexOpal.o: ../src/LexOpal.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexOthers.o: ../src/LexOthers.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPascal.o: ../src/LexPascal.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \
+ ../src/StyleContext.h
+LexPB.o: ../src/LexPB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPerl.o: ../src/LexPerl.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexPOV.o: ../src/LexPOV.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPS.o: ../src/LexPS.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexPython.o: ../src/LexPython.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexRebol.o: ../src/LexRebol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h \
+ ../src/StyleContext.h
+LexRuby.o: ../src/LexRuby.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h
+LexScriptol.o: ../src/LexScriptol.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexSmalltalk.o: ../src/LexSmalltalk.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexSpecman.o: ../src/LexSpecman.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexSpice.o: ../src/LexSpice.cxx ../include/Platform.h \
+ ../include/Accessor.h ../src/StyleContext.h ../include/PropSet.h \
+ ../include/KeyWords.h ../include/SciLexer.h
+LexSQL.o: ../src/LexSQL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexTADS3.o: ../src/LexTADS3.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexTCL.o: ../src/LexTCL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexTeX.o: ../src/LexTeX.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../include/KeyWords.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../src/StyleContext.h
+LexVB.o: ../src/LexVB.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexVerilog.o: ../src/LexVerilog.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h ../include/KeyWords.h ../include/Scintilla.h \
+ ../include/SciLexer.h
+LexVHDL.o: ../src/LexVHDL.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LexYAML.o: ../src/LexYAML.cxx ../include/Platform.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/StyleContext.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+PropSet.o: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h
+RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
+RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h
+ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Editor.h ../src/ScintillaBase.h
+Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Style.h
+StyleContext.o: ../src/StyleContext.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h
+UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h
+ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h
+WindowAccessor.o: ../src/WindowAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/WindowAccessor.h ../include/Scintilla.h
+XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
diff --git a/scintilla/win32/makefile b/scintilla/win32/makefile
new file mode 100644
index 0000000..d9e5dcb
--- /dev/null
+++ b/scintilla/win32/makefile
@@ -0,0 +1,108 @@
+# Make file for Scintilla on Windows
+# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile assumes the mingw32 version of GCC 3.x or 4.x is used and changes will
+# be needed to use other compilers.
+
+.SUFFIXES: .cxx
+CC = g++
+DLLWRAP = dllwrap
+DEL = del /q
+
+COMPONENT = ../bin/Scintilla.dll
+LEXCOMPONENT = ../bin/SciLexer.dll
+LEXLIB = Lexers.a
+
+vpath %.h ../src ../include
+vpath %.cxx ../src
+
+LDFLAGS=-mwindows -lstdc++ -limm32 -lole32 -luuid -mno-cygwin
+# Add -MMD to get dependencies
+INCLUDEDIRS=-I ../include -I ../src
+CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -Wno-strict-overflow -pedantic $(INCLUDEDIRS) -fno-rtti -mno-cygwin
+
+ifdef DEBUG
+CXXFLAGS=-DDEBUG -g $(CXXBASEFLAGS)
+else
+CXXFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS)
+STRIPFLAG=-s
+endif
+
+.cxx.o:
+ $(CC) $(CXXFLAGS) -c $<
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) $(LEXLIB) ScintillaWinS.o WindowAccessor.o
+
+clean:
+ $(DEL) *.exe *.o *.obj *.dll *.res *.map
+
+deps:
+ $(CC) -MM $(CXXFLAGS) *.cxx ../src/*.cxx >deps.mak
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**LEXOBJS=\\\n\(\*.o \)
+LEXOBJS=\
+LexAbaqus.o LexAda.o LexAPDL.o LexAsm.o LexAsn1.o LexASY.o LexAU3.o LexAVE.o \
+LexBaan.o LexBash.o LexBasic.o LexBullant.o LexCaml.o LexCLW.o LexCmake.o \
+LexCOBOL.o LexConf.o LexCPP.o LexCrontab.o LexCsound.o LexCSS.o LexD.o \
+LexEiffel.o LexErlang.o LexEScript.o LexFlagship.o LexForth.o LexFortran.o \
+LexGAP.o LexGui4Cli.o LexHaskell.o LexHTML.o LexInno.o LexKix.o LexLisp.o \
+LexLout.o LexLua.o LexMagik.o LexMarkdown.o LexMatlab.o LexMetapost.o \
+LexMMIXAL.o LexMPT.o LexMSSQL.o LexMySQL.o LexNimrod.o LexNsis.o LexOpal.o \
+LexOthers.o LexPascal.o LexPB.o LexPerl.o LexPLM.o LexPOV.o LexPowerPro.o \
+LexPowerShell.o LexProgress.o LexPS.o LexPython.o LexR.o LexRebol.o LexRuby.o \
+LexScriptol.o LexSmalltalk.o LexSML.o LexSorcus.o LexSpecman.o LexSpice.o \
+LexSQL.o LexTACL.o LexTADS3.o LexTAL.o LexTCL.o LexTeX.o LexVB.o LexVerilog.o \
+LexVHDL.o LexYAML.o
+#--Autogenerated -- end of automatically generated section
+
+SOBJS = ScintillaWin.o ScintillaBase.o Editor.o CharClassify.o Decoration.o \
+ Document.o ContractionState.o CellBuffer.o CallTip.o \
+ ScintRes.o PlatWin.o PositionCache.o KeyMap.o Indicator.o LineMarker.o RESearch.o RunStyles.o \
+ Selection.o Style.o ViewStyle.o AutoComplete.o UniConversion.o PropSet.o XPM.o PerLine.o
+$(COMPONENT): $(SOBJS) Scintilla.def
+ $(DLLWRAP) --add-stdcall-alias --target i386-mingw32 -o $@ $(SOBJS) $(LDFLAGS) $(STRIPFLAG) --relocatable
+
+LOBJS = ScintillaWinL.o ScintillaBaseL.o Editor.o CharClassify.o Decoration.o \
+ Document.o ContractionState.o CellBuffer.o CallTip.o \
+ ScintRes.o PlatWin.o PositionCache.o KeyMap.o Indicator.o LineMarker.o RESearch.o RunStyles.o \
+ Selection.o Style.o ViewStyle.o AutoComplete.o UniConversion.o KeyWords.o \
+ DocumentAccessor.o PropSet.o ExternalLexer.o StyleContext.o XPM.o PerLine.o $(LEXOBJS)
+$(LEXCOMPONENT): $(LOBJS) Scintilla.def
+ $(DLLWRAP) --add-stdcall-alias --target i386-mingw32 -o $@ $(LOBJS) $(LDFLAGS) $(STRIPFLAG) --relocatable
+
+$(LEXLIB): $(LEXOBJS)
+ $(AR) rc $@ $^
+ ranlib $@
+
+# Automatically generate dependencies for most files with "make deps"
+include deps.mak
+
+# These dependencies are maintained by hand as they do not use the default output name
+ScintillaBaseL.o: ScintillaBase.cxx Platform.h Scintilla.h SciLexer.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h PropSet.h Accessor.h DocumentAccessor.h \
+ KeyWords.h ExternalLexer.h PerLine.h
+ScintillaWinL.o: ScintillaWin.cxx Platform.h Scintilla.h SciLexer.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h PropSet.h Accessor.h KeyWords.h \
+ ExternalLexer.h UniConversion.h PerLine.h
+ScintillaWinS.o: ScintillaWin.cxx Platform.h Scintilla.h \
+ ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \
+ LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \
+ ScintillaBase.h UniConversion.h PerLine.h
+
+ScintillaBaseL.o:
+ $(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o $@
+
+ScintillaWinS.o:
+ $(CC) $(CXXFLAGS) -D STATIC_BUILD -c $< -o $@
+
+ScintillaWinL.o:
+ $(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o $@
+
+ScintRes.o: ScintRes.rc PlatformRes.h
+ windres ScintRes.rc $@
+
diff --git a/scintilla/win32/scintilla.mak b/scintilla/win32/scintilla.mak
new file mode 100644
index 0000000..5c412fd
--- /dev/null
+++ b/scintilla/win32/scintilla.mak
@@ -0,0 +1,553 @@
+# Make file for Scintilla on Windows Visual C++ and Borland C++ version
+# Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile is for using Visual C++ with nmake or Borland C++ with make depending on
+# the setting of the VENDOR macro. If no VENDOR is defined n the command line then
+# the tool used is automatically detected.
+# Usage for Microsoft:
+# nmake -f scintilla.mak
+# Usage for Borland:
+# make -f scintilla.mak
+# For debug versions define DEBUG on the command line, for Borland:
+# make DEBUG=1 -f scintilla.mak
+# The main makefile uses mingw32 gcc and may be more current than this file.
+
+.SUFFIXES: .cxx
+
+DIR_O=.
+DIR_BIN=..\bin
+
+COMPONENT=$(DIR_BIN)\Scintilla.dll
+LEXCOMPONENT=$(DIR_BIN)\SciLexer.dll
+
+!IFNDEF VENDOR
+!IFDEF _NMAKE_VER
+#Microsoft nmake so make default VENDOR MICROSOFT
+VENDOR=MICROSOFT
+!ELSE
+VENDOR=BORLAND
+!ENDIF
+!ENDIF
+
+!IF "$(VENDOR)"=="MICROSOFT"
+
+CC=cl
+RC=rc
+LD=link
+
+CXXFLAGS=-Zi -TP -W4 -EHsc -Zc:forScope -Zc:wchar_t -D_CRT_SECURE_NO_DEPRECATE=1
+# For something scary:-Wp64
+CXXDEBUG=-Od -MTd -DDEBUG
+CXXNDEBUG=-O1 -MT -DNDEBUG -GL
+NAME=-Fo
+LDFLAGS=-OPT:REF -LTCG -DEBUG
+LDDEBUG=
+LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.LIB
+NOLOGO=-nologo
+
+!ELSE
+# BORLAND
+
+CC=bcc32
+RC=brcc32 -r
+LD=ilink32
+
+CXXFLAGS=-P -tWM -w -w-prc -w-inl -w-pin -RT-
+# Above turns off warnings for clarfying parentheses and inlines with for not expanded
+CXXDEBUG=-Od -v -DDEBUG
+CXXNDEBUG=-O1 -DNDEBUG
+NAME=-o
+LDFLAGS=-Gn -x -c
+LDDEBUG=-v
+LIBS=import32 cw32mt
+NOLOGO=-q
+
+!ENDIF
+
+!IFDEF QUIET
+CC=@$(CC)
+CXXFLAGS=$(CXXFLAGS) $(NOLOGO)
+LDFLAGS=$(LDFLAGS) $(NOLOGO)
+!ENDIF
+
+!IFDEF DEBUG
+CXXFLAGS=$(CXXFLAGS) $(CXXDEBUG)
+LDFLAGS=$(LDDEBUG) $(LDFLAGS)
+!ELSE
+CXXFLAGS=$(CXXFLAGS) $(CXXNDEBUG)
+!ENDIF
+
+INCLUDEDIRS=-I../include -I../src
+CXXFLAGS=$(CXXFLAGS) $(INCLUDEDIRS)
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) $(DIR_O)\ScintillaWinS.obj $(DIR_O)\WindowAccessor.obj
+
+clean:
+ -del /q $(DIR_O)\*.obj $(DIR_O)\*.pdb $(COMPONENT) $(LEXCOMPONENT) \
+ $(DIR_O)\*.res $(DIR_BIN)\*.map $(DIR_BIN)\*.exp $(DIR_BIN)\*.pdb $(DIR_BIN)\*.lib
+
+SOBJS=\
+ $(DIR_O)\AutoComplete.obj \
+ $(DIR_O)\CallTip.obj \
+ $(DIR_O)\CellBuffer.obj \
+ $(DIR_O)\CharClassify.obj \
+ $(DIR_O)\ContractionState.obj \
+ $(DIR_O)\Decoration.obj \
+ $(DIR_O)\Document.obj \
+ $(DIR_O)\Editor.obj \
+ $(DIR_O)\Indicator.obj \
+ $(DIR_O)\KeyMap.obj \
+ $(DIR_O)\LineMarker.obj \
+ $(DIR_O)\PlatWin.obj \
+ $(DIR_O)\PositionCache.obj \
+ $(DIR_O)\PropSet.obj \
+ $(DIR_O)\RESearch.obj \
+ $(DIR_O)\RunStyles.obj \
+ $(DIR_O)\ScintillaBase.obj \
+ $(DIR_O)\ScintillaWin.obj \
+ $(DIR_O)\Selection.obj \
+ $(DIR_O)\Style.obj \
+ $(DIR_O)\UniConversion.obj \
+ $(DIR_O)\ViewStyle.obj \
+ $(DIR_O)\XPM.obj \
+ $(DIR_O)\PerLine.obj
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**LEXOBJS=\\\n\(\t$(DIR_O)\\\*.obj \\\n\)
+LEXOBJS=\
+ $(DIR_O)\LexAbaqus.obj \
+ $(DIR_O)\LexAda.obj \
+ $(DIR_O)\LexAPDL.obj \
+ $(DIR_O)\LexAsm.obj \
+ $(DIR_O)\LexAsn1.obj \
+ $(DIR_O)\LexASY.obj \
+ $(DIR_O)\LexAU3.obj \
+ $(DIR_O)\LexAVE.obj \
+ $(DIR_O)\LexBaan.obj \
+ $(DIR_O)\LexBash.obj \
+ $(DIR_O)\LexBasic.obj \
+ $(DIR_O)\LexBullant.obj \
+ $(DIR_O)\LexCaml.obj \
+ $(DIR_O)\LexCLW.obj \
+ $(DIR_O)\LexCmake.obj \
+ $(DIR_O)\LexCOBOL.obj \
+ $(DIR_O)\LexConf.obj \
+ $(DIR_O)\LexCPP.obj \
+ $(DIR_O)\LexCrontab.obj \
+ $(DIR_O)\LexCsound.obj \
+ $(DIR_O)\LexCSS.obj \
+ $(DIR_O)\LexD.obj \
+ $(DIR_O)\LexEiffel.obj \
+ $(DIR_O)\LexErlang.obj \
+ $(DIR_O)\LexEScript.obj \
+ $(DIR_O)\LexFlagship.obj \
+ $(DIR_O)\LexForth.obj \
+ $(DIR_O)\LexFortran.obj \
+ $(DIR_O)\LexGAP.obj \
+ $(DIR_O)\LexGui4Cli.obj \
+ $(DIR_O)\LexHaskell.obj \
+ $(DIR_O)\LexHTML.obj \
+ $(DIR_O)\LexInno.obj \
+ $(DIR_O)\LexKix.obj \
+ $(DIR_O)\LexLisp.obj \
+ $(DIR_O)\LexLout.obj \
+ $(DIR_O)\LexLua.obj \
+ $(DIR_O)\LexMagik.obj \
+ $(DIR_O)\LexMarkdown.obj \
+ $(DIR_O)\LexMatlab.obj \
+ $(DIR_O)\LexMetapost.obj \
+ $(DIR_O)\LexMMIXAL.obj \
+ $(DIR_O)\LexMPT.obj \
+ $(DIR_O)\LexMSSQL.obj \
+ $(DIR_O)\LexMySQL.obj \
+ $(DIR_O)\LexNimrod.obj \
+ $(DIR_O)\LexNsis.obj \
+ $(DIR_O)\LexOpal.obj \
+ $(DIR_O)\LexOthers.obj \
+ $(DIR_O)\LexPascal.obj \
+ $(DIR_O)\LexPB.obj \
+ $(DIR_O)\LexPerl.obj \
+ $(DIR_O)\LexPLM.obj \
+ $(DIR_O)\LexPOV.obj \
+ $(DIR_O)\LexPowerPro.obj \
+ $(DIR_O)\LexPowerShell.obj \
+ $(DIR_O)\LexProgress.obj \
+ $(DIR_O)\LexPS.obj \
+ $(DIR_O)\LexPython.obj \
+ $(DIR_O)\LexR.obj \
+ $(DIR_O)\LexRebol.obj \
+ $(DIR_O)\LexRuby.obj \
+ $(DIR_O)\LexScriptol.obj \
+ $(DIR_O)\LexSmalltalk.obj \
+ $(DIR_O)\LexSML.obj \
+ $(DIR_O)\LexSorcus.obj \
+ $(DIR_O)\LexSpecman.obj \
+ $(DIR_O)\LexSpice.obj \
+ $(DIR_O)\LexSQL.obj \
+ $(DIR_O)\LexTACL.obj \
+ $(DIR_O)\LexTADS3.obj \
+ $(DIR_O)\LexTAL.obj \
+ $(DIR_O)\LexTCL.obj \
+ $(DIR_O)\LexTeX.obj \
+ $(DIR_O)\LexVB.obj \
+ $(DIR_O)\LexVerilog.obj \
+ $(DIR_O)\LexVHDL.obj \
+ $(DIR_O)\LexYAML.obj \
+
+#--Autogenerated -- end of automatically generated section
+
+LOBJS=\
+ $(DIR_O)\AutoComplete.obj \
+ $(DIR_O)\CallTip.obj \
+ $(DIR_O)\CellBuffer.obj \
+ $(DIR_O)\CharClassify.obj \
+ $(DIR_O)\ContractionState.obj \
+ $(DIR_O)\Decoration.obj \
+ $(DIR_O)\Document.obj \
+ $(DIR_O)\DocumentAccessor.obj \
+ $(DIR_O)\Editor.obj \
+ $(DIR_O)\ExternalLexer.obj \
+ $(DIR_O)\Indicator.obj \
+ $(DIR_O)\KeyMap.obj \
+ $(DIR_O)\KeyWords.obj \
+ $(DIR_O)\LineMarker.obj \
+ $(DIR_O)\PerLine.obj \
+ $(DIR_O)\PlatWin.obj \
+ $(DIR_O)\PositionCache.obj \
+ $(DIR_O)\PropSet.obj \
+ $(DIR_O)\RESearch.obj \
+ $(DIR_O)\RunStyles.obj \
+ $(DIR_O)\ScintillaBaseL.obj \
+ $(DIR_O)\ScintillaWinL.obj \
+ $(DIR_O)\Selection.obj \
+ $(DIR_O)\Style.obj \
+ $(DIR_O)\StyleContext.obj \
+ $(DIR_O)\UniConversion.obj \
+ $(DIR_O)\ViewStyle.obj \
+ $(DIR_O)\XPM.obj \
+ $(LEXOBJS)
+
+$(DIR_O)\ScintRes.res : ScintRes.rc
+ $(RC) -fo$@ $**
+
+!IF "$(VENDOR)"=="MICROSOFT"
+
+$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)
+
+$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)
+
+!ELSE
+
+$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -Tpd c0d32 $(SOBJS), $@, , $(LIBS), , $(DIR_O)\ScintRes.res
+
+$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -Tpd c0d32 $(LOBJS), $@, , $(LIBS), , $(DIR_O)\ScintRes.res
+
+!ENDIF
+
+# Define how to build all the objects and what they depend on
+
+# Most of the source is in ..\src with a couple in this directory
+{..\src}.cxx{$(DIR_O)}.obj:
+ $(CC) $(CXXFLAGS) -c $(NAME)$@ $<
+{.}.cxx{$(DIR_O)}.obj:
+ $(CC) $(CXXFLAGS) -c $(NAME)$@ $<
+
+# Some source files are compiled into more than one object because of different conditional compilation
+$(DIR_O)\ScintillaBaseL.obj: ..\src\ScintillaBase.cxx
+ $(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ..\src\ScintillaBase.cxx
+
+$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx
+ $(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ScintillaWin.cxx
+
+$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx
+ $(CC) $(CXXFLAGS) -DSTATIC_BUILD -c $(NAME)$@ ScintillaWin.cxx
+
+# Dependencies
+
+# All lexers depend on this set of headers
+LEX_HEADERS=..\include\Platform.h ..\include\PropSet.h \
+ ..\include\Accessor.h ..\include\KeyWords.h \
+ ..\include\Scintilla.h ..\include\SciLexer.h ..\src\StyleContext.h
+
+$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/AutoComplete.h
+$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/CallTip.h
+$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h
+$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h
+$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \
+ ../src/ContractionState.h
+$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Decoration.h
+$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/RESearch.h ../src/PerLine.h
+$(DIR_O)\DocumentAccessor.obj: ../src/DocumentAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/SVector.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../include/Scintilla.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h
+$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../include/KeyWords.h ../src/ExternalLexer.h
+$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Indicator.h
+$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/KeyMap.h
+$(DIR_O)\KeyWords.obj: ../src/KeyWords.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**\n\($(DIR_O)\\\*.obj: ..\\src\\\*.cxx $(LEX_HEADERS)\n\n\)
+
+$(DIR_O)\LexAbaqus.obj: ..\src\LexAbaqus.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAda.obj: ..\src\LexAda.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAPDL.obj: ..\src\LexAPDL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAsm.obj: ..\src\LexAsm.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAsn1.obj: ..\src\LexAsn1.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexASY.obj: ..\src\LexASY.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAU3.obj: ..\src\LexAU3.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAVE.obj: ..\src\LexAVE.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBaan.obj: ..\src\LexBaan.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBash.obj: ..\src\LexBash.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBasic.obj: ..\src\LexBasic.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBullant.obj: ..\src\LexBullant.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCaml.obj: ..\src\LexCaml.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCLW.obj: ..\src\LexCLW.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCmake.obj: ..\src\LexCmake.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCOBOL.obj: ..\src\LexCOBOL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexConf.obj: ..\src\LexConf.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCPP.obj: ..\src\LexCPP.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCrontab.obj: ..\src\LexCrontab.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCsound.obj: ..\src\LexCsound.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCSS.obj: ..\src\LexCSS.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexD.obj: ..\src\LexD.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexEiffel.obj: ..\src\LexEiffel.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexErlang.obj: ..\src\LexErlang.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexEScript.obj: ..\src\LexEScript.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexFlagship.obj: ..\src\LexFlagship.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexForth.obj: ..\src\LexForth.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexFortran.obj: ..\src\LexFortran.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexGAP.obj: ..\src\LexGAP.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexGui4Cli.obj: ..\src\LexGui4Cli.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexHaskell.obj: ..\src\LexHaskell.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexHTML.obj: ..\src\LexHTML.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexInno.obj: ..\src\LexInno.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexKix.obj: ..\src\LexKix.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLisp.obj: ..\src\LexLisp.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLout.obj: ..\src\LexLout.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLua.obj: ..\src\LexLua.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMagik.obj: ..\src\LexMagik.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMarkdown.obj: ..\src\LexMarkdown.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMatlab.obj: ..\src\LexMatlab.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMetapost.obj: ..\src\LexMetapost.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMMIXAL.obj: ..\src\LexMMIXAL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMPT.obj: ..\src\LexMPT.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMSSQL.obj: ..\src\LexMSSQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMySQL.obj: ..\src\LexMySQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexNimrod.obj: ..\src\LexNimrod.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexNsis.obj: ..\src\LexNsis.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexOpal.obj: ..\src\LexOpal.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexOthers.obj: ..\src\LexOthers.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPascal.obj: ..\src\LexPascal.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPB.obj: ..\src\LexPB.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPerl.obj: ..\src\LexPerl.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPLM.obj: ..\src\LexPLM.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPOV.obj: ..\src\LexPOV.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPowerPro.obj: ..\src\LexPowerPro.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPowerShell.obj: ..\src\LexPowerShell.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexProgress.obj: ..\src\LexProgress.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPS.obj: ..\src\LexPS.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPython.obj: ..\src\LexPython.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexR.obj: ..\src\LexR.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexRebol.obj: ..\src\LexRebol.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexRuby.obj: ..\src\LexRuby.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexScriptol.obj: ..\src\LexScriptol.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSmalltalk.obj: ..\src\LexSmalltalk.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSML.obj: ..\src\LexSML.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSorcus.obj: ..\src\LexSorcus.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSpecman.obj: ..\src\LexSpecman.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSpice.obj: ..\src\LexSpice.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSQL.obj: ..\src\LexSQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTACL.obj: ..\src\LexTACL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTADS3.obj: ..\src\LexTADS3.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTAL.obj: ..\src\LexTAL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTCL.obj: ..\src\LexTCL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTeX.obj: ..\src\LexTeX.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVB.obj: ..\src\LexVB.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVerilog.obj: ..\src\LexVerilog.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVHDL.obj: ..\src\LexVHDL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexYAML.obj: ..\src\LexYAML.cxx $(LEX_HEADERS)
+
+
+#--Autogenerated -- end of automatically generated section
+
+$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/PerLine.h
+$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h PlatformRes.h \
+ ../src/UniConversion.h ../src/XPM.h
+$(DIR_O)\PositionCache.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+$(DIR_O)\PropSet.obj: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h
+$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
+$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h
+$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Selection.h
+$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Style.h
+$(DIR_O)\StyleContext.obj: ../src/StyleContext.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h
+$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h
+$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h
+$(DIR_O)\WindowAccessor.obj: ../src/WindowAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/WindowAccessor.h ../include/Scintilla.h
+$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
diff --git a/scintilla/win32/scintilla_vc6.mak b/scintilla/win32/scintilla_vc6.mak
new file mode 100644
index 0000000..7f9939f
--- /dev/null
+++ b/scintilla/win32/scintilla_vc6.mak
@@ -0,0 +1,555 @@
+# Make file for Scintilla on Windows Visual C++ and Borland C++ version
+# Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
+# The License.txt file describes the conditions under which this software may be distributed.
+# This makefile is for using Visual C++ with nmake or Borland C++ with make depending on
+# the setting of the VENDOR macro. If no VENDOR is defined n the command line then
+# the tool used is automatically detected.
+# Usage for Microsoft:
+# nmake -f scintilla.mak
+# Usage for Borland:
+# make -f scintilla.mak
+# For debug versions define DEBUG on the command line, for Borland:
+# make DEBUG=1 -f scintilla.mak
+# The main makefile uses mingw32 gcc and may be more current than this file.
+
+.SUFFIXES: .cxx
+
+DIR_O=.
+DIR_BIN=..\bin
+
+COMPONENT=$(DIR_BIN)\Scintilla.dll
+LEXCOMPONENT=$(DIR_BIN)\SciLexer.dll
+
+!IFNDEF VENDOR
+!IFDEF _NMAKE_VER
+#Microsoft nmake so make default VENDOR MICROSOFT
+VENDOR=MICROSOFT
+!ELSE
+VENDOR=BORLAND
+!ENDIF
+!ENDIF
+
+!IF "$(VENDOR)"=="MICROSOFT"
+
+CC=cl
+RC=rc
+LD=link
+
+#-Zc:forScope -Zc:wchar_t
+CXXFLAGS=-Zi -TP -W3 -EHsc
+# For something scary:-Wp64
+CXXDEBUG=-Od -MTd -DDEBUG
+CXXNDEBUG=-O1 -MT -DNDEBUG
+NAME=-Fo
+# If you have problems with lexers being linked, try removing -OPT:REF and replacing with -OPT:NOREF
+LDFLAGS=-OPT:NOWIN98 -OPT:REF
+LDDEBUG=
+LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.LIB
+NOLOGO=-nologo
+
+!ELSE
+# BORLAND
+
+CC=bcc32
+RC=brcc32 -r
+LD=ilink32
+
+CXXFLAGS=-P -tWM -w -w-prc -w-inl -RT-
+# Above turns off warnings for clarfying parentheses and inlines with for not expanded
+CXXDEBUG=-Od -v -DDEBUG
+CXXNDEBUG=-O1 -DNDEBUG
+NAME=-o
+LDFLAGS=-Gn -x -c
+LDDEBUG=-v
+LIBS=import32 cw32mt
+NOLOGO=-q
+
+!ENDIF
+
+!IFDEF QUIET
+CC=@$(CC)
+CXXFLAGS=$(CXXFLAGS) $(NOLOGO)
+LDFLAGS=$(LDFLAGS) $(NOLOGO)
+!ENDIF
+
+!IFDEF DEBUG
+CXXFLAGS=$(CXXFLAGS) $(CXXDEBUG)
+LDFLAGS=$(LDDEBUG) $(LDFLAGS)
+!ELSE
+CXXFLAGS=$(CXXFLAGS) $(CXXNDEBUG)
+!ENDIF
+
+INCLUDEDIRS=-I../include -I../src
+CXXFLAGS=$(CXXFLAGS) $(INCLUDEDIRS)
+
+ALL: $(COMPONENT) $(LEXCOMPONENT) $(DIR_O)\ScintillaWinS.obj $(DIR_O)\WindowAccessor.obj
+
+clean:
+ -del /q $(DIR_O)\*.obj $(DIR_O)\*.pdb $(COMPONENT) $(LEXCOMPONENT) \
+ $(DIR_O)\*.res $(DIR_BIN)\*.map $(DIR_BIN)\*.exp $(DIR_BIN)\*.pdb $(DIR_BIN)\*.lib
+
+SOBJS=\
+ $(DIR_O)\AutoComplete.obj \
+ $(DIR_O)\CallTip.obj \
+ $(DIR_O)\CellBuffer.obj \
+ $(DIR_O)\CharClassify.obj \
+ $(DIR_O)\ContractionState.obj \
+ $(DIR_O)\Decoration.obj \
+ $(DIR_O)\Document.obj \
+ $(DIR_O)\Editor.obj \
+ $(DIR_O)\Indicator.obj \
+ $(DIR_O)\KeyMap.obj \
+ $(DIR_O)\LineMarker.obj \
+ $(DIR_O)\PlatWin.obj \
+ $(DIR_O)\PositionCache.obj \
+ $(DIR_O)\PropSet.obj \
+ $(DIR_O)\RESearch.obj \
+ $(DIR_O)\RunStyles.obj \
+ $(DIR_O)\ScintillaBase.obj \
+ $(DIR_O)\ScintillaWin.obj \
+ $(DIR_O)\Selection.obj \
+ $(DIR_O)\Style.obj \
+ $(DIR_O)\UniConversion.obj \
+ $(DIR_O)\ViewStyle.obj \
+ $(DIR_O)\XPM.obj \
+ $(DIR_O)\PerLine.obj
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**LEXOBJS=\\\n\(\t$(DIR_O)\\\*.obj \\\n\)
+LEXOBJS=\
+ $(DIR_O)\LexAbaqus.obj \
+ $(DIR_O)\LexAda.obj \
+ $(DIR_O)\LexAPDL.obj \
+ $(DIR_O)\LexAsm.obj \
+ $(DIR_O)\LexAsn1.obj \
+ $(DIR_O)\LexASY.obj \
+ $(DIR_O)\LexAU3.obj \
+ $(DIR_O)\LexAVE.obj \
+ $(DIR_O)\LexBaan.obj \
+ $(DIR_O)\LexBash.obj \
+ $(DIR_O)\LexBasic.obj \
+ $(DIR_O)\LexBullant.obj \
+ $(DIR_O)\LexCaml.obj \
+ $(DIR_O)\LexCLW.obj \
+ $(DIR_O)\LexCmake.obj \
+ $(DIR_O)\LexCOBOL.obj \
+ $(DIR_O)\LexConf.obj \
+ $(DIR_O)\LexCPP.obj \
+ $(DIR_O)\LexCrontab.obj \
+ $(DIR_O)\LexCsound.obj \
+ $(DIR_O)\LexCSS.obj \
+ $(DIR_O)\LexD.obj \
+ $(DIR_O)\LexEiffel.obj \
+ $(DIR_O)\LexErlang.obj \
+ $(DIR_O)\LexEScript.obj \
+ $(DIR_O)\LexFlagship.obj \
+ $(DIR_O)\LexForth.obj \
+ $(DIR_O)\LexFortran.obj \
+ $(DIR_O)\LexGAP.obj \
+ $(DIR_O)\LexGui4Cli.obj \
+ $(DIR_O)\LexHaskell.obj \
+ $(DIR_O)\LexHTML.obj \
+ $(DIR_O)\LexInno.obj \
+ $(DIR_O)\LexKix.obj \
+ $(DIR_O)\LexLisp.obj \
+ $(DIR_O)\LexLout.obj \
+ $(DIR_O)\LexLua.obj \
+ $(DIR_O)\LexMagik.obj \
+ $(DIR_O)\LexMarkdown.obj \
+ $(DIR_O)\LexMatlab.obj \
+ $(DIR_O)\LexMetapost.obj \
+ $(DIR_O)\LexMMIXAL.obj \
+ $(DIR_O)\LexMPT.obj \
+ $(DIR_O)\LexMSSQL.obj \
+ $(DIR_O)\LexMySQL.obj \
+ $(DIR_O)\LexNimrod.obj \
+ $(DIR_O)\LexNsis.obj \
+ $(DIR_O)\LexOpal.obj \
+ $(DIR_O)\LexOthers.obj \
+ $(DIR_O)\LexPascal.obj \
+ $(DIR_O)\LexPB.obj \
+ $(DIR_O)\LexPerl.obj \
+ $(DIR_O)\LexPLM.obj \
+ $(DIR_O)\LexPOV.obj \
+ $(DIR_O)\LexPowerPro.obj \
+ $(DIR_O)\LexPowerShell.obj \
+ $(DIR_O)\LexProgress.obj \
+ $(DIR_O)\LexPS.obj \
+ $(DIR_O)\LexPython.obj \
+ $(DIR_O)\LexR.obj \
+ $(DIR_O)\LexRebol.obj \
+ $(DIR_O)\LexRuby.obj \
+ $(DIR_O)\LexScriptol.obj \
+ $(DIR_O)\LexSmalltalk.obj \
+ $(DIR_O)\LexSML.obj \
+ $(DIR_O)\LexSorcus.obj \
+ $(DIR_O)\LexSpecman.obj \
+ $(DIR_O)\LexSpice.obj \
+ $(DIR_O)\LexSQL.obj \
+ $(DIR_O)\LexTACL.obj \
+ $(DIR_O)\LexTADS3.obj \
+ $(DIR_O)\LexTAL.obj \
+ $(DIR_O)\LexTCL.obj \
+ $(DIR_O)\LexTeX.obj \
+ $(DIR_O)\LexVB.obj \
+ $(DIR_O)\LexVerilog.obj \
+ $(DIR_O)\LexVHDL.obj \
+ $(DIR_O)\LexYAML.obj \
+
+#--Autogenerated -- end of automatically generated section
+
+LOBJS=\
+ $(DIR_O)\AutoComplete.obj \
+ $(DIR_O)\CallTip.obj \
+ $(DIR_O)\CellBuffer.obj \
+ $(DIR_O)\CharClassify.obj \
+ $(DIR_O)\ContractionState.obj \
+ $(DIR_O)\Decoration.obj \
+ $(DIR_O)\Document.obj \
+ $(DIR_O)\DocumentAccessor.obj \
+ $(DIR_O)\Editor.obj \
+ $(DIR_O)\ExternalLexer.obj \
+ $(DIR_O)\Indicator.obj \
+ $(DIR_O)\KeyMap.obj \
+ $(DIR_O)\KeyWords.obj \
+ $(DIR_O)\LineMarker.obj \
+ $(DIR_O)\PerLine.obj \
+ $(DIR_O)\PlatWin.obj \
+ $(DIR_O)\PositionCache.obj \
+ $(DIR_O)\PropSet.obj \
+ $(DIR_O)\RESearch.obj \
+ $(DIR_O)\RunStyles.obj \
+ $(DIR_O)\ScintillaBaseL.obj \
+ $(DIR_O)\ScintillaWinL.obj \
+ $(DIR_O)\Selection.obj \
+ $(DIR_O)\Style.obj \
+ $(DIR_O)\StyleContext.obj \
+ $(DIR_O)\UniConversion.obj \
+ $(DIR_O)\ViewStyle.obj \
+ $(DIR_O)\XPM.obj \
+ $(LEXOBJS)
+
+$(DIR_O)\ScintRes.res : ScintRes.rc
+ $(RC) -fo$@ $**
+
+!IF "$(VENDOR)"=="MICROSOFT"
+
+$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)
+
+$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)
+
+!ELSE
+
+$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -Tpd c0d32 $(SOBJS), $@, , $(LIBS), , $(DIR_O)\ScintRes.res
+
+$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
+ $(LD) $(LDFLAGS) -Tpd c0d32 $(LOBJS), $@, , $(LIBS), , $(DIR_O)\ScintRes.res
+
+!ENDIF
+
+# Define how to build all the objects and what they depend on
+
+# Most of the source is in ..\src with a couple in this directory
+{..\src}.cxx{$(DIR_O)}.obj:
+ $(CC) $(CXXFLAGS) -c $(NAME)$@ $<
+{.}.cxx{$(DIR_O)}.obj:
+ $(CC) $(CXXFLAGS) -c $(NAME)$@ $<
+
+# Some source files are compiled into more than one object because of different conditional compilation
+$(DIR_O)\ScintillaBaseL.obj: ..\src\ScintillaBase.cxx
+ $(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ..\src\ScintillaBase.cxx
+
+$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx
+ $(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ScintillaWin.cxx
+
+$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx
+ $(CC) $(CXXFLAGS) -DSTATIC_BUILD -c $(NAME)$@ ScintillaWin.cxx
+
+# Dependencies
+
+# All lexers depend on this set of headers
+LEX_HEADERS=..\include\Platform.h ..\include\PropSet.h \
+ ..\include\Accessor.h ..\include\KeyWords.h \
+ ..\include\Scintilla.h ..\include\SciLexer.h ..\src\StyleContext.h
+
+$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/AutoComplete.h
+$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/CallTip.h
+$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h
+$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h
+$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \
+ ../src/ContractionState.h
+$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Decoration.h
+$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
+ ../src/RESearch.h ../src/PerLine.h
+$(DIR_O)\DocumentAccessor.obj: ../src/DocumentAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../src/SVector.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../include/Scintilla.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h
+$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../include/PropSet.h \
+ ../include/Accessor.h ../src/DocumentAccessor.h \
+ ../include/KeyWords.h ../src/ExternalLexer.h
+$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/Indicator.h
+$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/KeyMap.h
+$(DIR_O)\KeyWords.obj: ../src/KeyWords.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/KeyWords.h ../include/Scintilla.h ../include/SciLexer.h
+
+#++Autogenerated -- run src/LexGen.py to regenerate
+#**\n\($(DIR_O)\\\*.obj: ..\\src\\\*.cxx $(LEX_HEADERS)\n\n\)
+
+$(DIR_O)\LexAbaqus.obj: ..\src\LexAbaqus.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAda.obj: ..\src\LexAda.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAPDL.obj: ..\src\LexAPDL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAsm.obj: ..\src\LexAsm.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAsn1.obj: ..\src\LexAsn1.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexASY.obj: ..\src\LexASY.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAU3.obj: ..\src\LexAU3.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexAVE.obj: ..\src\LexAVE.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBaan.obj: ..\src\LexBaan.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBash.obj: ..\src\LexBash.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBasic.obj: ..\src\LexBasic.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexBullant.obj: ..\src\LexBullant.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCaml.obj: ..\src\LexCaml.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCLW.obj: ..\src\LexCLW.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCmake.obj: ..\src\LexCmake.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCOBOL.obj: ..\src\LexCOBOL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexConf.obj: ..\src\LexConf.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCPP.obj: ..\src\LexCPP.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCrontab.obj: ..\src\LexCrontab.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCsound.obj: ..\src\LexCsound.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexCSS.obj: ..\src\LexCSS.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexD.obj: ..\src\LexD.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexEiffel.obj: ..\src\LexEiffel.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexErlang.obj: ..\src\LexErlang.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexEScript.obj: ..\src\LexEScript.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexFlagship.obj: ..\src\LexFlagship.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexForth.obj: ..\src\LexForth.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexFortran.obj: ..\src\LexFortran.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexGAP.obj: ..\src\LexGAP.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexGui4Cli.obj: ..\src\LexGui4Cli.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexHaskell.obj: ..\src\LexHaskell.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexHTML.obj: ..\src\LexHTML.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexInno.obj: ..\src\LexInno.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexKix.obj: ..\src\LexKix.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLisp.obj: ..\src\LexLisp.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLout.obj: ..\src\LexLout.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexLua.obj: ..\src\LexLua.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMagik.obj: ..\src\LexMagik.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMarkdown.obj: ..\src\LexMarkdown.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMatlab.obj: ..\src\LexMatlab.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMetapost.obj: ..\src\LexMetapost.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMMIXAL.obj: ..\src\LexMMIXAL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMPT.obj: ..\src\LexMPT.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMSSQL.obj: ..\src\LexMSSQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexMySQL.obj: ..\src\LexMySQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexNimrod.obj: ..\src\LexNimrod.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexNsis.obj: ..\src\LexNsis.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexOpal.obj: ..\src\LexOpal.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexOthers.obj: ..\src\LexOthers.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPascal.obj: ..\src\LexPascal.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPB.obj: ..\src\LexPB.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPerl.obj: ..\src\LexPerl.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPLM.obj: ..\src\LexPLM.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPOV.obj: ..\src\LexPOV.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPowerPro.obj: ..\src\LexPowerPro.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPowerShell.obj: ..\src\LexPowerShell.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexProgress.obj: ..\src\LexProgress.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPS.obj: ..\src\LexPS.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexPython.obj: ..\src\LexPython.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexR.obj: ..\src\LexR.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexRebol.obj: ..\src\LexRebol.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexRuby.obj: ..\src\LexRuby.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexScriptol.obj: ..\src\LexScriptol.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSmalltalk.obj: ..\src\LexSmalltalk.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSML.obj: ..\src\LexSML.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSorcus.obj: ..\src\LexSorcus.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSpecman.obj: ..\src\LexSpecman.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSpice.obj: ..\src\LexSpice.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexSQL.obj: ..\src\LexSQL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTACL.obj: ..\src\LexTACL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTADS3.obj: ..\src\LexTADS3.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTAL.obj: ..\src\LexTAL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTCL.obj: ..\src\LexTCL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexTeX.obj: ..\src\LexTeX.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVB.obj: ..\src\LexVB.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVerilog.obj: ..\src\LexVerilog.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexVHDL.obj: ..\src\LexVHDL.cxx $(LEX_HEADERS)
+
+$(DIR_O)\LexYAML.obj: ..\src\LexYAML.cxx $(LEX_HEADERS)
+
+
+#--Autogenerated -- end of automatically generated section
+
+$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/PerLine.h
+$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h PlatformRes.h \
+ ../src/UniConversion.h ../src/XPM.h
+$(DIR_O)\PositionCache.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+$(DIR_O)\PropSet.obj: ../src/PropSet.cxx ../include/Platform.h ../include/PropSet.h
+$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
+$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h
+$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../include/PropSet.h \
+ ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/ContractionState.h \
+ ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h \
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Selection.h
+$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
+ ../src/Style.h
+$(DIR_O)\StyleContext.obj: ../src/StyleContext.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../src/StyleContext.h
+$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h
+$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \
+ ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
+ ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h
+$(DIR_O)\WindowAccessor.obj: ../src/WindowAccessor.cxx ../include/Platform.h \
+ ../include/PropSet.h ../include/Accessor.h \
+ ../include/WindowAccessor.h ../include/Scintilla.h
+$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
diff --git a/scintilla/zipsrc.bat b/scintilla/zipsrc.bat
new file mode 100644
index 0000000..9d6d08b
--- /dev/null
+++ b/scintilla/zipsrc.bat
@@ -0,0 +1,4 @@
+cd ..
+del/q scintilla.zip
+zip scintilla.zip scintilla\*.* scintilla\*\*.* scintilla\*\*\*.* scintilla\*\*\*\*.* scintilla\*\*\*\*\*.* -x *.o -x *.obj -x *.dll -x *.lib -x *.res -x *.exp
+cd scintilla