anjuta-extras r13 - in trunk: . plugins/sample1 plugins/scintilla plugins/scintilla/properties plugins/scintilla/scintilla plugins/scintilla/scintilla/include plugins/valgrind



Author: mcora
Date: Wed Apr  8 20:49:12 2009
New Revision: 13
URL: http://svn.gnome.org/viewvc/anjuta-extras?rev=13&view=rev

Log:
	* Makefile:
	* configure.ac:
	* plugins/sample1/Makefile.in:
	* plugins/scintilla/Makefile.am:
	* plugins/scintilla/properties/Makefile:
	* plugins/scintilla/properties/Makefile.in:
	* plugins/scintilla/scintilla/AutoComplete.cxx:
	* plugins/scintilla/scintilla/AutoComplete.h:
	* plugins/scintilla/scintilla/CallTip.cxx:
	* plugins/scintilla/scintilla/CallTip.h:
	* plugins/scintilla/scintilla/CellBuffer.cxx:
	* plugins/scintilla/scintilla/CharClassify.cxx:
	* plugins/scintilla/scintilla/CharClassify.h:
	* plugins/scintilla/scintilla/CharacterSet.h:
	* plugins/scintilla/scintilla/ContractionState.cxx:
	* plugins/scintilla/scintilla/ContractionState.h:
	* plugins/scintilla/scintilla/Converter.h:
	* plugins/scintilla/scintilla/Decoration.cxx:
	* plugins/scintilla/scintilla/Decoration.h:
	* plugins/scintilla/scintilla/Document.cxx:
	* plugins/scintilla/scintilla/Document.h:
	* plugins/scintilla/scintilla/DocumentAccessor.cxx:
	* plugins/scintilla/scintilla/DocumentAccessor.h:
	* plugins/scintilla/scintilla/Editor.h:
	* plugins/scintilla/scintilla/ExternalLexer.cxx:
	* plugins/scintilla/scintilla/Indicator.cxx:
	* plugins/scintilla/scintilla/KeyMap.cxx:
	* plugins/scintilla/scintilla/KeyMap.h:
	* plugins/scintilla/scintilla/KeyWords.cxx:
	* plugins/scintilla/scintilla/LexAPDL.cxx:
	* plugins/scintilla/scintilla/LexASY.cxx:
	* plugins/scintilla/scintilla/LexAU3.cxx:
	* plugins/scintilla/scintilla/LexAVE.cxx:
	* plugins/scintilla/scintilla/LexAbaqus.cxx:
	* plugins/scintilla/scintilla/LexAda.cxx:
	* plugins/scintilla/scintilla/LexAsn1.cxx:
	* plugins/scintilla/scintilla/LexBaan.cxx:
	* plugins/scintilla/scintilla/LexBullant.cxx:
	* plugins/scintilla/scintilla/LexCLW.cxx:
	* plugins/scintilla/scintilla/LexCPP.cxx:
	* plugins/scintilla/scintilla/LexCSS.cxx:
	* plugins/scintilla/scintilla/LexCmake.cxx:
	* plugins/scintilla/scintilla/LexConf.cxx:
	* plugins/scintilla/scintilla/LexCrontab.cxx:
	* plugins/scintilla/scintilla/LexCsound.cxx:
	* plugins/scintilla/scintilla/LexD.cxx:
	* plugins/scintilla/scintilla/LexEScript.cxx:
	* plugins/scintilla/scintilla/LexEiffel.cxx:
	* plugins/scintilla/scintilla/LexErlang.cxx:
	* plugins/scintilla/scintilla/LexFlagship.cxx:
	* plugins/scintilla/scintilla/LexForth.cxx:
	* plugins/scintilla/scintilla/LexFortran.cxx:
	* plugins/scintilla/scintilla/LexGAP.cxx:
	* plugins/scintilla/scintilla/LexGui4Cli.cxx:
	* plugins/scintilla/scintilla/LexHTML.cxx:
	* plugins/scintilla/scintilla/LexHaskell.cxx:
	* plugins/scintilla/scintilla/LexInno.cxx:
	* plugins/scintilla/scintilla/LexKix.cxx:
	* plugins/scintilla/scintilla/LexLisp.cxx:
	* plugins/scintilla/scintilla/LexLout.cxx:
	* plugins/scintilla/scintilla/LexLua.cxx:
	* plugins/scintilla/scintilla/LexMMIXAL.cxx:
	* plugins/scintilla/scintilla/LexMPT.cxx:
	* plugins/scintilla/scintilla/LexMSSQL.cxx:
	* plugins/scintilla/scintilla/LexMagik.cxx:
	* plugins/scintilla/scintilla/LexMatlab.cxx:
	* plugins/scintilla/scintilla/LexMetapost.cxx:
	* plugins/scintilla/scintilla/LexMySQL.cxx:
	* plugins/scintilla/scintilla/LexOpal.cxx:
	* plugins/scintilla/scintilla/LexOthers.cxx:
	* plugins/scintilla/scintilla/LexPB.cxx:
	* plugins/scintilla/scintilla/LexPLM.cxx:
	* plugins/scintilla/scintilla/LexPOV.cxx:
	* plugins/scintilla/scintilla/LexPS.cxx:
	* plugins/scintilla/scintilla/LexPascal.cxx:
	* plugins/scintilla/scintilla/LexPerl.cxx:
	* plugins/scintilla/scintilla/LexPowerShell.cxx:
	* plugins/scintilla/scintilla/LexProgress.cxx:
	* plugins/scintilla/scintilla/LexPython.cxx:
	* plugins/scintilla/scintilla/LexR.cxx:
	* plugins/scintilla/scintilla/LexRebol.cxx:
	* plugins/scintilla/scintilla/LexRuby.cxx:
	* plugins/scintilla/scintilla/LexSQL.cxx:
	* plugins/scintilla/scintilla/LexSmalltalk.cxx:
	* plugins/scintilla/scintilla/LexSpecman.cxx:
	* plugins/scintilla/scintilla/LexSpice.cxx:
	* plugins/scintilla/scintilla/LexTADS3.cxx:
	* plugins/scintilla/scintilla/LexTeX.cxx:
	* plugins/scintilla/scintilla/LexVB.cxx:
	* plugins/scintilla/scintilla/LexVHDL.cxx:
	* plugins/scintilla/scintilla/LexVerilog.cxx:
	* plugins/scintilla/scintilla/LineMarker.cxx:
	* plugins/scintilla/scintilla/LineMarker.h:
	* plugins/scintilla/scintilla/PlatGTK.cxx:
	* plugins/scintilla/scintilla/PositionCache.cxx:
	* plugins/scintilla/scintilla/PositionCache.h:
	* plugins/scintilla/scintilla/PropSet.cxx:
	* plugins/scintilla/scintilla/RESearch.cxx:
	* plugins/scintilla/scintilla/RESearch.h:
	* plugins/scintilla/scintilla/RunStyles.cxx:
	* plugins/scintilla/scintilla/RunStyles.h:
	* plugins/scintilla/scintilla/SVector.h:
	* plugins/scintilla/scintilla/ScintillaBase.cxx:
	* plugins/scintilla/scintilla/ScintillaBase.h:
	* plugins/scintilla/scintilla/ScintillaGTK.cxx:
	* plugins/scintilla/scintilla/SplitVector.h:
	* plugins/scintilla/scintilla/Style.cxx:
	* plugins/scintilla/scintilla/Style.h:
	* plugins/scintilla/scintilla/StyleContext.cxx:
	* plugins/scintilla/scintilla/StyleContext.h:
	* plugins/scintilla/scintilla/UniConversion.cxx:
	* plugins/scintilla/scintilla/UniConversion.h:
	* plugins/scintilla/scintilla/ViewStyle.cxx:
	* plugins/scintilla/scintilla/ViewStyle.h:
	* plugins/scintilla/scintilla/WindowAccessor.cxx:
	* plugins/scintilla/scintilla/XPM.cxx:
	* plugins/scintilla/scintilla/XPM.h:
	* plugins/scintilla/scintilla/include/Makefile.in:
	* plugins/scintilla/scintilla/scintilla-marshal.c
	(scintilla_marshal_VOID__INT_POINTER):
	* plugins/scintilla/scintilla/scintilla-marshal.h:
	* plugins/scintilla/scintilla/scintilla-marshal.list:
	* plugins/scintilla/scintilla/test-scintilla.cxx:
	* plugins/scintilla/scintilla/update-properties.pl:
	added some more files left out.


Added:
   trunk/plugins/scintilla/scintilla/AutoComplete.cxx
   trunk/plugins/scintilla/scintilla/AutoComplete.h
   trunk/plugins/scintilla/scintilla/CallTip.cxx
   trunk/plugins/scintilla/scintilla/CallTip.h
   trunk/plugins/scintilla/scintilla/CellBuffer.cxx
   trunk/plugins/scintilla/scintilla/CharClassify.cxx
   trunk/plugins/scintilla/scintilla/CharClassify.h
   trunk/plugins/scintilla/scintilla/CharacterSet.h
   trunk/plugins/scintilla/scintilla/ContractionState.cxx
   trunk/plugins/scintilla/scintilla/ContractionState.h
   trunk/plugins/scintilla/scintilla/Converter.h
   trunk/plugins/scintilla/scintilla/Decoration.cxx
   trunk/plugins/scintilla/scintilla/Decoration.h
   trunk/plugins/scintilla/scintilla/Document.cxx
   trunk/plugins/scintilla/scintilla/Document.h
   trunk/plugins/scintilla/scintilla/DocumentAccessor.cxx
   trunk/plugins/scintilla/scintilla/DocumentAccessor.h
   trunk/plugins/scintilla/scintilla/Editor.h
   trunk/plugins/scintilla/scintilla/ExternalLexer.cxx
   trunk/plugins/scintilla/scintilla/Indicator.cxx
   trunk/plugins/scintilla/scintilla/KeyMap.cxx
   trunk/plugins/scintilla/scintilla/KeyMap.h
   trunk/plugins/scintilla/scintilla/KeyWords.cxx
   trunk/plugins/scintilla/scintilla/LexAPDL.cxx
   trunk/plugins/scintilla/scintilla/LexASY.cxx
   trunk/plugins/scintilla/scintilla/LexAU3.cxx
   trunk/plugins/scintilla/scintilla/LexAVE.cxx
   trunk/plugins/scintilla/scintilla/LexAbaqus.cxx
   trunk/plugins/scintilla/scintilla/LexAda.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/LexAsn1.cxx
   trunk/plugins/scintilla/scintilla/LexBaan.cxx
   trunk/plugins/scintilla/scintilla/LexBullant.cxx
   trunk/plugins/scintilla/scintilla/LexCLW.cxx
   trunk/plugins/scintilla/scintilla/LexCPP.cxx
   trunk/plugins/scintilla/scintilla/LexCSS.cxx
   trunk/plugins/scintilla/scintilla/LexCmake.cxx
   trunk/plugins/scintilla/scintilla/LexConf.cxx
   trunk/plugins/scintilla/scintilla/LexCrontab.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/LexCsound.cxx
   trunk/plugins/scintilla/scintilla/LexD.cxx
   trunk/plugins/scintilla/scintilla/LexEScript.cxx
   trunk/plugins/scintilla/scintilla/LexEiffel.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/LexErlang.cxx
   trunk/plugins/scintilla/scintilla/LexFlagship.cxx
   trunk/plugins/scintilla/scintilla/LexForth.cxx
   trunk/plugins/scintilla/scintilla/LexFortran.cxx
   trunk/plugins/scintilla/scintilla/LexGAP.cxx
   trunk/plugins/scintilla/scintilla/LexGui4Cli.cxx
   trunk/plugins/scintilla/scintilla/LexHTML.cxx
   trunk/plugins/scintilla/scintilla/LexHaskell.cxx
   trunk/plugins/scintilla/scintilla/LexInno.cxx
   trunk/plugins/scintilla/scintilla/LexKix.cxx
   trunk/plugins/scintilla/scintilla/LexLisp.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/LexLout.cxx
   trunk/plugins/scintilla/scintilla/LexLua.cxx
   trunk/plugins/scintilla/scintilla/LexMMIXAL.cxx
   trunk/plugins/scintilla/scintilla/LexMPT.cxx
   trunk/plugins/scintilla/scintilla/LexMSSQL.cxx
   trunk/plugins/scintilla/scintilla/LexMagik.cxx
   trunk/plugins/scintilla/scintilla/LexMatlab.cxx
   trunk/plugins/scintilla/scintilla/LexMetapost.cxx
   trunk/plugins/scintilla/scintilla/LexMySQL.cxx
   trunk/plugins/scintilla/scintilla/LexOpal.cxx
   trunk/plugins/scintilla/scintilla/LexOthers.cxx
   trunk/plugins/scintilla/scintilla/LexPB.cxx
   trunk/plugins/scintilla/scintilla/LexPLM.cxx
   trunk/plugins/scintilla/scintilla/LexPOV.cxx
   trunk/plugins/scintilla/scintilla/LexPS.cxx
   trunk/plugins/scintilla/scintilla/LexPascal.cxx
   trunk/plugins/scintilla/scintilla/LexPerl.cxx
   trunk/plugins/scintilla/scintilla/LexPowerShell.cxx
   trunk/plugins/scintilla/scintilla/LexProgress.cxx
   trunk/plugins/scintilla/scintilla/LexPython.cxx
   trunk/plugins/scintilla/scintilla/LexR.cxx
   trunk/plugins/scintilla/scintilla/LexRebol.cxx
   trunk/plugins/scintilla/scintilla/LexRuby.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/LexSQL.cxx
   trunk/plugins/scintilla/scintilla/LexSmalltalk.cxx
   trunk/plugins/scintilla/scintilla/LexSpecman.cxx
   trunk/plugins/scintilla/scintilla/LexSpice.cxx
   trunk/plugins/scintilla/scintilla/LexTADS3.cxx
   trunk/plugins/scintilla/scintilla/LexTeX.cxx
   trunk/plugins/scintilla/scintilla/LexVB.cxx
   trunk/plugins/scintilla/scintilla/LexVHDL.cxx
   trunk/plugins/scintilla/scintilla/LexVerilog.cxx
   trunk/plugins/scintilla/scintilla/LineMarker.cxx
   trunk/plugins/scintilla/scintilla/LineMarker.h
   trunk/plugins/scintilla/scintilla/PlatGTK.cxx
   trunk/plugins/scintilla/scintilla/PositionCache.cxx
   trunk/plugins/scintilla/scintilla/PositionCache.h
   trunk/plugins/scintilla/scintilla/PropSet.cxx
   trunk/plugins/scintilla/scintilla/RESearch.cxx
   trunk/plugins/scintilla/scintilla/RESearch.h
   trunk/plugins/scintilla/scintilla/RunStyles.cxx
   trunk/plugins/scintilla/scintilla/RunStyles.h
   trunk/plugins/scintilla/scintilla/SVector.h
   trunk/plugins/scintilla/scintilla/ScintillaBase.cxx
   trunk/plugins/scintilla/scintilla/ScintillaBase.h
   trunk/plugins/scintilla/scintilla/ScintillaGTK.cxx
   trunk/plugins/scintilla/scintilla/SplitVector.h
   trunk/plugins/scintilla/scintilla/Style.cxx
   trunk/plugins/scintilla/scintilla/Style.h
   trunk/plugins/scintilla/scintilla/StyleContext.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/StyleContext.h   (contents, props changed)
   trunk/plugins/scintilla/scintilla/UniConversion.cxx
   trunk/plugins/scintilla/scintilla/UniConversion.h
   trunk/plugins/scintilla/scintilla/ViewStyle.cxx
   trunk/plugins/scintilla/scintilla/ViewStyle.h
   trunk/plugins/scintilla/scintilla/WindowAccessor.cxx
   trunk/plugins/scintilla/scintilla/XPM.cxx   (contents, props changed)
   trunk/plugins/scintilla/scintilla/XPM.h   (contents, props changed)
   trunk/plugins/scintilla/scintilla/scintilla-marshal.c
   trunk/plugins/scintilla/scintilla/scintilla-marshal.h
   trunk/plugins/scintilla/scintilla/scintilla-marshal.list
   trunk/plugins/scintilla/scintilla/test-scintilla.cxx
   trunk/plugins/scintilla/scintilla/update-properties.pl   (contents, props changed)
Removed:
   trunk/plugins/scintilla/properties/Makefile
   trunk/plugins/scintilla/properties/Makefile.in
   trunk/plugins/scintilla/scintilla/include/Makefile.in
   trunk/plugins/valgrind/Makefile
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/plugins/sample1/Makefile.in
   trunk/plugins/scintilla/Makefile.am

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Wed Apr  8 20:49:12 2009
@@ -17,9 +17,13 @@
 
 BINUTILS_REQUIRED=2.15.92
 LIBGRAPHVIZ_REQUIRED=1.0
+GTK_REQUIRED=2.14.0
+GLIB_REQUIRED=2.16.0
 
 AC_SUBST(LIBGRAPHVIZ_REQUIRED)
 AC_SUBST(BINUTILS_REQUIRED)
+AC_SUBST(GTK_REQUIRED)
+AC_SUBST(GLIB_REQUIRED)
 
 dnl Compiler settings
 dnl ---------------------------------------------------------------------------
@@ -241,4 +245,4 @@
         echo "Building Scintilla based editor: .......................YES"
 else
         echo "Building Scintilla based editor: .......................NO"
-fi
\ No newline at end of file
+fi

Modified: trunk/plugins/sample1/Makefile.in
==============================================================================
--- trunk/plugins/sample1/Makefile.in	(original)
+++ trunk/plugins/sample1/Makefile.in	Wed Apr  8 20:49:12 2009
@@ -126,11 +126,13 @@
 GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
 GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
 GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_REQUIRED = @GLIB_REQUIRED@
 GMOFILES = @GMOFILES@
 GMSGFMT = @GMSGFMT@
 GRAPHVIZ_CFLAGS = @GRAPHVIZ_CFLAGS@
 GRAPHVIZ_LIBS = @GRAPHVIZ_LIBS@
 GREP = @GREP@
+GTK_REQUIRED = @GTK_REQUIRED@
 HAVE_GRAPHVIZ_FALSE = @HAVE_GRAPHVIZ_FALSE@
 HAVE_GRAPHVIZ_TRUE = @HAVE_GRAPHVIZ_TRUE@
 HAVE_PLUGIN_SCINTILLA_FALSE = @HAVE_PLUGIN_SCINTILLA_FALSE@

Modified: trunk/plugins/scintilla/Makefile.am
==============================================================================
--- trunk/plugins/scintilla/Makefile.am	(original)
+++ trunk/plugins/scintilla/Makefile.am	Wed Apr  8 20:49:12 2009
@@ -25,9 +25,9 @@
 	$(GIO_CFLAGS) \
 	$(LIBANJUTA_CFLAGS) \
 	$(GTK_CFLAGS) \
-	$(GNOME_CFLAGS) \
-	-I$(srcdir)/scintilla/include
-	-DG_LOG_DOMAIN=\"libanjuta-editor\"
+  $(GLIB_CFLAGS) \
+	-I$(srcdir)/scintilla/include \
+	-DG_LOG_DOMAIN=\"libanjuta-scintilla\"
 
 libanjuta_editor_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
 
@@ -35,9 +35,8 @@
 	$(GIO_LIBS) \
 	$(LIBANJUTA_LIBS) \
 	$(GTK_LIBS) \
-	$(GNOME_LIBS) \
-	$(GLADE_LIBS) \
-	scintilla/libanjuta-scintilla.la
+  $(GLIB_LIBS) \
+	$(GLADE_LIBS)
 
 libanjuta_editor_la_SOURCES= \
 	properties.cxx \

Added: trunk/plugins/scintilla/scintilla/AutoComplete.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/AutoComplete.cxx	Wed Apr  8 20:49:12 2009
@@ -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 "PropSet.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() {
+	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() {
+	return separator;
+}
+
+void AutoComplete::SetTypesep(char separator_) {
+	typesep = separator_;
+}
+
+char AutoComplete::GetTypesep() {
+	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);
+}
+

Added: trunk/plugins/scintilla/scintilla/AutoComplete.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/AutoComplete.h	Wed Apr  8 20:49:12 2009
@@ -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();
+
+	/// 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();
+
+	/// The typesep character is used for seperating the word from the type
+	void SetTypesep(char separator_);
+	char GetTypesep();
+
+	/// The list string contains a sequence of words separated by the separator character
+	void SetList(const char *list);
+
+	void Show(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

Added: trunk/plugins/scintilla/scintilla/CallTip.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CallTip.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,329 @@
+// 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) {
+	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;
+	if (val)
+		delete []val;
+	val = new char[strlen(defn) + 1];
+	if (!val)
+		return PRectangle();
+	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;
+}

Added: trunk/plugins/scintilla/scintilla/CallTip.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CallTip.h	Wed Apr  8 20:49:12 2009
@@ -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 &) { return *this; }
+	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);
+	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

Added: trunk/plugins/scintilla/scintilla/CellBuffer.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CellBuffer.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,939 @@
+// 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
+
+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;
+}
+
+LineVector::LineVector() : starts(256) {
+	handleCurrent = 1;
+
+	Init();
+}
+
+LineVector::~LineVector() {
+	starts.DeleteAll();
+	for (int line = 0; line < markers.Length(); line++) {
+		delete markers[line];
+		markers[line] = 0;
+	}
+	markers.DeleteAll();
+	levels.DeleteAll();
+}
+
+void LineVector::Init() {
+	starts.DeleteAll();
+	for (int line = 0; line < markers.Length(); line++) {
+		delete markers[line];
+		markers[line] = 0;
+	}
+	markers.DeleteAll();
+	levels.DeleteAll();
+}
+
+void LineVector::ExpandLevels(int sizeNew) {
+	levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
+}
+
+void LineVector::ClearLevels() {
+	levels.DeleteAll();
+}
+
+int LineVector::SetLevel(int line, int level) {
+	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 LineVector::GetLevel(int line) {
+	if (levels.Length() && (line >= 0) && (line < Lines())) {
+		return levels[line];
+	} else {
+		return SC_FOLDLEVELBASE;
+	}
+}
+
+void LineVector::InsertText(int line, int delta) {
+	starts.InsertText(line, delta);
+}
+
+void LineVector::InsertLine(int line, int position) {
+	starts.InsertPartition(line, position);
+	if (markers.Length()) {
+		markers.Insert(line, 0);
+	}
+	if (levels.Length()) {
+		int level = SC_FOLDLEVELBASE;
+		if ((line > 0) && (line < Lines())) {
+			level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG;
+		}
+		levels.InsertValue(line, 1, level);
+	}
+}
+
+void LineVector::SetLineStart(int line, int position) {
+	starts.SetPartitionStartPosition(line, position);
+}
+
+void LineVector::RemoveLine(int line) {
+	starts.RemovePartition(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);
+	}
+	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 > 0)
+			levels[line-1] |= firstHeader;
+	}
+}
+
+int LineVector::LineFromPosition(int pos) {
+	return starts.PartitionFromPosition(pos);
+}
+
+int LineVector::MarkValue(int line) {
+	if (markers.Length() && markers[line])
+		return markers[line]->MarkValue();
+	else
+		return 0;
+}
+
+int LineVector::AddMark(int line, int markerNum) {
+	handleCurrent++;
+	if (!markers.Length()) {
+		// No existing markers so allocate one element per line
+		markers.InsertValue(0, Lines(), 0);
+	}
+	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 LineVector::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;
+	}
+}
+
+void LineVector::DeleteMark(int line, int markerNum, bool all) {
+	if (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 LineVector::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;
+		}
+	}
+}
+
+int LineVector::LineFromHandle(int markerHandle) {
+	if (markers.Length()) {
+		for (int line = 0; line < Lines(); line++) {
+			if (markers[line]) {
+				if (markers[line]->Contains(markerHandle)) {
+					return line;
+				}
+			}
+		}
+	}
+	return -1;
+}
+
+Action::Action() {
+	at = startAction;
+	position = 0;
+	data = 0;
+	lenData = 0;
+}
+
+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];
+		if (!actionsNew)
+			return;
+		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) {
+	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
+			Action &actPrevious = actions[currentAction - 1];
+			// See if current action can be coalesced into previous action
+			// Will work if both are inserts or deletes and position is same
+			if (at != actPrevious.at) {
+				currentAction++;
+			} else if (currentAction == savePoint) {
+				currentAction++;
+			} else if ((at == insertAction) &&
+			           (position != (actPrevious.position + actPrevious.lenData))) {
+				// Insertions must be immediately after to coalesce
+				currentAction++;
+			} else if (!actions[currentAction].mayCoalesce) {
+				// Not allowed to coalesce if this set
+				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);
+	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) {
+	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) {
+	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);
+}
+
+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() {
+	return readOnly;
+}
+
+void CellBuffer::SetReadOnly(bool set) {
+	readOnly = set;
+}
+
+void CellBuffer::SetSavePoint() {
+	uh.SetSavePoint();
+}
+
+bool CellBuffer::IsSavePoint() {
+	return uh.IsSavePoint();
+}
+
+int CellBuffer::AddMark(int line, int markerNum) {
+	if ((line >= 0) && (line < Lines())) {
+		return lv.AddMark(line, markerNum);
+	}
+	return - 1;
+}
+
+void CellBuffer::DeleteMark(int line, int markerNum) {
+	if ((line >= 0) && (line < Lines())) {
+		lv.DeleteMark(line, markerNum, false);
+	}
+}
+
+void CellBuffer::DeleteMarkFromHandle(int markerHandle) {
+	lv.DeleteMarkFromHandle(markerHandle);
+}
+
+int CellBuffer::GetMark(int line) {
+	if ((line >= 0) && (line < Lines()))
+		return lv.MarkValue(line);
+	return 0;
+}
+
+void CellBuffer::DeleteAllMarks(int markerNum) {
+	for (int line = 0; line < Lines(); line++) {
+		lv.DeleteMark(line, markerNum, true);
+	}
+}
+
+int CellBuffer::LineFromHandle(int markerHandle) {
+	return lv.LineFromHandle(markerHandle);
+}
+
+// Without undo
+
+void CellBuffer::InsertLine(int line, int position) {
+	lv.InsertLine(line, position);
+	if (lineStates.Length()) {
+		lineStates.EnsureLength(line);
+		lineStates.Insert(line, 0);
+	}
+}
+
+void CellBuffer::RemoveLine(int line) {
+	lv.RemoveLine(line);
+	if (lineStates.Length() > line) {
+		lineStates.Delete(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;
+	// 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);
+		lineInsert++;
+	}
+	char ch = ' ';
+	for (int i = 0; i < insertLength; i++) {
+		ch = s[i];
+		if (ch == '\r') {
+			InsertLine(lineInsert, (position + i) + 1);
+			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);
+				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() {
+	return collectingUndo;
+}
+
+void CellBuffer::BeginUndoAction() {
+	uh.BeginUndoAction();
+}
+
+void CellBuffer::EndUndoAction() {
+	uh.EndUndoAction();
+}
+
+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();
+}
+
+int CellBuffer::SetLineState(int line, int state) {
+	lineStates.EnsureLength(line + 1);
+	int stateOld = lineStates[line];
+	lineStates[line] = state;
+	return stateOld;
+}
+
+int CellBuffer::GetLineState(int line) {
+	lineStates.EnsureLength(line + 1);
+	return lineStates[line];
+}
+
+int CellBuffer::GetMaxLineState() {
+	return lineStates.Length();
+}
+
+int CellBuffer::SetLevel(int line, int level) {
+	return lv.SetLevel(line, level);
+}
+
+int CellBuffer::GetLevel(int line) {
+	return lv.GetLevel(line);
+}
+
+void CellBuffer::ClearLevels() {
+	lv.ClearLevels();
+}

Added: trunk/plugins/scintilla/scintilla/CharClassify.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CharClassify.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,43 @@
+// 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 <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++;
+		}
+	}
+}

Added: trunk/plugins/scintilla/scintilla/CharClassify.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CharClassify.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,25 @@
+// Scintilla source code edit control
+/** @file CharClassify.h
+ ** 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.
+
+#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
+};
+#endif

Added: trunk/plugins/scintilla/scintilla/CharacterSet.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/CharacterSet.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,58 @@
+// 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);
+		return (val < size) ? bset[val] : valueAfter;
+	}
+};

Added: trunk/plugins/scintilla/scintilla/ContractionState.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ContractionState.cxx	Wed Apr  8 20:49:12 2009
@@ -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
+}

Added: trunk/plugins/scintilla/scintilla/ContractionState.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ContractionState.h	Wed Apr  8 20:49:12 2009
@@ -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

Added: trunk/plugins/scintilla/scintilla/Converter.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Converter.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,87 @@
+// 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.
+
+#include <iconv.h>
+#if GTK_MAJOR_VERSION >= 2
+	typedef GIConv ConverterHandle;
+#else
+	typedef iconv_t ConverterHandle;
+#endif
+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) {
+#if GTK_MAJOR_VERSION >= 2
+		iconvh = g_iconv_open(fullDestination, charSetSource);
+#else
+		iconvh = iconv_open(fullDestination, charSetSource);
+#endif
+	}
+	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()) {
+#if GTK_MAJOR_VERSION >= 2
+			g_iconv_close(iconvh);
+#else
+			iconv_close(iconvh);
+#endif
+			iconvh = iconvhBad;
+		}
+	}
+	size_t Convert(char** src, size_t *srcleft, char **dst, size_t *dstleft) const {
+		if (!Succeeded()) {
+			return (size_t)(-1);
+		} else {
+#if GTK_MAJOR_VERSION >= 2
+			return iconv_adaptor(g_iconv, iconvh, src, srcleft, dst, dstleft);
+#else
+			return iconv_adaptor(iconv, iconvh, src, srcleft, dst, dstleft);
+#endif
+		}
+	}
+};

Added: trunk/plugins/scintilla/scintilla/Decoration.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Decoration.cxx	Wed Apr  8 20:49:12 2009
@@ -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;
+}

Added: trunk/plugins/scintilla/scintilla/Decoration.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Decoration.h	Wed Apr  8 20:49:12 2009
@@ -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() { return currentIndicator; }
+
+	void SetCurrentValue(int value);
+	int GetCurrentValue() { 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

Added: trunk/plugins/scintilla/scintilla/Document.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Document.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,1664 @@
+// 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 "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "CellBuffer.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "Document.h"
+#include "RESearch.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;
+}
+
+Document::~Document() {
+	for (int i = 0; i < lenWatchers; i++) {
+		watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
+	}
+	delete []watchers;
+	watchers = 0;
+	lenWatchers = 0;
+	delete regex;
+	regex = 0;
+}
+
+// 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::AddMark(int line, int markerNum) {
+	int prev = cb.AddMark(line, markerNum);
+	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+	NotifyModified(mh);
+	return prev;
+}
+
+void Document::AddMarkSet(int line, int valueSet) {
+	unsigned int m = valueSet;
+	for (int i = 0; m; i++, m >>= 1)
+		if (m & 1)
+			cb.AddMark(line, i);
+	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+	NotifyModified(mh);
+}
+
+void Document::DeleteMark(int line, int markerNum) {
+	cb.DeleteMark(line, markerNum);
+	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+	NotifyModified(mh);
+}
+
+void Document::DeleteMarkFromHandle(int markerHandle) {
+	cb.DeleteMarkFromHandle(markerHandle);
+	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+	mh.line = -1;
+	NotifyModified(mh);
+}
+
+void Document::DeleteAllMarks(int markerNum) {
+	cb.DeleteAllMarks(markerNum);
+	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+	mh.line = -1;
+	NotifyModified(mh);
+}
+
+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) {
+	return cb.LineFromPosition(pos);
+}
+
+int Document::LineEndPosition(int position) {
+	return LineEnd(LineFromPosition(position));
+}
+
+int Document::VCHomePosition(int position) {
+	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 = cb.SetLevel(line, level);
+	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;
+}
+
+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 {
+					NotifyModified(DocModification(
+									SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
+				}
+				cb.PerformUndoStep();
+				int cellPosition = action.position;
+				ModifiedAt(cellPosition);
+				newPos = cellPosition;
+
+				int modFlags = SC_PERFORMED_UNDO;
+				// With undo, an insertion action becomes a deletion notification
+				if (action.at == removeAction) {
+					newPos += action.lenData;
+					modFlags |= SC_MOD_INSERTTEXT;
+				} else {
+					modFlags |= SC_MOD_DELETETEXT;
+				}
+				if (steps > 1)
+					modFlags |= SC_MULTISTEPUNDOREDO;
+				const int linesAdded = LinesTotal() - prevLinesTotal;
+				if (linesAdded != 0)
+					multiLine = true;
+				if (step == steps - 1) {
+					modFlags |= SC_LASTSTEPINUNDOREDO;
+					if (multiLine)
+						modFlags |= SC_MULTILINEUNDOREDO;
+				}
+				NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
+											   linesAdded, action.data));
+			}
+
+			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 {
+					NotifyModified(DocModification(
+									SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
+				}
+				cb.PerformRedoStep();
+				ModifiedAt(action.position);
+				newPos = action.position;
+
+				int modFlags = SC_PERFORMED_REDO;
+				if (action.at == insertAction) {
+					newPos += action.lenData;
+					modFlags |= SC_MOD_INSERTTEXT;
+				} else {
+					modFlags |= SC_MOD_DELETETEXT;
+				}
+				if (steps > 1)
+					modFlags |= SC_MULTISTEPUNDOREDO;
+				const int linesAdded = LinesTotal() - prevLinesTotal;
+				if (linesAdded != 0)
+					multiLine = true;
+				if (step == steps - 1) {
+					modFlags |= SC_LASTSTEPINUNDOREDO;
+					if (multiLine)
+						modFlags |= SC_MULTILINEUNDOREDO;
+				}
+				NotifyModified(
+					DocModification(modFlags, action.position, action.lenData,
+									linesAdded, action.data));
+			}
+
+			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);
+		BeginUndoAction();
+		DeleteChars(thisLineStart, indentPos - thisLineStart);
+		InsertCString(thisLineStart, linebuf);
+		EndUndoAction();
+	}
+}
+
+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);
+	int columnCurrent = 0;
+	if ((line >= 0) && (line < LinesTotal())) {
+		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) {
+	BeginUndoAction();
+
+	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
+			}
+		}
+	}
+
+	EndUndoAction();
+}
+
+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);
+}
+
+/**
+ * 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);
+}
+
+// The comparison and case changing functions here assume ASCII
+// or extended ASCII such as the normal Windows code page.
+
+static inline char MakeUpperCase(char ch) {
+	if (ch < 'a' || ch > 'z')
+		return ch;
+	else
+		return static_cast<char>(ch - 'a' + 'A');
+}
+
+static inline char MakeLowerCase(char ch) {
+	if (ch < 'A' || ch > 'Z')
+		return ch;
+	else
+		return static_cast<char>(ch - 'A' + 'a');
+}
+
+/**
+ * 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 *s,
+                        bool caseSensitive, bool word, bool wordStart, bool regExp, int flags,
+                        int *length) {
+	if (regExp) {
+		if (!regex)
+			regex = CreateRegexSearch(&charClass);
+		return regex->FindText(this, minPos, maxPos, s, caseSensitive, word, wordStart, flags, length);
+	} else {
+
+		bool forward = minPos <= maxPos;
+		int increment = forward ? 1 : -1;
+
+		// Range endpoints should not be inside DBCS characters, but just in case, move them.
+		int startPos = MovePositionOutsideChar(minPos, increment, false);
+		int endPos = MovePositionOutsideChar(maxPos, increment, false);
+
+		// Compute actual search ranges needed
+		int lengthFind = *length;
+		if (lengthFind == -1)
+			lengthFind = static_cast<int>(strlen(s));
+		int endSearch = endPos;
+		if (startPos <= endPos) {
+			endSearch = endPos - lengthFind + 1;
+		}
+		//Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
+		char firstChar = s[0];
+		if (!caseSensitive)
+			firstChar = static_cast<char>(MakeUpperCase(firstChar));
+		int pos = forward ? startPos : (startPos - 1);
+		while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+			char ch = CharAt(pos);
+			if (caseSensitive) {
+				if (ch == firstChar) {
+					bool found = true;
+					if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
+					for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+						ch = CharAt(pos + posMatch);
+						if (ch != s[posMatch])
+							found = false;
+					}
+					if (found) {
+						if ((!word && !wordStart) ||
+						        word && IsWordAt(pos, pos + lengthFind) ||
+						        wordStart && IsWordStartAt(pos))
+							return pos;
+					}
+				}
+			} else {
+				if (MakeUpperCase(ch) == firstChar) {
+					bool found = true;
+					if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
+					for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+						ch = CharAt(pos + posMatch);
+						if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch]))
+							found = false;
+					}
+					if (found) {
+						if ((!word && !wordStart) ||
+						        word && IsWordAt(pos, pos + lengthFind) ||
+						        wordStart && IsWordStartAt(pos))
+							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, 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 = cb.SetLineState(line, state);
+	if (state != statePrevious) {
+		DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
+		NotifyModified(mh);
+	}
+	return statePrevious;
+}
+
+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];
+	if (!pwNew)
+		return false;
+	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];
+				if (!pwNew)
+					return false;
+				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);
+		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':
+					i++;
+				}
+				lenResult++;
+			}
+		} else {
+			lenResult++;
+		}
+	}
+	substituted = new char[lenResult + 1];
+	if (!substituted)
+		return 0;
+	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;
+				default:
+					*o++ = '\\';
+					j--;
+				}
+			}
+		} else {
+			*o++ = text[j];
+		}
+	}
+	*o = '\0';
+	*length = lenResult;
+	return substituted;
+}
+
+#ifndef SCI_OWNREGEX
+
+RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) {
+	return new BuiltinRegex(charClassTable);
+}
+
+#endif

Added: trunk/plugins/scintilla/scintilla/Document.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Document.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,333 @@
+// 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);
+
+/**
+ */
+class Document {
+
+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;
+
+	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();
+
+	int LineFromPosition(int pos);
+	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 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) {
+		cb.GetCharRange(buffer, position, lengthRetrieve);
+	}
+	char StyleAt(int position) { return cb.StyleAt(position); }
+	int GetMark(int line) { return cb.GetMark(line); }
+	int AddMark(int line, int markerNum);
+	void AddMarkSet(int line, int valueSet);
+	void DeleteMark(int line, int markerNum);
+	void DeleteMarkFromHandle(int markerHandle);
+	void DeleteAllMarks(int markerNum);
+	int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
+	int LineStart(int line) const;
+	int LineEnd(int line) const;
+	int LineEndPosition(int position);
+	int VCHomePosition(int position);
+
+	int SetLevel(int line, int level);
+	int GetLevel(int line) { return cb.GetLevel(line); }
+	void ClearLevels() { cb.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); }
+	long FindText(int minPos, int maxPos, const char *s,
+		bool caseSensitive, bool word, bool wordStart, bool regExp, int flags, int *length);
+	long FindText(int iMessage, unsigned long wParam, long lParam);
+	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, 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) { return cb.GetLineState(line); }
+	int GetMaxLineState() { return cb.GetMaxLineState(); }
+
+	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);
+};
+
+/**
+ * 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;
+
+	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) {}
+
+	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) {}
+};
+
+/**
+ * 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

Added: trunk/plugins/scintilla/scintilla/DocumentAccessor.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/DocumentAccessor.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+}

Added: trunk/plugins/scintilla/scintilla/DocumentAccessor.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/DocumentAccessor.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,76 @@
+// 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) : Accessor(), props(source.props) {}
+	DocumentAccessor &operator=(const DocumentAccessor &) { return *this; }
+
+protected:
+	Document *pdoc;
+	PropSet &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_, PropSet &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

Added: trunk/plugins/scintilla/scintilla/Editor.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Editor.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,522 @@
+// 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();
+};
+
+/**
+ * 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 = new char[len_];
+		if (s) {
+			len = len_;
+			for (int i = 0; i < len_; i++) {
+				s[i] = s_[i];
+			}
+		} else {
+			len = 0;
+		}
+		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 &) : DocWatcher() {}
+	Editor &operator=(const Editor &) { return *this; }
+
+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;
+	int errorStatus;
+	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;
+
+	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;
+	int posDrag;
+	int posDrop;
+	int lastXChosen;
+	int lineAnchor;
+	int originalAnchorPos;
+	int currentPos;
+	int anchor;
+	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;
+
+	int modEventMask;
+
+	SelectionText drag;
+	enum selTypes { noSel, selStream, selRectangle, selLines };
+	selTypes selType;
+	bool moveExtendsSelection;
+	int xStartSelect;	///< x position of start of rectangular selection
+	int xEndSelect;		///< x position of end of rectangular selection
+	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 actualWrapVisualStartIndent;
+
+	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();
+	Point LocationFromPosition(int pos);
+	int XFromPosition(int pos);
+	int PositionFromLocation(Point pt);
+	int PositionFromLocationClose(Point pt);
+	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);
+	PRectangle RectangleFromRange(int start, int end);
+	void InvalidateRange(int start, int end);
+
+	int CurrentPosition();
+	bool SelectionEmpty();
+	int SelectionStart();
+	int SelectionEnd();
+	void SetRectangularRange();
+	void InvalidateSelection(int currentPos_, int anchor_, bool invalidateWholeSelection);
+	void SetSelection(int currentPos_, int anchor_);
+	void SetSelection(int currentPos_);
+	void SetEmptySelection(int currentPos_);
+	bool RangeContainsProtected(int start, int end) const;
+	bool SelectionContainsProtected();
+	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
+	int MovePositionTo(int newPos, selTypes sel=noSel, bool ensureVisible=true);
+	int MovePositionSoVisible(int pos, int moveDir);
+	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);
+	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);
+	ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, bool 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 DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+		PRectangle rcLine, LineLayout *ll, int subLine=0);
+	void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret);
+	void RefreshPixMaps(Surface *surfaceWindow);
+	void Paint(Surface *surfaceWindow, PRectangle rcArea);
+	long FormatRange(bool draw, 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 AddChar(char ch);
+	virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
+	void ClearSelection();
+	void ClearAll();
+	void ClearDocumentStyle();
+	void Cut();
+	void PasteRectangular(int 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 NotifyMove(int position);
+	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, selTypes sel=noSel, bool stuttered = false);
+	void ChangeCaseOfSelection(bool makeUpperCase);
+	void LineTranspose();
+	void Duplicate(bool forLine);
+	virtual void CancelModes();
+	void NewLine();
+	void CursorUpOrDown(int direction, selTypes sel=noSel);
+	void ParaUpOrDown(int direction, selTypes sel=noSel);
+	int StartEndDisplayLine(int pos, bool start);
+	virtual int KeyCommand(unsigned int iMessage);
+	virtual int KeyDefault(int /* key */, int /*modifiers*/);
+	int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0);
+
+	int GetWhitespaceVisible();
+	void SetWhitespaceVisible(int view);
+
+	void Indent(bool forwards);
+
+	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 CopySelectionFromRange(SelectionText *ss, bool allowLineCopy, 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(int newPos);
+	virtual void DisplayCursor(Window::Cursor c);
+	virtual bool DragThreshold(Point ptStart, Point ptNow);
+	virtual void StartDrag();
+	void DropAt(int position, const char *value, bool moving, bool rectangular);
+	/** PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after.
+	 * Before means either before any line of selection or before selection on its line, with a similar meaning to after. */
+	int PositionInSelection(int pos);
+	bool PointInSelection(Point pt);
+	bool PointInSelMargin(Point pt);
+	void LineSelection(int lineCurrent_, int lineAnchor_);
+	void DwellEnd(bool mouseMoved);
+	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);
+
+	virtual bool PaintContains(PRectangle rc);
+	bool PaintContainsMargin();
+	void CheckForChangeOutsidePaint(Range r);
+	void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
+
+	void SetDocPointer(Document *document);
+
+	void Expand(int &line, bool doExpand);
+	void ToggleContraction(int line);
+	void EnsureLineVisible(int lineDoc, bool enforcePolicy);
+	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);
+
+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;
+	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

Added: trunk/plugins/scintilla/scintilla/ExternalLexer.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ExternalLexer.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,263 @@
+// 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 "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++) {
+		SString 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()
+{
+	if(theInstance) {
+		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)
+{
+	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;

Added: trunk/plugins/scintilla/scintilla/Indicator.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Indicator.cxx	Wed Apr  8 20:49:12 2009
@@ -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, 30, fore.allocated, 50, 0);
+	} else {	// Either INDIC_PLAIN or unknown
+		surface->MoveTo(rc.left, ymid);
+		surface->LineTo(rc.right, ymid);
+	}
+}
+

Added: trunk/plugins/scintilla/scintilla/KeyMap.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/KeyMap.cxx	Wed Apr  8 20:49:12 2009
@@ -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},
+};
+

Added: trunk/plugins/scintilla/scintilla/KeyMap.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/KeyMap.h	Wed Apr  8 20:49:12 2009
@@ -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

Added: trunk/plugins/scintilla/scintilla/KeyWords.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/KeyWords.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,237 @@
+// 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
+
+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(lmASP);
+	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(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(lmMatlab);
+	LINK_LEXER(lmMETAPOST);
+	LINK_LEXER(lmMMIXAL);
+	LINK_LEXER(lmMSSQL);
+	LINK_LEXER(lmMySQL);
+	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(lmPHP);
+	LINK_LEXER(lmPHPSCRIPT);
+	LINK_LEXER(lmPLM);
+	LINK_LEXER(lmPo);
+	LINK_LEXER(lmPOV);
+	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(lmSpecman);
+	LINK_LEXER(lmSpice);
+	LINK_LEXER(lmSQL);
+	LINK_LEXER(lmTADS3);
+	LINK_LEXER(lmTCL);
+	LINK_LEXER(lmTeX);
+	LINK_LEXER(lmVB);
+	LINK_LEXER(lmVBScript);
+	LINK_LEXER(lmVerilog);
+	LINK_LEXER(lmVHDL);
+	LINK_LEXER(lmXML);
+	LINK_LEXER(lmYAML);
+
+//--Autogenerated -- end of automatically generated section
+
+	return 1;
+}

Added: trunk/plugins/scintilla/scintilla/LexAPDL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAPDL.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexASY.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexASY.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexAU3.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAU3.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,906 @@
+// 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);

Added: trunk/plugins/scintilla/scintilla/LexAVE.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAVE.cxx	Wed Apr  8 20:49:12 2009
@@ -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 (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);
+

Added: trunk/plugins/scintilla/scintilla/LexAbaqus.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAbaqus.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexAda.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAda.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,524 @@
+// 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 "Platform.h"
+
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
+#include "KeyWords.h"
+#include "SciLexer.h"
+#include "SString.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 SString& identifier);
+static bool IsValidNumber(const SString& 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();
+
+	SString 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;
+
+	SString 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);
+
+	SString 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 SString& 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 SString& number) {
+	int hashPos = number.search("#");
+	bool seenDot = false;
+
+	size_t i = 0;
+	size_t length = number.length();
+
+	if (length == 0)
+		return false; // Just in case
+
+	// Decimal number
+	if (hashPos == -1) {
+		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 == '_';
+}

Added: trunk/plugins/scintilla/scintilla/LexAsn1.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexAsn1.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexBaan.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexBaan.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexBullant.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexBullant.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,228 @@
+// 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];
+	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 (!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);

Added: trunk/plugins/scintilla/scintilla/LexCLW.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCLW.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexCPP.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCPP.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,470 @@
+// 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];
+
+	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);
+	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;
+
+	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;
+		}
+
+		// 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 (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);
+			} 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 (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) {
+	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;
+	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;
+			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);

Added: trunk/plugins/scintilla/scintilla/LexCSS.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCSS.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,363 @@
+// Scintilla source code edit control
+/** @file LexCSS.cxx
+ ** Lexer for Cascading Style Sheets
+ ** Written by Jakub Vrá
+ ** 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 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(SCE_CSS_VALUE);
+		}
+
+		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_DIRECTIVE)
+					sc.SetState(SCE_CSS_DEFAULT);
+				else if (lastState == SCE_CSS_TAG)
+					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
+		)) {
+			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;
+			}
+		}
+
+		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.ch == '\"' || sc.ch == '\'')) {
+			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.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);

Added: trunk/plugins/scintilla/scintilla/LexCmake.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCmake.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,456 @@
+// 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 "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);

Added: trunk/plugins/scintilla/scintilla/LexConf.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexConf.cxx	Wed Apr  8 20:49:12 2009
@@ -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( ispunct(ch) ) {
+					// signals an operator...
+					// no state jump necessary for this
+					// simple case...
+					styler.ColourTo(i,SCE_CONF_OPERATOR);
+				} else if( isalpha(ch) ) {
+					// signals the start of an identifier
+					bufferCount = 0;
+					buffer[bufferCount++] = static_cast<char>(tolower(ch));
+					state = SCE_CONF_IDENTIFIER;
+				} else if( 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( 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( 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( 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);

Added: trunk/plugins/scintilla/scintilla/LexCrontab.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCrontab.cxx	Wed Apr  8 20:49:12 2009
@@ -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( isalpha(ch) || ch == '<' ) {
+					// signals the start of an identifier
+					bufferCount = 0;
+					buffer[bufferCount++] = ch;
+					state = SCE_NNCRONTAB_IDENTIFIER;
+				} else if( 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( 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( 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);

Added: trunk/plugins/scintilla/scintilla/LexCsound.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexCsound.cxx	Wed Apr  8 20:49:12 2009
@@ -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 (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);

Added: trunk/plugins/scintilla/scintilla/LexD.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexD.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,358 @@
+/** @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.
+/*/
+
+// We use custom qualifiers since it is not clear what D allows.
+
+static bool IsWordStart(int ch) {
+	return isascii(ch) && (isalpha(ch) || ch == '_');
+}
+
+static bool IsWord(int ch) {
+	return isascii(ch) && (isalnum(ch) || 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 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];
+    WordList &keywords4 = *keywordlists[3];
+
+    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;
+
+    for (; sc.More(); sc.Forward()) {
+
+        if (sc.atLineStart) {
+            if (sc.state == SCE_D_STRING) {
+                // Prevent SCE_D_STRINGEOL from leaking back to previous line which
+                // ends with a line continuation by locking in the state upto this position.
+                sc.SetState(SCE_D_STRING);
+            }
+            curLine = styler.GetLine(sc.currentPos);
+            styler.SetLineState(curLine, curNcLevel);
+        }
+
+        // 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_D_OPERATOR:
+                sc.SetState(SCE_D_DEFAULT);
+                break;
+            case SCE_D_NUMBER:
+                // We accept almost anything because of hex. and number suffixes
+                if (!IsWord(sc.ch) && sc.ch != '.') {
+                    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);
+                    }
+                    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.atLineEnd) {
+                    sc.ChangeState(SCE_D_STRINGEOL);
+                } else if (sc.ch == '\\') {
+                    if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                        sc.Forward();
+                    }
+                } else if (sc.ch == '\"') {
+                    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.chNext == '\\') {
+                        sc.Forward();
+                    }
+                } else if (sc.ch == '\'') {
+                    sc.ForwardSetState(SCE_D_DEFAULT);
+                }
+                break;
+            case SCE_D_STRINGEOL:
+                if (sc.atLineStart) {
+                    sc.SetState(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);
+            } else if (IsWordStart(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 (isoperator(static_cast<char>(sc.ch))) {
+                sc.SetState(SCE_D_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;
+    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",
+            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);

Added: trunk/plugins/scintilla/scintilla/LexEScript.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexEScript.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexEiffel.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexEiffel.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexErlang.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexErlang.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,526 @@
+// Scintilla source code edit control
+/** @file LexErlang.cxx
+ ** Lexer for Erlang.
+ ** Written by Peter-Henry Mander, based on Matlab lexer by Joséonseca
+ **/
+// 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
+
+/*
+   TODO:
+   o  _Param should be a new lexical type
+*/
+
+static int is_radix(int radix, int ch) {
+   int digit;
+   if ( 16 < radix || 2 > radix ) {
+      return 0;
+   }
+   if ( isdigit(ch) ) {
+      digit = ch - '0';
+   } else if ( isxdigit(ch) ) {
+      digit = toupper(ch) - 'A' + 10;
+   } else {
+      return 0;
+   }
+   if ( digit < radix ) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+
+typedef enum {
+   STATE_NULL,
+   ATOM_UNQUOTED,
+   ATOM_QUOTED,
+   ATOM_FUN_NAME,
+   NODE_NAME_UNQUOTED,
+   NODE_NAME_QUOTED,
+   MACRO_START,
+   MACRO_UNQUOTED,
+   MACRO_QUOTED,
+   RECORD_START,
+   RECORD_UNQUOTED,
+   RECORD_QUOTED,
+   NUMERAL_START,
+   NUMERAL_SIGNED,
+   NUMERAL_RADIX_LITERAL,
+   NUMERAL_SPECULATIVE_MANTISSA,
+   NUMERAL_FLOAT_MANTISSA,
+   NUMERAL_FLOAT_EXPONENT,
+   NUMERAL_FLOAT_SIGNED_EXPONENT,
+   PARSE_ERROR
+} atom_parse_state_t;
+
+static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle,
+                               WordList *keywordlists[], Accessor &styler) {
+
+	WordList &keywords = *keywordlists[0];
+
+	styler.StartAt(startPos);
+
+	StyleContext sc(startPos, length, initStyle, styler);
+   atom_parse_state_t parse_state = STATE_NULL;
+   int radix_digits = 0;
+   int exponent_digits = 0;
+	for (; sc.More(); sc.Forward()) {
+      if ( STATE_NULL != parse_state ) {
+         switch (parse_state) {
+         case STATE_NULL:
+				sc.SetState(SCE_ERLANG_DEFAULT);
+            break;
+         case ATOM_UNQUOTED:
+            if ( '@' == sc.ch ){
+               parse_state = NODE_NAME_UNQUOTED;
+            } else if ( !isalnum(sc.ch) && sc.ch != '_' ) {
+               char s[100];
+               sc.GetCurrent(s, sizeof(s));
+               if (keywords.InList(s)) {
+                  sc.ChangeState(SCE_ERLANG_KEYWORD);
+                  sc.SetState(SCE_ERLANG_DEFAULT);
+                  parse_state = STATE_NULL;
+               } else {
+                  if ( '/' == sc.ch ) {
+                     parse_state = ATOM_FUN_NAME;
+                  } else {
+                     sc.ChangeState(SCE_ERLANG_ATOM);
+                     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;
+         case ATOM_FUN_NAME:
+            if ( !isdigit(sc.ch) ) {
+               sc.ChangeState(SCE_ERLANG_FUNCTION_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);
+               sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         case NODE_NAME_UNQUOTED:
+            if ( '@' == sc.ch ) {
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            } else if ( !isalnum(sc.ch) && sc.ch != '_' ) {
+               sc.ChangeState(SCE_ERLANG_NODE_NAME);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         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_QUOTED:
+            if ( '\'' == sc.ch && '\\' != sc.chPrev ) {
+               sc.ChangeState(SCE_ERLANG_RECORD);
+               sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         case RECORD_UNQUOTED:
+            if ( !isalpha(sc.ch) && '_' != sc.ch ) {
+               sc.ChangeState(SCE_ERLANG_RECORD);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         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 ( !isalpha(sc.ch) && '_' != 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);
+               sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         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 || 16 < radix_digits) {
+                  sc.SetState(SCE_ERLANG_DEFAULT);
+                  parse_state = STATE_NULL;
+               } else {
+                  parse_state = NUMERAL_RADIX_LITERAL;
+               }
+            } else if ( '.' == sc.ch && isdigit(sc.chNext)) {
+               radix_digits = 0;
+               parse_state = NUMERAL_FLOAT_MANTISSA;
+            } else if ( 'e' == sc.ch || 'E' == sc.ch ) {
+               exponent_digits = 0;
+               parse_state = NUMERAL_FLOAT_EXPONENT;
+            } else {
+               radix_digits = 0;
+               sc.ChangeState(SCE_ERLANG_NUMBER);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         case NUMERAL_RADIX_LITERAL:
+            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;
+         case NUMERAL_FLOAT_MANTISSA:
+            if ( 'e' == sc.ch || 'E' == sc.ch ) {
+               exponent_digits = 0;
+               parse_state = NUMERAL_FLOAT_EXPONENT;
+            } else if ( !isdigit(sc.ch) ) {
+               sc.ChangeState(SCE_ERLANG_NUMBER);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            }
+            break;
+         case NUMERAL_FLOAT_EXPONENT:
+            if ( '-' == sc.ch || '+' == sc.ch ) {
+               parse_state = NUMERAL_FLOAT_SIGNED_EXPONENT;
+            } 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;
+         case NUMERAL_FLOAT_SIGNED_EXPONENT:
+            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;
+         case NUMERAL_SIGNED:
+            if ( !isdigit(sc.ch) ) {
+               sc.ChangeState(SCE_ERLANG_NUMBER);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            } else if ( '.' == sc.ch ) {
+               parse_state = NUMERAL_FLOAT_MANTISSA;
+            }
+            break;
+         case NUMERAL_SPECULATIVE_MANTISSA:
+            if ( !isdigit(sc.ch) ) {
+               sc.ChangeState(SCE_ERLANG_OPERATOR);
+               sc.SetState(SCE_ERLANG_DEFAULT);
+               parse_state = STATE_NULL;
+            } else {
+               parse_state = NUMERAL_FLOAT_MANTISSA;
+            }
+            break;
+         case PARSE_ERROR:
+				sc.SetState(SCE_ERLANG_DEFAULT);
+            parse_state = STATE_NULL;
+            break;
+         }
+      } else if (sc.state == 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);
+			}
+		} else if (sc.state == SCE_ERLANG_VARIABLE) {
+			if (!isalnum(sc.ch) && sc.ch != '_') {
+            sc.SetState(SCE_ERLANG_DEFAULT);
+			}
+		} else if (sc.state == SCE_ERLANG_STRING) {
+			if (sc.ch == '\"' && sc.chPrev != '\\') {
+				sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+			}
+		} else if (sc.state == SCE_ERLANG_COMMENT ) {
+			if (sc.atLineEnd) {
+				sc.SetState(SCE_ERLANG_DEFAULT);
+			}
+      } else if (sc.state == SCE_ERLANG_CHARACTER ) {
+         if ( sc.chPrev == '\\' ) {
+            sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+         } else if ( sc.ch != '\\' ) {
+            sc.ForwardSetState(SCE_ERLANG_DEFAULT);
+         }
+      }
+
+		if (sc.state == SCE_ERLANG_DEFAULT) {
+			if (sc.ch == '%') {
+				sc.SetState(SCE_ERLANG_COMMENT);
+			} else if (sc.ch == '\"') {
+            sc.SetState(SCE_ERLANG_STRING);
+         } else if (sc.ch == '#') {
+            parse_state = RECORD_START;
+				sc.SetState(SCE_ERLANG_UNKNOWN);
+         } else if (sc.ch == '?') {
+            parse_state = MACRO_START;
+				sc.SetState(SCE_ERLANG_UNKNOWN);
+         } else if (sc.ch == '$') {
+				sc.SetState(SCE_ERLANG_CHARACTER);
+         } else if (sc.ch == '\'') {
+            parse_state = ATOM_QUOTED;
+				sc.SetState(SCE_ERLANG_UNKNOWN);
+			} else if ( isdigit(sc.ch) ) {
+            parse_state = NUMERAL_START;
+            radix_digits = sc.ch - '0';
+				sc.SetState(SCE_ERLANG_UNKNOWN);
+         } else if ( '.' == sc.ch ) {
+            parse_state = NUMERAL_SPECULATIVE_MANTISSA;
+				sc.SetState(SCE_ERLANG_UNKNOWN);
+			} else if (isalpha(sc.ch) && isupper(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 ClassifyFoldPointErlang(
+   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 visibleChars = 0;
+	int lineCurrent = styler.GetLine(startPos);
+	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+	int levelCurrent = levelPrev;
+	char chNext = styler.SafeGetCharAt(startPos);
+	int styleNext = styler.StyleAt(startPos);
+	int style = initStyle;
+	int keyword_start = 0;
+
+   bool fold_keywords = true;
+   bool fold_comments = true;
+   bool fold_braces = true;
+   bool fold_function_clauses = false;
+   bool fold_clauses = false;
+
+   //int clause_level = 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_ERLANG_KEYWORD) && (style == SCE_ERLANG_KEYWORD) ) {
+         keyword_start = i;
+      }
+      if ( fold_keywords ) {
+         if ( (stylePrev == SCE_ERLANG_KEYWORD)
+            && (style != SCE_ERLANG_KEYWORD)
+            && (style != SCE_ERLANG_ATOM)
+         ) {
+            levelCurrent += ClassifyFoldPointErlang(styler,styleNext,keyword_start);
+         }
+      }
+
+      if ( fold_comments ) {
+         if (style == SCE_ERLANG_COMMENT) {
+            if ((ch == '%') && (chNext == '{')) {
+               levelCurrent++;
+            } else if ((ch == '%') && (chNext == '}')) {
+               levelCurrent--;
+            }
+         }
+      }
+
+      if ( fold_function_clauses ) {
+         if ( (SC_FOLDLEVELBASE == levelCurrent) /*&& (style == SCE_ERLANG_OPERATOR)*/ ) {
+            if ( (ch == '-') && (chNext == '>')) {
+               //~ fprintf(stderr,"levelCurrent=%d\n", levelCurrent);
+               //++clause_level;
+               //~ if ( 0 < clause_level )
+                  ++levelCurrent;
+            }
+         }
+         //~ if (  (stylePrev != SCE_ERLANG_RECORD)
+            //~ && (style != SCE_ERLANG_NUMBER)
+            //~ && (style != SCE_ERLANG_STRING)
+            //~ && (style != SCE_ERLANG_COMMENT)
+         //~ ) {
+            if ( (SC_FOLDLEVELBASE+1 == levelCurrent) && (ch == '.') ) {
+               //--clause_level;
+               //~ if ( 0 == clause_level )
+                  --levelCurrent;
+            }
+         //~ }
+      }
+
+      if ( fold_clauses ) {
+         if ( (0 < levelCurrent) && (style == SCE_ERLANG_OPERATOR) ) {
+            if ((ch == '-') && (chNext == '>')) {
+               levelCurrent++;
+            }
+            if ( (ch == ';') ) {
+               levelCurrent--;
+            }
+         }
+         if ( (stylePrev != SCE_ERLANG_RECORD)
+            && (style != SCE_ERLANG_NUMBER)
+            && (style != SCE_ERLANG_STRING)
+            && (style != SCE_ERLANG_COMMENT)
+         ) {
+            if ( (ch == '.') ) {
+               levelCurrent--;
+            }
+         }
+         if (  (stylePrev == SCE_ERLANG_KEYWORD)
+            && (style != SCE_ERLANG_KEYWORD)
+            && (style != SCE_ERLANG_ATOM)
+            && (
+               styler.Match(keyword_start,"end") // 'end' counted twice if fold_keywords too
+               || styler.Match(keyword_start,"after") )
+         ) {
+            levelCurrent--;
+         }
+      }
+
+      if ( fold_braces ) {
+         if (style == SCE_ERLANG_OPERATOR) {
+            if ( (ch == '{') || (ch == '(') || (ch == '[') ) {
+               levelCurrent++;
+            } else if ( (ch == '}') || (ch == ')') || (ch == ']') ) {
+               levelCurrent--;
+            }
+         }
+      }
+
+		if (atEOL) {
+			int lev = levelPrev;
+			//~ if (visibleChars == 0 && foldCompact)
+				//~ lev |= SC_FOLDLEVELWHITEFLAG;
+			//~ if ((levelCurrent > levelPrev) && (visibleChars > 0))
+			if ((levelCurrent > levelPrev)) {
+				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 erlangWordListDesc[] = {
+	"Keywords",
+	0
+};
+
+LexerModule lmErlang(
+   SCLEX_ERLANG,
+   ColouriseErlangDoc,
+   "erlang",
+   FoldErlangDoc,
+   erlangWordListDesc);
+

Added: trunk/plugins/scintilla/scintilla/LexFlagship.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexFlagship.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,230 @@
+// Scintilla source code edit control
+/** @file LexFlagShip.cxx
+ ** Lexer for FlagShip 
+ ** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.)
+ **/
+// Copyright 2005 by Randy Butler
+// Copyright 1998-2003 by Neil Hodgson <neilh scintilla org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static bool IsFlagShipComment(Accessor &styler, int pos, int len) {
+	return len>0 && styler[pos]=='\'';
+}
+
+static inline bool IsTypeCharacter(int ch) {
+	return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
+}
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+	return ch >= 0x80 ||
+	       (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+	return ch >= 0x80 ||
+	       (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsADateCharacter(const int ch) {
+	return (ch < 0x80) &&
+		(isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
+}
+
+
+static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+
+	//bool FSScriptSyntax = true;
+	WordList &keywords = *keywordlists[0];
+	WordList &keywords2 = *keywordlists[1];
+	WordList &keywords3 = *keywordlists[2];
+	WordList &keywords4 = *keywordlists[3];
+
+	styler.StartAt(startPos);
+
+	int visibleChars = 0;
+
+	StyleContext sc(startPos, length, initStyle, styler);
+
+	for (; sc.More(); sc.Forward()) {
+
+		if (sc.state == SCE_FS_OPERATOR) {
+			sc.SetState(SCE_FS_DEFAULT);
+		} else if (sc.state == SCE_FS_IDENTIFIER) {
+			if (!IsAWordChar(sc.ch)) {
+				char s[100];
+				sc.GetCurrentLowered(s, sizeof(s));
+				if (keywords.InList(s)) {
+					sc.ChangeState(SCE_FS_KEYWORD);
+				} else if (keywords2.InList(s)) {
+					sc.ChangeState(SCE_FS_KEYWORD2);
+				} else if (keywords3.InList(s)) {
+					sc.ChangeState(SCE_FS_KEYWORD3);
+				} else if (keywords4.InList(s)) {
+					sc.ChangeState(SCE_FS_KEYWORD4);
+				}// Else, it is really an identifier...
+				sc.SetState(SCE_FS_DEFAULT);
+			}
+		} else if (sc.state == SCE_FS_NUMBER) {
+			if (!IsAWordChar(sc.ch)) {
+				sc.SetState(SCE_FS_DEFAULT);
+			}
+		} else if (sc.state == SCE_FS_STRING) {
+			// VB doubles quotes to preserve them, so just end this string
+			// state now as a following quote will start again
+			if (sc.ch == '\"') {
+				if (tolower(sc.chNext) == 'c') {
+					sc.Forward();
+				}
+				sc.ForwardSetState(SCE_FS_DEFAULT);
+			} else if (sc.atLineEnd) {
+				sc.ChangeState(SCE_FS_STRINGEOL);
+				sc.ForwardSetState(SCE_FS_DEFAULT);
+			}
+		} else if (sc.state == SCE_FS_COMMENT) {
+			if (sc.Match('*', '/')) {   // new code
+				sc.Forward();
+				sc.ForwardSetState(SCE_FS_DEFAULT);
+			//if (sc.atLineEnd) {       // old code
+			//	sc.SetState(SCE_FS_DEFAULT);
+			}
+		} else if (sc.state == SCE_FS_COMMENTLINE) {  //new code
+			if (sc.ch == '\r' || sc.ch == '\n') {
+				sc.SetState(SCE_FS_DEFAULT);
+				visibleChars = 0;
+			}
+		} else if (sc.state == SCE_FS_PREPROCESSOR) {
+			if (sc.atLineEnd) {
+				sc.SetState(SCE_FS_DEFAULT);
+			}
+		} else if (sc.state == SCE_FS_DATE) {
+			if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
+				sc.ForwardSetState(SCE_FS_DEFAULT);
+			}
+		}
+
+		// Determine if a new state should be entered.
+		if (sc.state == SCE_FS_DEFAULT) {
+			if (sc.Match('/', '*')) {  // New code
+				sc.SetState(SCE_FS_COMMENT);
+				sc.Forward();	// Eat the * so it isn't used for the end of the comment
+			//if (sc.ch == '\'') {  // Old code
+			//	sc.SetState(SCE_FS_COMMENT); // old code
+			} else if (sc.Match('/', '/')) { // New code
+				sc.SetState(SCE_FS_COMMENTLINE);
+			} else if (sc.ch == '\"') {
+				sc.SetState(SCE_FS_STRING);
+			} else if (sc.ch == '#' && visibleChars == 0) {
+				// Preprocessor commands are alone on their line
+				sc.SetState(SCE_FS_PREPROCESSOR);
+			} else if (sc.ch == '#') {
+				int n = 1;
+				int chSeek = ' ';
+				while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
+					chSeek = sc.GetRelative(n);
+					n++;
+				}
+				if (IsADigit(chSeek)) {
+					sc.SetState(SCE_FS_DATE);
+				} else {
+					sc.SetState(SCE_FS_OPERATOR);
+				}
+			} else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
+				sc.SetState(SCE_FS_NUMBER);
+			} else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
+				sc.SetState(SCE_FS_NUMBER);
+			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+				sc.SetState(SCE_FS_NUMBER);
+			} else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
+				sc.SetState(SCE_FS_IDENTIFIER);
+			} else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
+				sc.SetState(SCE_FS_OPERATOR);
+			}
+		}
+
+		if (sc.atLineEnd) {
+			visibleChars = 0;
+		}
+		if (!IsASpace(sc.ch)) {
+			visibleChars++;
+		}
+	}
+	sc.Complete();
+}
+
+static void FoldFlagShipDoc(unsigned int startPos, int length, int,
+						   WordList *[], Accessor &styler) {
+
+	int endPos = startPos + length;
+
+	// Backtrack to previous line in case need to fix its fold status
+	int lineCurrent = styler.GetLine(startPos);
+	if (startPos > 0) {
+		if (lineCurrent > 0) {
+			lineCurrent--;
+			startPos = styler.LineStart(lineCurrent);
+		}
+	}
+	int spaceFlags = 0;
+	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment);
+	char chNext = styler[startPos];
+	for (int i = startPos; i < endPos; i++) {
+		char ch = chNext;
+		chNext = styler.SafeGetCharAt(i + 1);
+
+		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+			int lev = indentCurrent;
+			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment);
+			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+				// Only non whitespace lines can be headers
+				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+					lev |= SC_FOLDLEVELHEADERFLAG;
+				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
+					// Line after is blank so check the next - maybe should continue further?
+					int spaceFlags2 = 0;
+					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment);
+					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+						lev |= SC_FOLDLEVELHEADERFLAG;
+					}
+				}
+			}
+			indentCurrent = indentNext;
+			styler.SetLevel(lineCurrent, lev);
+			lineCurrent++;
+		}
+	}
+}
+
+
+static const char * const FSWordListDesc[] = {
+	"Keywords",
+	"functions",
+	"user2",
+	"user3",
+	0
+};
+
+LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);
+
+
+

Added: trunk/plugins/scintilla/scintilla/LexForth.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexForth.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,352 @@
+// 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
+
+bool is_whitespace(int ch){
+    return ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ';
+}
+
+bool is_blank(int ch){
+    return ch == '\t' || ch == ' ';
+}
+//#define FORTH_DEBUG
+#ifdef FORTH_DEBUG
+static FILE *f_debug;
+#define log(x)  fputs(f_debug,x);
+#else
+#define log(x)
+#endif
+
+#define STATE_LOCALE
+#define BL ' '
+
+static Accessor *st;
+static int cur_pos,pos1,pos2,pos0,lengthDoc;
+char *buffer;
+
+char getChar(bool is_bl){
+    char ch=st->SafeGetCharAt(cur_pos);
+    if(is_bl) if(is_whitespace(ch)) ch=BL;
+    return ch;
+}
+
+char getCharBL(){
+    char ch=st->SafeGetCharAt(cur_pos);
+    return ch;
+}
+bool is_eol(char ch){
+    return ch=='\n' || ch=='\r';
+}
+
+int parse(char ch, bool skip_eol){
+// pos1 - start pos of word
+// pos2 - pos after of word
+// pos0 - start pos
+    char c=0;
+    int len;
+    bool is_bl=ch==BL;
+    pos0=pos1=pos2=cur_pos;
+    for(;cur_pos<lengthDoc && (c=getChar(is_bl))==ch; cur_pos++){
+        if(is_eol(c) && !skip_eol){
+            pos2=pos1;
+            return 0;
+        }
+    }
+    pos1=cur_pos;
+    pos2=pos1;
+    if(cur_pos==lengthDoc) return 0;
+    for(len=0;cur_pos<lengthDoc && (c=getChar(is_bl))!=ch; cur_pos++){
+        if(is_eol(c) && !skip_eol) break;
+        pos2++;
+        buffer[len++]=c;
+    }
+    if(c==ch) pos2--;
+    buffer[len]='\0';
+#ifdef FORTH_DEBUG
+    fprintf(f_debug,"parse: %c %s\n",ch,buffer);
+#endif
+    return len;
+}
+
+bool _is_number(char *s,int base){
+    for(;*s;s++){
+        int digit=((int)*s)-(int)'0';
+#ifdef FORTH_DEBUG
+    fprintf(f_debug,"digit: %c %d\n",*s,digit);
+#endif
+        if(digit>9 && base>10) digit-=7;
+        if(digit<0) return false;
+        if(digit>=base) return false;
+    }
+    return true;
+}
+
+bool is_number(char *s){
+    if(strncmp(s,"0x",2)==0) return _is_number(s+2,16);
+    return _is_number(s,10);
+}
+
+static void ColouriseForthDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
+{
+    st=&styler;
+    cur_pos=startPos;
+    lengthDoc = startPos + length;
+    buffer = new char[length];
+
+#ifdef FORTH_DEBUG
+    f_debug=fopen("c:\\sci.log","at");
+#endif
+
+    WordList &control = *keywordLists[0];
+    WordList &keyword = *keywordLists[1];
+    WordList &defword = *keywordLists[2];
+    WordList &preword1 = *keywordLists[3];
+    WordList &preword2 = *keywordLists[4];
+    WordList &strings = *keywordLists[5];
+
+    // go through all provided text segment
+    // using the hand-written state machine shown below
+    styler.StartAt(startPos);
+    styler.StartSegment(startPos);
+    while(parse(BL,true)!=0){
+        if(pos0!=pos1){
+            styler.ColourTo(pos0,SCE_FORTH_DEFAULT);
+            styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT);
+        }
+        if(strcmp("\\",buffer)==0){
+            styler.ColourTo(pos1,SCE_FORTH_COMMENT);
+            parse(1,false);
+            styler.ColourTo(pos2,SCE_FORTH_COMMENT);
+        }else if(strcmp("(",buffer)==0){
+            styler.ColourTo(pos1,SCE_FORTH_COMMENT);
+            parse(')',true);
+            if(cur_pos<lengthDoc) cur_pos++;
+            styler.ColourTo(cur_pos,SCE_FORTH_COMMENT);
+        }else if(strcmp("[",buffer)==0){
+            styler.ColourTo(pos1,SCE_FORTH_STRING);
+            parse(']',true);
+            if(cur_pos<lengthDoc) cur_pos++;
+            styler.ColourTo(cur_pos,SCE_FORTH_STRING);
+        }else if(strcmp("{",buffer)==0){
+            styler.ColourTo(pos1,SCE_FORTH_LOCALE);
+            parse('}',false);
+            if(cur_pos<lengthDoc) cur_pos++;
+            styler.ColourTo(cur_pos,SCE_FORTH_LOCALE);
+        }else if(strings.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_STRING);
+            parse('"',false);
+            if(cur_pos<lengthDoc) cur_pos++;
+            styler.ColourTo(cur_pos,SCE_FORTH_STRING);
+        }else if(control.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_CONTROL);
+            styler.ColourTo(pos2,SCE_FORTH_CONTROL);
+        }else if(keyword.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_KEYWORD);
+            styler.ColourTo(pos2,SCE_FORTH_KEYWORD);
+        }else if(defword.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_KEYWORD);
+            styler.ColourTo(pos2,SCE_FORTH_KEYWORD);
+            parse(BL,false);
+            styler.ColourTo(pos1-1,SCE_FORTH_DEFAULT);
+            styler.ColourTo(pos1,SCE_FORTH_DEFWORD);
+            styler.ColourTo(pos2,SCE_FORTH_DEFWORD);
+        }else if(preword1.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_PREWORD1);
+            parse(BL,false);
+            styler.ColourTo(pos2,SCE_FORTH_PREWORD1);
+        }else if(preword2.InList(buffer)) {
+            styler.ColourTo(pos1,SCE_FORTH_PREWORD2);
+            parse(BL,false);
+            styler.ColourTo(pos2,SCE_FORTH_PREWORD2);
+            parse(BL,false);
+            styler.ColourTo(pos1,SCE_FORTH_STRING);
+            styler.ColourTo(pos2,SCE_FORTH_STRING);
+        }else if(is_number(buffer)){
+            styler.ColourTo(pos1,SCE_FORTH_NUMBER);
+            styler.ColourTo(pos2,SCE_FORTH_NUMBER);
+        }
+    }
+#ifdef FORTH_DEBUG
+    fclose(f_debug);
+#endif
+    delete []buffer;
+    return;
+/*
+                        if(control.InList(buffer)) {
+                            styler.ColourTo(i,SCE_FORTH_CONTROL);
+                        } else if(keyword.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_KEYWORD );
+                        } else if(defword.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_DEFWORD );
+//                            prev_state=SCE_FORTH_DEFWORD
+                        } else if(preword1.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_PREWORD1 );
+//                            state=SCE_FORTH_PREWORD1;
+                        } else if(preword2.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_PREWORD2 );
+                         } else {
+                            styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
+                        }
+*/
+/*
+    chPrev=' ';
+    for (int i = startPos; i < lengthDoc; i++) {
+        char ch = chNext;
+        chNext = styler.SafeGetCharAt(i + 1);
+        if(i!=startPos) chPrev=styler.SafeGetCharAt(i - 1);
+
+        if (styler.IsLeadByte(ch)) {
+            chNext = styler.SafeGetCharAt(i + 2);
+            i++;
+            continue;
+        }
+#ifdef FORTH_DEBUG
+        fprintf(f_debug,"%c %d ",ch,state);
+#endif
+        switch(state) {
+            case SCE_FORTH_DEFAULT:
+                if(is_whitespace(ch)) {
+                    // whitespace is simply ignored here...
+                    styler.ColourTo(i,SCE_FORTH_DEFAULT);
+                    break;
+                } else if( ch == '\\' && is_blank(chNext)) {
+                    // signals the start of an one line comment...
+                    state = SCE_FORTH_COMMENT;
+                    styler.ColourTo(i,SCE_FORTH_COMMENT);
+                } else if( is_whitespace(chPrev) &&  ch == '(' &&  is_whitespace(chNext)) {
+                    // signals the start of a plain comment...
+                    state = SCE_FORTH_COMMENT_ML;
+                    styler.ColourTo(i,SCE_FORTH_COMMENT_ML);
+                } else if( isdigit(ch) ) {
+                    // signals the start of a number
+                    bufferCount = 0;
+                    buffer[bufferCount++] = ch;
+                    state = SCE_FORTH_NUMBER;
+                } else if( !is_whitespace(ch)) {
+                    // signals the start of an identifier
+                    bufferCount = 0;
+                    buffer[bufferCount++] = ch;
+                    state = SCE_FORTH_IDENTIFIER;
+                } else {
+                    // style it the default style..
+                    styler.ColourTo(i,SCE_FORTH_DEFAULT);
+                }
+                break;
+
+            case SCE_FORTH_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_FORTH_DEFAULT;
+                } else {
+                    styler.ColourTo(i,SCE_FORTH_COMMENT);
+                }
+                break;
+
+            case SCE_FORTH_COMMENT_ML:
+                if( ch == ')') {
+                    state = SCE_FORTH_DEFAULT;
+                } else {
+                    styler.ColourTo(i+1,SCE_FORTH_COMMENT_ML);
+                }
+                break;
+
+            case SCE_FORTH_IDENTIFIER:
+                // stay  in CONF_IDENTIFIER state until we find a non-alphanumeric
+                if( !is_whitespace(ch) ) {
+                    buffer[bufferCount++] = ch;
+                } else {
+                    state = SCE_FORTH_DEFAULT;
+                    buffer[bufferCount] = '\0';
+#ifdef FORTH_DEBUG
+        fprintf(f_debug,"\nid %s\n",buffer);
+#endif
+
+                    // check if the buffer contains a keyword,
+                    // and highlight it if it is a keyword...
+//                    switch(prev_state)
+//                    case SCE_FORTH_DEFAULT:
+                        if(control.InList(buffer)) {
+                            styler.ColourTo(i,SCE_FORTH_CONTROL);
+                        } else if(keyword.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_KEYWORD );
+                        } else if(defword.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_DEFWORD );
+//                            prev_state=SCE_FORTH_DEFWORD
+                        } else if(preword1.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_PREWORD1 );
+//                            state=SCE_FORTH_PREWORD1;
+                        } else if(preword2.InList(buffer)) {
+                            styler.ColourTo(i-1,SCE_FORTH_PREWORD2 );
+                         } else {
+                            styler.ColourTo(i-1,SCE_FORTH_DEFAULT);
+                        }
+//                        break;
+//                    case
+
+                    // push back the faulty character
+                    chNext = styler[i--];
+                }
+                break;
+
+            case SCE_FORTH_NUMBER:
+                // stay  in CONF_NUMBER state until we find a non-numeric
+                if( isdigit(ch) ) {
+                    buffer[bufferCount++] = ch;
+                } else {
+                    state = SCE_FORTH_DEFAULT;
+                    buffer[bufferCount] = '\0';
+                    // Colourize here... (normal number)
+                    styler.ColourTo(i-1,SCE_FORTH_NUMBER);
+                    // push back a character
+                    chNext = styler[i--];
+                }
+                break;
+        }
+    }
+#ifdef FORTH_DEBUG
+    fclose(f_debug);
+#endif
+    delete []buffer;
+*/
+}
+
+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);

Added: trunk/plugins/scintilla/scintilla/LexFortran.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexFortran.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexGAP.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexGAP.cxx	Wed Apr  8 20:49:12 2009
@@ -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 (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);

Added: trunk/plugins/scintilla/scintilla/LexGui4Cli.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexGui4Cli.cxx	Wed Apr  8 20:49:12 2009
@@ -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
+

Added: trunk/plugins/scintilla/scintilla/LexHTML.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexHTML.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,2184 @@
+// 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 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
+	// Name of a closing tag starts at s + 1
+	char chAttr = SCE_H_TAGUNKNOWN;
+	if (s[0] == '!') {
+		chAttr = SCE_H_SGML_DEFAULT;
+	} else if (!keywords || keywords.InList(s[0] == '/' ? s + 1 : s)) {
+		chAttr = SCE_H_TAG;
+	}
+	styler.ColourTo(end, chAttr);
+	if (chAttr == SCE_H_TAG) {
+		if (allowScripts && 0 == strcmp(s, "script")) {
+			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 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);
+
+	// 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;
+		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;
+	}
+
+	const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;
+	const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);
+	const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);
+	const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+	const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0;
+	const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;
+	const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
+	const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 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 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++;
+
+		// 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++;
+			styler.SetLineState(lineCurrent,
+			                    ((inScriptType & 0x03) << 0) |
+			                    ((tagOpened & 0x01) << 2) |
+			                    ((tagClosing & 0x01) << 3) |
+			                    ((aspScript & 0x0F) << 4) |
+			                    ((clientScript & 0x0F) << 8) |
+			                    ((beforePreProc & 0xFF) << 12));
+		}
+
+		// 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 of ASP pre-processor = Non-HTML
+		else if (!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)
+				levelCurrent++;
+			continue;
+		}
+
+		// handle the end of a pre-processor = Non-HTML
+		else if ((
+		             ((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
+				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 bool isASPScript(int state) {
+	return
+		(state >= SCE_HJA_START && state <= SCE_HJA_REGEX) ||
+		(state >= SCE_HBA_START && state <= SCE_HBA_STRINGEOL) ||
+		(state >= SCE_HPA_DEFAULT && state <= SCE_HPA_IDENTIFIER);
+}
+
+static void ColouriseHBAPiece(StyleContext &sc, WordList *keywordlists[]) {
+	WordList &keywordsVBS = *keywordlists[2];
+	if (sc.state == SCE_HBA_WORD) {
+		if (!IsAWordChar(sc.ch)) {
+			char s[100];
+			sc.GetCurrentLowered(s, sizeof(s));
+			if (keywordsVBS.InList(s)) {
+				if (strcmp(s, "rem") == 0) {
+					sc.ChangeState(SCE_HBA_COMMENTLINE);
+					if (sc.atLineEnd) {
+						sc.SetState(SCE_HBA_DEFAULT);
+					}
+				} else {
+					sc.SetState(SCE_HBA_DEFAULT);
+				}
+			} else {
+				sc.ChangeState(SCE_HBA_IDENTIFIER);
+				sc.SetState(SCE_HBA_DEFAULT);
+			}
+		}
+	} else if (sc.state == SCE_HBA_NUMBER) {
+		if (!IsAWordChar(sc.ch)) {
+			sc.SetState(SCE_HBA_DEFAULT);
+		}
+	} else if (sc.state == SCE_HBA_STRING) {
+		if (sc.ch == '\"') {
+			sc.ForwardSetState(SCE_HBA_DEFAULT);
+		} else if (sc.ch == '\r' || sc.ch == '\n') {
+			sc.ChangeState(SCE_HBA_STRINGEOL);
+			sc.ForwardSetState(SCE_HBA_DEFAULT);
+		}
+	} else if (sc.state == SCE_HBA_COMMENTLINE) {
+		if (sc.ch == '\r' || sc.ch == '\n') {
+			sc.SetState(SCE_HBA_DEFAULT);
+		}
+	}
+
+	if (sc.state == SCE_HBA_DEFAULT) {
+		if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+			sc.SetState(SCE_HBA_NUMBER);
+		} else if (IsAWordStart(sc.ch)) {
+			sc.SetState(SCE_HBA_WORD);
+		} else if (sc.ch == '\'') {
+			sc.SetState(SCE_HBA_COMMENTLINE);
+		} else if (sc.ch == '\"') {
+			sc.SetState(SCE_HBA_STRING);
+		}
+	}
+}
+
+static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) {
+	WordList &keywordsTags = *keywordlists[0];
+	if (sc.state == SCE_H_COMMENT) {
+		if (sc.Match("-->")) {
+			sc.Forward();
+			sc.Forward();
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		}
+	} else if (sc.state == SCE_H_ENTITY) {
+		if (sc.ch == ';') {
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		} else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch)	// Should check that '#' follows '&', but it is unlikely anyway...
+			&& sc.ch != '.' && sc.ch != '-' && sc.ch != '_' && sc.ch != ':') { // valid in XML
+			sc.ChangeState(SCE_H_TAGUNKNOWN);
+			sc.SetState(SCE_H_DEFAULT);
+		}
+	} else if (sc.state == SCE_H_TAGUNKNOWN) {
+		if (!ishtmlwordchar(sc.ch) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') {
+			char s[100];
+			sc.GetCurrentLowered(s, sizeof(s));
+			if (s[1] == '/') {
+				if (keywordsTags.InList(s + 2)) {
+					sc.ChangeState(SCE_H_TAG);
+				}
+			} else {
+				if (keywordsTags.InList(s + 1)) {
+					sc.ChangeState(SCE_H_TAG);
+				}
+			}
+			if (sc.ch == '>') {
+				sc.ForwardSetState(SCE_H_DEFAULT);
+			} else if (sc.Match('/', '>')) {
+				sc.SetState(SCE_H_TAGEND);
+				sc.Forward();
+				sc.ForwardSetState(SCE_H_DEFAULT);
+			} else {
+				sc.SetState(SCE_H_OTHER);
+			}
+		}
+	} else if (sc.state == SCE_H_ATTRIBUTE) {
+		if (!ishtmlwordchar(sc.ch)) {
+			char s[100];
+			sc.GetCurrentLowered(s, sizeof(s));
+			if (!keywordsTags.InList(s)) {
+				sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN);
+			}
+			sc.SetState(SCE_H_OTHER);
+		}
+	} else if (sc.state == SCE_H_OTHER) {
+		if (sc.ch == '>') {
+			sc.SetState(SCE_H_TAG);
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		} else if (sc.Match('/', '>')) {
+			sc.SetState(SCE_H_TAG);
+			sc.Forward();
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		} else if (sc.chPrev == '=') {
+			sc.SetState(SCE_H_VALUE);
+		}
+	} else if (sc.state == SCE_H_DOUBLESTRING) {
+		if (sc.ch == '\"') {
+			sc.ForwardSetState(SCE_H_OTHER);
+		}
+	} else if (sc.state == SCE_H_SINGLESTRING) {
+		if (sc.ch == '\'') {
+			sc.ForwardSetState(SCE_H_OTHER);
+		}
+	} else if (sc.state == SCE_H_NUMBER) {
+		if (!IsADigit(sc.ch)) {
+			sc.SetState(SCE_H_OTHER);
+		}
+	}
+
+	if (sc.state == SCE_H_DEFAULT) {
+		if (sc.ch == '<') {
+			if (sc.Match("<!--"))
+				sc.SetState(SCE_H_COMMENT);
+			else
+				sc.SetState(SCE_H_TAGUNKNOWN);
+		} else if (sc.ch == '&') {
+			sc.SetState(SCE_H_ENTITY);
+		}
+	} else if ((sc.state == SCE_H_OTHER) || (sc.state == SCE_H_VALUE)) {
+		if (sc.ch == '\"' && sc.chPrev == '=') {
+			sc.SetState(SCE_H_DOUBLESTRING);
+		} else if (sc.ch == '\'' && sc.chPrev == '=') {
+			sc.SetState(SCE_H_SINGLESTRING);
+		} else if (IsADigit(sc.ch)) {
+			sc.SetState(SCE_H_NUMBER);
+		} else if (sc.ch == '>') {
+			sc.SetState(SCE_H_TAG);
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		} else if (ishtmlwordchar(sc.ch)) {
+			sc.SetState(SCE_H_ATTRIBUTE);
+		}
+	}
+}
+
+static void ColouriseASPPiece(StyleContext &sc, WordList *keywordlists[]) {
+	// Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
+	if ((sc.state == SCE_H_ASPAT || isASPScript(sc.state)) && sc.Match('%', '>')) {
+		sc.SetState(SCE_H_ASP);
+		sc.Forward();
+		sc.ForwardSetState(SCE_H_DEFAULT);
+	}
+
+	// Handle some ASP script
+	if (sc.state >= SCE_HBA_START && sc.state <= SCE_HBA_STRINGEOL) {
+		ColouriseHBAPiece(sc, keywordlists);
+	} else if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
+		ColouriseHTMLPiece(sc, keywordlists);
+	}
+
+	// Enter new sc.state
+	if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
+		if (sc.Match('<', '%')) {
+			if (sc.state == SCE_H_TAGUNKNOWN)
+				sc.ChangeState(SCE_H_ASP);
+			else
+				sc.SetState(SCE_H_ASP);
+			sc.Forward();
+			sc.Forward();
+			if (sc.ch == '@') {
+				sc.ForwardSetState(SCE_H_ASPAT);
+			} else {
+				if (sc.ch == '=') {
+					sc.Forward();
+				}
+				sc.SetState(SCE_HBA_DEFAULT);
+			}
+		}
+	}
+}
+
+static void ColouriseASPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                                  Accessor &styler) {
+	// Lexer for HTML requires more lexical states (8 bits worth) than most lexers
+	StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(STYLE_MAX));
+	for (; sc.More(); sc.Forward()) {
+		ColouriseASPPiece(sc, keywordlists);
+	}
+	sc.Complete();
+}
+
+static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {
+	// Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
+	if (sc.state >= SCE_HPHP_DEFAULT && sc.state <= SCE_HPHP_OPERATOR) {
+		if (!isPHPStringState(sc.state) &&
+			(sc.state != SCE_HPHP_COMMENT) &&
+			(sc.Match('?', '>'))) {
+			sc.SetState(SCE_H_QUESTION);
+			sc.Forward();
+			sc.ForwardSetState(SCE_H_DEFAULT);
+		}
+	}
+
+	if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
+		ColouriseHTMLPiece(sc, keywordlists);
+	}
+
+	// Handle some PHP script
+	if (sc.state == SCE_HPHP_WORD) {
+		if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
+			sc.SetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_COMMENTLINE) {
+		if (sc.ch == '\r' || sc.ch == '\n') {
+			sc.SetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_COMMENT) {
+		if (sc.Match('*', '/')) {
+			sc.Forward();
+			sc.Forward();
+			sc.SetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_HSTRING) {
+		if (sc.ch == '\"') {
+			sc.ForwardSetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_SIMPLESTRING) {
+		if (sc.ch == '\'') {
+			sc.ForwardSetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_VARIABLE) {
+		if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
+			sc.SetState(SCE_HPHP_DEFAULT);
+		}
+	} else if (sc.state == SCE_HPHP_OPERATOR) {
+		sc.SetState(SCE_HPHP_DEFAULT);
+	}
+
+	// Enter new sc.state
+	if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
+		if (sc.Match("<?php")) {
+			sc.SetState(SCE_H_QUESTION);
+			sc.Forward();
+			sc.Forward();
+			sc.Forward();
+			sc.Forward();
+			sc.Forward();
+			sc.SetState(SCE_HPHP_DEFAULT);
+		}
+	}
+	if (sc.state == SCE_HPHP_DEFAULT) {
+		if (IsPhpWordStart(static_cast<char>(sc.ch))) {
+			sc.SetState(SCE_HPHP_WORD);
+		} else if (sc.ch == '#') {
+			sc.SetState(SCE_HPHP_COMMENTLINE);
+		} else if (sc.Match("<!--")) {
+			sc.SetState(SCE_HPHP_COMMENTLINE);
+		} else if (sc.Match('/', '/')) {
+			sc.SetState(SCE_HPHP_COMMENTLINE);
+		} else if (sc.Match('/', '*')) {
+			sc.SetState(SCE_HPHP_COMMENT);
+		} else if (sc.ch == '\"') {
+			sc.SetState(SCE_HPHP_HSTRING);
+		} else if (sc.ch == '\'') {
+			sc.SetState(SCE_HPHP_SIMPLESTRING);
+		} else if (sc.ch == '$' && IsPhpWordStart(static_cast<char>(sc.chNext))) {
+			sc.SetState(SCE_HPHP_VARIABLE);
+		} else if (IsOperator(static_cast<char>(sc.ch))) {
+			sc.SetState(SCE_HPHP_OPERATOR);
+		}
+	}
+}
+
+static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                                  Accessor &styler) {
+	// Lexer for HTML requires more lexical states (8 bits worth) than most lexers
+	StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(STYLE_MAX));
+	for (; sc.More(); sc.Forward()) {
+		ColourisePHPPiece(sc, keywordlists);
+	}
+	sc.Complete();
+}
+
+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);
+// SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
+LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 8);
+LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 8);
+LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8);

Added: trunk/plugins/scintilla/scintilla/LexHaskell.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexHaskell.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,274 @@
+/******************************************************************
+ *    LexHaskell.cxx
+ *
+ *    A haskell lexer for the scintilla code control.
+ *    Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
+ *    External lexer stuff inspired from the caml external lexer.
+ *
+ *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se
+ *
+ *
+ *    TODO:
+ *    * Implement a folder :)
+ *    * Nice Character-lexing (stuff inside '\''), LexPython has
+ *      this.
+ *
+ *
+ *****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef 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)
+{
+   PropSet ps;
+   ps.SetMultiple(props);
+   WindowAccessor wa(window, ps);
+
+   int nWL = 0;
+   for (; words[nWL]; nWL++) ;
+   WordList** wl = new WordList* [nWL + 1];
+   int i = 0;
+   for (; i<nWL; i++)
+   {
+      wl[i] = new WordList();
+      wl[i]->Set(words[i]);
+   }
+   wl[i] = 0;
+
+   ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
+   wa.Flush();
+   for (i=nWL-1;i>=0;i--)
+      delete wl[i];
+   delete [] wl;
+}
+
+void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
+                        char *words[], WindowID window, char *props)
+{
+
+}
+
+int EXT_LEXER_DECL GetLexerCount()
+{
+   return 1;
+}
+
+void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
+{
+   if (buflength > 0) {
+      buflength--;
+      int n = strlen(LexerName);
+      if (n > buflength)
+         n = buflength;
+      memcpy(name, LexerName, n), name[n] = '\0';
+   }
+}
+#endif
+
+LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");
+

Added: trunk/plugins/scintilla/scintilla/LexInno.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexInno.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,264 @@
+// 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 "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;
+
+	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 (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 (ch == '{' && chNext == '#') {
+					// Start of a preprocessor inline directive
+					state = SCE_INNO_PREPROC_INLINE;
+				} else if ((ch == '{' && (chNext == ' ' || chNext == '\t'))
+					   || (ch == '(' && chNext == '*')) {
+					// Start of a Pascal comment
+					state = SCE_INNO_COMMENT_PASCAL;
+				} 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 (standardKeywords.InList(buffer)) {
+						styler.ColourTo(i-1,SCE_INNO_KEYWORD);
+					} else if (parameterKeywords.InList(buffer)) {
+						styler.ColourTo(i-1,SCE_INNO_PARAMETER);
+					} else if (pascalKeywords.InList(buffer)) {
+						styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
+					} else if (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);
+					} 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_PREPROC_INLINE:
+				if (ch == '}') {
+					state = SCE_INNO_DEFAULT;
+					styler.ColourTo(i,SCE_INNO_PREPROC_INLINE);
+				} else if (isEOL) {
+					state = SCE_INNO_DEFAULT;
+					styler.ColourTo(i,SCE_INNO_DEFAULT);
+				}
+				break;
+
+			case SCE_INNO_COMMENT_PASCAL:
+				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);

Added: trunk/plugins/scintilla/scintilla/LexKix.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexKix.cxx	Wed Apr  8 20:49:12 2009
@@ -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");
+

Added: trunk/plugins/scintilla/scintilla/LexLisp.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexLisp.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,279 @@
+// 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 == ')' )
+		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 (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 (!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 == '(') {
+				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 lispWordListDesc[] = {
+	"Functions and special operators",
+	"Keywords",
+	0
+};
+
+LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);

Added: trunk/plugins/scintilla/scintilla/LexLout.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexLout.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexLua.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexLua.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexMMIXAL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMMIXAL.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,186 @@
+// Scintilla source code edit control
+/** @file LexMMIXAL.cxx
+ ** Lexer for MMIX Assembler Language.
+ ** Written by Christoph Hör <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 (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);
+

Added: trunk/plugins/scintilla/scintilla/LexMPT.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMPT.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,186 @@
+// 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 "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "SString.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static int GetLotLineState(SString &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 (!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.contains("PASSED")) {
+				return SCE_LOT_PASS;
+			}
+			else if (line.contains("FAILED")) {
+				return SCE_LOT_FAIL;
+			}
+			else if (line.contains("ABORTED")) {
+				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);
+	SString line("");
+	line.setsizegrowth(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);

Added: trunk/plugins/scintilla/scintilla/LexMSSQL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMSSQL.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexMagik.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMagik.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+

Added: trunk/plugins/scintilla/scintilla/LexMatlab.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMatlab.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,236 @@
+// Scintilla source code edit control
+/** @file LexMatlab.cxx
+ ** Lexer for Matlab.
+ ** Written by Joséonseca
+ **
+ ** 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);

Added: trunk/plugins/scintilla/scintilla/LexMetapost.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMetapost.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexMySQL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexMySQL.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,367 @@
+// Scintilla source code edit control
+/** @file LexMySQL.cxx
+ ** Lexer for MySQL
+ **/
+// 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 == '+');
+}
+
+static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                            Accessor &styler) {
+
+	WordList &major_keywords = *keywordlists[0];
+	WordList &keywords = *keywordlists[1];
+	WordList &database_objects = *keywordlists[2];
+	WordList &functions = *keywordlists[3];
+	WordList &system_variables = *keywordlists[4];
+	WordList &procedure_keywords = *keywordlists[5];
+	WordList &kw_user1 = *keywordlists[6];
+	WordList &kw_user2 = *keywordlists[7];
+	WordList &kw_user3 = *keywordlists[8];
+
+	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:
+			if (!IsAWordChar(sc.ch)) {
+				int nextState = SCE_MYSQL_DEFAULT;
+				char s[1000];
+				sc.GetCurrentLowered(s, sizeof(s));
+				if (major_keywords.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
+				} else if (keywords.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_KEYWORD);
+				} else if (database_objects.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
+				} else if (functions.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_FUNCTION);
+				} else if (procedure_keywords.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
+				} else if (kw_user1.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_USER1);
+				} else if (kw_user2.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_USER2);
+				} else if (kw_user3.InList(s)) {
+					sc.ChangeState(SCE_MYSQL_USER3);
+				}
+				sc.SetState(nextState);
+			}
+			break;
+		case SCE_MYSQL_VARIABLE:
+			if (!IsAWordChar(sc.ch)) {
+				sc.SetState(SCE_MYSQL_DEFAULT);
+			}
+			break;
+		case SCE_MYSQL_SYSTEMVARIABLE:
+			if (!IsAWordChar(sc.ch)) {
+				char s[1000];
+				sc.GetCurrentLowered(s, sizeof(s));
+// Check for known system variables here.
+				if (system_variables.InList(&s[2])) {
+					sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
+				}
+				sc.SetState(SCE_MYSQL_DEFAULT);
+			}
+			break;
+		case SCE_MYSQL_QUOTEDIDENTIFIER:
+			if (sc.ch == 0x60) {
+				if (sc.chNext == 0x60) {
+					sc.Forward();	// Ignore it
+				} else {
+					sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+				}
+			}
+			break;
+		case SCE_MYSQL_COMMENT:
+			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 == '\\') {
+				// Escape sequence
+				sc.Forward();
+			} else if (sc.ch == '\'') {
+				if (sc.chNext == '\'') {
+					sc.Forward();
+				} else {
+					sc.ChangeState(SCE_MYSQL_STRING);
+					sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+				}
+			}
+			break;
+		case SCE_MYSQL_DQSTRING:
+			if (sc.ch == '\\') {
+				// Escape sequence
+				sc.Forward();
+			} else if (sc.ch == '\"') {
+				if (sc.chNext == '\"') {
+					sc.Forward();
+				} else {
+					sc.ChangeState(SCE_MYSQL_STRING);
+					sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+				}
+			}
+			break;
+		}
+
+		// Determine if a new state should be entered.
+		if (sc.state == SCE_MYSQL_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);
+// Note that the order of SYSTEMVARIABLE and VARIABLE is important here.
+			} else if (sc.ch == 0x40 && sc.chNext == 0x40) {
+				sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
+				sc.Forward(); // Skip past the second at-sign.
+			} else if (sc.ch == 0x40) {
+				sc.SetState(SCE_MYSQL_VARIABLE);
+			} else if (sc.ch == 0x60) {
+				sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
+			} else if (sc.Match('/', '*')) {
+				sc.SetState(SCE_MYSQL_COMMENT);
+				sc.Forward();	// Eat the * so it isn't used for the end of the comment
+			} else if (sc.Match('-', '-') || sc.Match('#')) {
+				sc.SetState(SCE_MYSQL_COMMENTLINE);
+			} else if (sc.ch == '\'') {
+				sc.SetState(SCE_MYSQL_SQSTRING);
+			} else if (sc.ch == '\"') {
+				sc.SetState(SCE_MYSQL_DQSTRING);
+			} else if (isoperator(static_cast<char>(sc.ch))) {
+				sc.SetState(SCE_MYSQL_OPERATOR);
+			}
+		}
+	}
+	sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+	return style == SCE_MYSQL_COMMENT;
+}
+
+// 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;
+
+	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;
+	bool whenFound = false;
+	bool elseFound = 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_MYSQL_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_MYSQL_OPERATOR) {
+			if (ch == '(') {
+				levelNext++;
+			} else if (ch == ')') {
+				levelNext--;
+			}
+		}
+
+// Style new keywords here.
+		if ((style == SCE_MYSQL_MAJORKEYWORD && stylePrev != SCE_MYSQL_MAJORKEYWORD)
+		  || (style == SCE_MYSQL_KEYWORD && stylePrev != SCE_MYSQL_KEYWORD)
+		  || (style == SCE_MYSQL_PROCEDUREKEYWORD && stylePrev != SCE_MYSQL_PROCEDUREKEYWORD)) {
+			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 && endFound && (strcmp(s, "if") == 0 || strcmp(s, "while") == 0 || strcmp(s, "loop") == 0)) {
+				endFound = false;
+				levelNext--;
+				if (levelNext < SC_FOLDLEVELBASE) {
+					levelNext = SC_FOLDLEVELBASE;
+				}
+// Note that else is special here. It may or may be followed by an if then, but in aly case the level stays the
+// same. When followed by a if .. then, the level will be increased later, if not, at eol.
+			} else if (!foldOnlyBegin && strcmp(s, "else") == 0) {
+				levelNext--;
+				elseFound = true;
+			} else if (!foldOnlyBegin && strcmp(s, "then") == 0) {
+				if(whenFound) {
+					whenFound = false;
+				} else {
+					levelNext++;
+				}
+			} else if (strcmp(s, "if") == 0) {
+				elseFound = false;
+			} else if (strcmp(s, "when") == 0) {
+				whenFound = true;
+			} else if (strcmp(s, "begin") == 0) {
+				levelNext++;
+			} else if (!foldOnlyBegin && (strcmp(s, "loop") == 0 || strcmp(s, "repeat") == 0
+			  || strcmp(s, "while") == 0)) {
+				if(endFound) {
+					endFound = false;
+				} else {
+					levelNext++;
+				}
+			} else if (strcmp(s, "end") == 0) {
+// Multiple END in a row are counted multiple times!
+				if (endFound) {
+					levelNext--;
+					if (levelNext < SC_FOLDLEVELBASE) {
+						levelNext = SC_FOLDLEVELBASE;
+					}
+				}
+				endFound = true;
+				whenFound = false;
+			}
+		}
+// Handle this for a trailing end withiut 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(ch)) {
+			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"
+};
+
+LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc);

Added: trunk/plugins/scintilla/scintilla/LexOpal.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexOpal.cxx	Wed Apr  8 20:49:12 2009
@@ -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( !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 != '-' ) &&
+			!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( isdigit( ch ) )
+						{
+							if( !HandleInteger( cur, one_too_much, styler ) ) return;
+						}
+
+						// Keyword
+						else if( 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);

Added: trunk/plugins/scintilla/scintilla/LexOthers.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexOthers.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,1231 @@
+// 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 "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 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 ((isalpha(lineBuffer[offset])) &&
+		(lineBuffer[offset + 1] == ':') &&
+		((isspacechar(lineBuffer[offset + 2])) ||
+		(((lineBuffer[offset + 2] == '\\')) &&
+		(isspacechar(lineBuffer[offset + 3]))))) {
+		// Colorize Regular Keyword
+		styler.ColourTo(endPos, SCE_BAT_WORD);
+		return;
+	}
+
+	// Check for Hide Command (@ECHO OFF/ON)
+	if (lineBuffer[offset] == '@') {
+		styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
+		offset++;
+	}
+	// 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] != '%') &&
+			(!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] != '%') &&
+						(!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] != '%') &&
+						(!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 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] != '%') &&
+				(!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 void ColourisePropsLine(
+    char *lineBuffer,
+    unsigned int lengthLine,
+    unsigned int startLine,
+    unsigned int endPos,
+    Accessor &styler) {
+
+	unsigned int i = 0;
+	while ((i < lengthLine) && isspacechar(lineBuffer[i]))	// Skip initial spaces
+		i++;
+	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 (lineBuffer[++i] == '=')
+				styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
+			styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
+		} else {
+			// Search for the '=' character
+			while ((i < lengthLine) && (lineBuffer[i] != '='))
+				i++;
+			if ((i < lengthLine) && (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;
+	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);
+			linePos = 0;
+			startLine = i + 1;
+		}
+	}
+	if (linePos > 0) {	// Last line does not have ending characters
+		ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
+	}
+}
+
+// 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 && isalpha(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
+						word[chPos++] = lineBuffer[j];
+					word[chPos] = 0;
+					if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") ||
+						!CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") ||
+						!CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) {
+						state = stMsVc;
+					} else
+						state = stUnrecognized;
+				} else {
+					state = 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;
+	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");

Added: trunk/plugins/scintilla/scintilla/LexPB.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPB.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexPLM.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPLM.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexPOV.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPOV.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexPS.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPS.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexPascal.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPascal.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,373 @@
+// 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)
+ **/
+
+#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 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 classifyWordPascal(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInClass, bool bInAsm) {
+	int ret = 0;
+
+	WordList& keywords = *keywordlists[0];
+	WordList& classwords = *keywordlists[1];
+
+	char s[100];
+	getRange(start, end, styler, s, sizeof(s));
+
+	char chAttr = SCE_C_IDENTIFIER;
+	if (isdigit(s[0]) || (s[0] == '.') ||(s[0] == '$')) {
+		chAttr = SCE_C_NUMBER;
+	}
+	else {
+		if (s[0] == '#') {
+			chAttr = SCE_C_CHARACTER;
+		}
+		else {
+			if (keywords.InList(s)) {
+				chAttr = SCE_C_WORD;
+
+				if(strcmp(s, "class") == 0) {
+					ret = 1;
+				}
+				else if (strcmp(s, "asm") == 0) {
+					ret = 2;
+				}
+				else if (strcmp(s, "end") == 0) {
+					ret = -1;
+				}
+			} else if (bInClass) {
+				if (classwords.InList(s)) {
+					chAttr = SCE_C_WORD;
+				}
+			}
+		}
+	}
+	ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
+	return ret;
+}
+
+static int classifyFoldPointPascal(const char* s) {
+	int lev = 0;
+	if (!(isdigit(s[0]) || (s[0] == '.'))) {
+		if (strcmp(s, "begin") == 0 ||
+			strcmp(s, "object") == 0 ||
+			strcmp(s, "case") == 0 ||
+			strcmp(s, "class") == 0 ||
+			strcmp(s, "record") == 0 ||
+			strcmp(s, "try") == 0) {
+			lev=1;
+		} else if (strcmp(s, "end") == 0) {
+			lev=-1;
+		}
+	}
+	return lev;
+}
+
+static void ColourisePascalDoc(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);
+	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;
+			}
+			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 (iswordstart(ch) || ch == '#' || ch == '$' || (ch == '@' && bInAsm)) {
+				ColourTo(styler, i-1, state, bInAsm);
+				state = SCE_C_IDENTIFIER;
+			} else if (ch == '{' && chNext != '$' && chNext != '&') {
+				ColourTo(styler, i-1, state, bInAsm);
+				state = SCE_C_COMMENT;
+			} else if (ch == '(' && chNext == '*'
+						&& styler.SafeGetCharAt(i + 2) != '$'
+						&& styler.SafeGetCharAt(i + 2) != '&') {
+				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_CHARACTER;
+			} else if (ch == '{' && (chNext == '$' || chNext=='&')) {
+				ColourTo(styler, i-1, state, bInAsm);
+				state = SCE_C_PREPROCESSOR;
+			} else if (isoperator(ch)) {
+				ColourTo(styler, i-1, state, bInAsm);
+				ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+
+			}
+		} else if (state == SCE_C_IDENTIFIER) {
+			bool bDoublePoint = ((ch == '.') && (chPrev == '.'));
+			if ((!iswordchar(ch) && ch != '$' && ch != '#' && (ch != '@' || !bInAsm)) || bDoublePoint) {
+				if (bDoublePoint) i--;
+				int lStateChange = classifyWordPascal(styler.GetStartSegment(), i - 1, keywordlists, styler, bInClassDefinition, 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 (bDoublePoint) {
+					i++;
+					ColourTo(styler, i-1, SCE_C_DEFAULT, bInAsm);
+				}
+
+				state = SCE_C_DEFAULT;
+				chNext = styler.SafeGetCharAt(i + 1);
+				if (ch == '{' && chNext != '$' && chNext != '&') {
+					state = SCE_C_COMMENT;
+				} else if (ch == '(' && chNext == '*'
+						&& styler.SafeGetCharAt(i + 2) != '$'
+						&& styler.SafeGetCharAt(i + 2) != '&') {
+					ColourTo(styler, i-1, state, bInAsm);
+					state = SCE_C_COMMENTDOC;
+				} else if (ch == '/' && chNext == '/') {
+					state = SCE_C_COMMENTLINE;
+				} else if (ch == '\'') {
+					state = SCE_C_CHARACTER;
+				} else if (isoperator(ch)) {
+					ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
+				}
+			}
+		} else {
+			if (state == SCE_C_PREPROCESSOR) {
+				if (ch=='}'){
+					ColourTo(styler, i, state, bInAsm);
+					state = SCE_C_DEFAULT;
+				} else {
+					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 == '}' ) {
+					ColourTo(styler, i, state, bInAsm);
+					state = SCE_C_DEFAULT;
+				}
+			} else if (state == SCE_C_COMMENTDOC) {
+				if (ch == ')' && chPrev == '*') {
+					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_CHARACTER) {
+				if (ch == '\'') {
+					ColourTo(styler, i, state, bInAsm);
+					state = SCE_C_DEFAULT;
+				}
+			}
+		}
+		chPrev = ch;
+	}
+	ColourTo(styler, lengthDoc - 1, state, bInAsm);
+}
+
+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;
+	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_C_WORD && style == SCE_C_WORD)
+		{
+			// Store last word start point.
+			lastStart = i;
+		}
+
+		if (stylePrev == SCE_C_WORD) {
+			if(iswordchar(ch) && !iswordchar(chNext)) {
+				char s[100];
+				getRange(lastStart, i, styler, s, sizeof(s));
+				levelCurrent += classifyFoldPointPascal(s);
+			}
+		}
+
+		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;
+			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 pascalWordListDesc[] = {
+	"Keywords",
+	"Classwords",
+	0
+};
+
+LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc);

Added: trunk/plugins/scintilla/scintilla/LexPerl.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPerl.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,1295 @@
+// 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
+	if (s[strlen(s) - 1] == '\r')
+		s[strlen(s) - 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;
+				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
+				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
+	bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0;
+	bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0;
+	unsigned int endPos = startPos + length;
+	int visibleChars = 0;
+	int lineCurrent = styler.GetLine(startPos);
+	int levelPrev = 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 == '=' && 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);

Added: trunk/plugins/scintilla/scintilla/LexPowerShell.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPowerShell.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+

Added: trunk/plugins/scintilla/scintilla/LexProgress.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexProgress.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,276 @@
+// 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
+change lmPS to lmProgress
+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];
+    WordList &keywords2 = *keywordlists[1];
+    WordList &keywords3 = *keywordlists[2];
+    //WordList &keywords4 = *keywordlists[3];
+    //WordList &keywords5 = *keywordlists[4];
+
+	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.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);
+				} else if (sc.ch == '*' && sc.chNext == '/') {
+					sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
+				}
+				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))) {
+				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_PS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists);
+
+

Added: trunk/plugins/scintilla/scintilla/LexPython.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexPython.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,461 @@
+// 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
+
+enum kwType { kwOther, kwClass, kwDef, kwImport };
+static const int indicatorWhitespace = 1;
+
+static bool IsPyComment(Accessor &styler, int pos, int len) {
+	return len > 0 && styler[pos] == '#';
+}
+
+static bool IsPyStringStart(int ch, int chNext, int chNext2) {
+	if (ch == '\'' || ch == '"')
+		return true;
+	if (ch == 'u' || ch == 'U') {
+		if (chNext == '"' || chNext == '\'')
+			return true;
+		if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\''))
+			return true;
+	}
+	if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\''))
+		return true;
+
+	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) {
+	char ch = styler.SafeGetCharAt(i);
+	char chNext = styler.SafeGetCharAt(i + 1);
+
+	// Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars
+	if (ch == 'r' || ch == 'R') {
+		i++;
+		ch = styler.SafeGetCharAt(i);
+		chNext = styler.SafeGetCharAt(i + 1);
+	} else if (ch == 'u' || ch == 'U') {
+		if (chNext == 'r' || chNext == 'R')
+			i += 2;
+		else
+			i += 1;
+		ch = styler.SafeGetCharAt(i);
+		chNext = styler.SafeGetCharAt(i + 1);
+	}
+
+	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--;
+			startPos = styler.LineStart(lineCurrent);
+			if (startPos == 0)
+				initStyle = SCE_P_DEFAULT;
+			else
+				initStyle = styler.StyleAt(startPos - 1);
+		}
+	}
+
+	WordList &keywords = *keywordlists[0];
+	WordList &keywords2 = *keywordlists[1];
+
+	const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
+
+	initStyle = initStyle & 31;
+	if (initStyle == SCE_P_STRINGEOL) {
+		initStyle = SCE_P_DEFAULT;
+	}
+
+	kwType kwLast = kwOther;
+	int spaceFlags = 0;
+	styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
+	bool hexadecimal = false;
+
+	StyleContext sc(startPos, endPos - startPos, initStyle, styler);
+
+	bool indentGood = true;
+	int startIndicator = sc.currentPos;
+
+	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)) {
+				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) &&
+			        !(!hexadecimal && ((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 (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
+						kwLast = kwOther;
+				} else {
+					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();
+				}
+				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;
+		}
+
+		// 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')) {
+					hexadecimal = true;
+				} else {
+					hexadecimal = 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))) {
+				unsigned int nextIndex = 0;
+				sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex));
+				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
+	const bool foldComment = styler.GetPropertyInt("fold.comment.python") != 0;
+	const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 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 pythonWordListDesc[] = {
+	"Keywords",
+	"Highlighted identifiers",
+	0
+};
+
+LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc, "python", FoldPyDoc,
+					 pythonWordListDesc);

Added: trunk/plugins/scintilla/scintilla/LexR.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexR.cxx	Wed Apr  8 20:49:12 2009
@@ -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) || (sc.ch == '.')) {
+				char s[100];
+				sc.GetCurrentLowered(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);

Added: trunk/plugins/scintilla/scintilla/LexRebol.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexRebol.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+

Added: trunk/plugins/scintilla/scintilla/LexRuby.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexRuby.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexSQL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexSQL.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,346 @@
+// 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);
+
+	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;
+
+	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
+						strcmp(s, "exists") == 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);

Added: trunk/plugins/scintilla/scintilla/LexSmalltalk.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexSmalltalk.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexSpecman.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexSpecman.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexSpice.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexSpice.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,225 @@
+// 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 "Platform.h"
+
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "PropSet.h"
+#include "KeyWords.h"
+#include "SciLexer.h"
+#include "SString.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;
+    SString 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);
+    SString 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 == '_';
+}

Added: trunk/plugins/scintilla/scintilla/LexTADS3.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexTADS3.cxx	Wed Apr  8 20:49:12 2009
@@ -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);

Added: trunk/plugins/scintilla/scintilla/LexTeX.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexTeX.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,491 @@
+// 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) ;
+					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);

Added: trunk/plugins/scintilla/scintilla/LexVB.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexVB.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,282 @@
+// 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++;
+		}
+	}
+	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);
+

Added: trunk/plugins/scintilla/scintilla/LexVHDL.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexVHDL.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,477 @@
+// 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 initStyle,
+  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);
+  int   style           = initStyle;
+  //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);
+    }
+    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
+//
+

Added: trunk/plugins/scintilla/scintilla/LexVerilog.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LexVerilog.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,305 @@
+// 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;
+}
+
+// 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 && (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);

Added: trunk/plugins/scintilla/scintilla/LineMarker.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LineMarker.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,309 @@
+// 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) {
+		// 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);
+	}
+}

Added: trunk/plugins/scintilla/scintilla/LineMarker.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/LineMarker.h	Wed Apr  8 20:49:12 2009
@@ -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

Added: trunk/plugins/scintilla/scintilla/PlatGTK.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/PlatGTK.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,2755 @@
+// 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
+
+#if GTK_MAJOR_VERSION >= 2
+#define USE_PANGO 1
+#include "Converter.h"
+#endif
+
+#ifdef _MSC_VER
+// Ignore unreferenced local functions in GTK+ headers
+#pragma warning(disable: 4505)
+#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;
+#ifdef USE_PANGO
+	PangoFontDescription *pfd;
+	int characterSet;
+#endif
+	FontHandle(GdkFont *pfont_) {
+		et = singleByte;
+		ascent = 0;
+		pfont = pfont_;
+#ifdef USE_PANGO
+		pfd = 0;
+		characterSet = -1;
+#endif
+		ResetWidths(et);
+	}
+#ifdef USE_PANGO
+	FontHandle(PangoFontDescription *pfd_, int characterSet_) {
+		et = singleByte;
+		ascent = 0;
+		pfont = 0;
+		pfd = pfd_;
+		characterSet = characterSet_;
+		ResetWidths(et);
+	}
+#endif
+	~FontHandle() {
+		if (pfont)
+			gdk_font_unref(pfont);
+		pfont = 0;
+#ifdef USE_PANGO
+		if (pfd)
+			pango_font_description_free(pfd);
+		pfd = 0;
+#endif
+	}
+	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 id) {
+	return reinterpret_cast<GtkWidget *>(id);
+}
+
+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);
+		d1 = strchr(tmp, '-');
+		// we know the first dash exists
+		d2 = strchr(d1 + 1, '-');
+		if (d2)
+			d3 = strchr(d2 + 1, '-');
+		if (d3) {
+			// 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 id_);
+};
+
+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_);
+	id = 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 (id)
+		delete PFont(*this);
+	id = 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->id;
+		}
+	}
+	if (ret == 0) {
+		FontCached *fc = new FontCached(faceName_, characterSet_, size_, bold_, italic_);
+		if (fc) {
+			fc->next = first;
+			first = fc;
+			ret = fc->id;
+		}
+	}
+	FontMutexUnlock();
+	return ret;
+}
+
+void FontCached::ReleaseId(FontID id_) {
+	FontMutexLock();
+	FontCached **pcur = &first;
+	for (FontCached *cur = first; cur; cur = cur->next) {
+		if (cur->id == id_) {
+			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';
+
+#ifdef USE_PANGO
+	//if (fontName[0] == '!') {
+	PangoFontDescription *pfd = pango_font_description_new();
+	if (pfd) {
+		pango_font_description_set_family(pfd, fontName);
+		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);
+	}
+	//}
+#endif
+
+	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() : id(0) {}
+
+Font::~Font() {}
+
+void Font::Create(const char *faceName, int characterSet, int size,
+	bool bold, bool italic, bool) {
+	Release();
+	id = FontCached::FindOrCreate(faceName, characterSet, size, bold, italic);
+}
+
+void Font::Release() {
+	if (id)
+		FontCached::ReleaseId(id);
+	id = 0;
+}
+
+class SurfaceImpl : public Surface {
+	encodingType et;
+	GdkDrawable *drawable;
+	GdkGC *gc;
+	GdkPixmap *ppixmap;
+	int x;
+	int y;
+	bool inited;
+	bool createdGC;
+#ifdef USE_PANGO
+	PangoContext *pcontext;
+	PangoLayout *layout;
+	Converter conv;
+	int characterSet;
+	void SetConverter(int characterSet_);
+#endif
+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);
+};
+
+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 "";
+	}
+}
+
+#ifdef USE_PANGO
+
+void SurfaceImpl::SetConverter(int characterSet_) {
+	if (characterSet != characterSet_) {
+		characterSet = characterSet_;
+		conv.Open("UTF-8", CharacterSetID(characterSet), false);
+	}
+}
+#endif
+
+SurfaceImpl::SurfaceImpl() : et(singleByte), drawable(0), gc(0), ppixmap(0),
+x(0), y(0), inited(false), createdGC(false)
+#ifdef USE_PANGO
+, pcontext(0), layout(0), characterSet(-1)
+#endif
+{
+}
+
+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;
+#ifdef USE_PANGO
+	if (layout)
+		g_object_unref(layout);
+	layout = 0;
+	if (pcontext)
+		g_object_unref(pcontext);
+	pcontext = 0;
+	conv.Close();
+	characterSet = -1;
+#endif
+	x = 0;
+	y = 0;
+	inited = false;
+	createdGC = false;
+}
+
+bool SurfaceImpl::Initialised() {
+	return inited;
+}
+
+// The WindowID argument is only used for Pango builds
+#ifdef USE_PANGO
+#define WID_NAME wid
+#else
+#define WID_NAME
+#endif
+
+void SurfaceImpl::Init(WindowID WID_NAME) {
+	Release();
+#ifdef USE_PANGO
+	PLATFORM_ASSERT(wid);
+	pcontext = gtk_widget_create_pango_context(PWidget(wid));
+	PLATFORM_ASSERT(pcontext);
+	layout = pango_layout_new(pcontext);
+	PLATFORM_ASSERT(layout);
+#endif
+	inited = true;
+}
+
+void SurfaceImpl::Init(SurfaceID sid, WindowID WID_NAME) {
+	PLATFORM_ASSERT(sid);
+	GdkDrawable *drawable_ = reinterpret_cast<GdkDrawable *>(sid);
+	Release();
+#ifdef USE_PANGO
+	PLATFORM_ASSERT(wid);
+	pcontext = gtk_widget_create_pango_context(PWidget(wid));
+	layout = pango_layout_new(pcontext);
+#endif
+	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_NAME) {
+	PLATFORM_ASSERT(surface_);
+	Release();
+	SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
+	PLATFORM_ASSERT(surfImpl->drawable);
+#ifdef USE_PANGO
+	PLATFORM_ASSERT(wid);
+	pcontext = gtk_widget_create_pango_context(PWidget(wid));
+	PLATFORM_ASSERT(pcontext);
+	layout = pango_layout_new(pcontext);
+	PLATFORM_ASSERT(layout);
+#endif
+	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);
+	}
+}
+
+#if GTK_MAJOR_VERSION >= 2
+
+// 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;
+}
+
+#endif
+
+#if GTK_MAJOR_VERSION < 2
+void SurfaceImpl::AlphaRectangle(PRectangle rc, int , ColourAllocated , int , ColourAllocated outline, int , int ) {
+	if (gc && drawable) {
+		// Can't use GdkPixbuf on GTK+ 1.x, so draw an outline rather than use alpha.
+		PenColour(outline);
+		gdk_draw_rectangle(drawable, gc, 0,
+		                   rc.left, rc.top,
+		                   rc.right - rc.left - 1, rc.bottom - rc.top - 1);
+	}
+}
+#else
+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);
+
+		guint8 pixVal[4] = {0};
+		guint32 valEmpty = *(reinterpret_cast<guint32 *>(pixVal));
+		pixVal[0] = GetRValue(fill.AsLong());
+		pixVal[1] = GetGValue(fill.AsLong());
+		pixVal[2] = GetBValue(fill.AsLong());
+		pixVal[3] = alphaFill;
+		guint32 valFill = *(reinterpret_cast<guint32 *>(pixVal));
+		pixVal[0] = GetRValue(outline.AsLong());
+		pixVal[1] = GetGValue(outline.AsLong());
+		pixVal[2] = GetBValue(outline.AsLong());
+		pixVal[3] = alphaOutline;
+		guint32 valOutline = *(reinterpret_cast<guint32 *>(pixVal));
+		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);
+	}
+}
+#endif
+
+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;
+}
+
+#ifdef USE_PANGO
+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;
+	}
+}
+
+#endif
+
+// 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;
+#ifdef USE_PANGO
+		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);
+			PangoLayoutLine *pll = pango_layout_get_line(layout,0);
+			gdk_draw_layout_line(drawable, gc, xText, ybase, pll);
+			if (useGFree) {
+				g_free(utfForm);
+			} else {
+				delete []utfForm;
+			}
+			return;
+		}
+#endif
+		// 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;
+		}
+	}
+}
+
+void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
+	if (font_.GetID()) {
+		int totalWidth = 0;
+#ifdef USE_PANGO
+		const int lenPositions = len;
+		if (PFont(font_)->pfd) {
+			if (len == 1) {
+				int width = PFont(font_)->CharWidth(*s, et);
+				if (width) {
+					positions[0] = width;
+					return;
+				}
+			}
+			PangoRectangle pos;
+			pango_layout_set_font_description(layout, PFont(font_)->pfd);
+			if (et == UTF8) {
+				// Simple and direct as UTF-8 is native Pango encoding
+				pango_layout_set_text(layout, s, len);
+				PangoLayoutIter *iter = pango_layout_get_iter(layout);
+				pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+				int i = 0;
+				while (pango_layout_iter_next_cluster(iter)) {
+					pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+					int position = PANGO_PIXELS(pos.x);
+					int curIndex = pango_layout_iter_get_index(iter);
+					int places = curIndex - i;
+					int distance = position - positions[i-1];
+					while (i < 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] = position - (curIndex - 1 - i) * distance / places;
+						i++;
+					}
+				}
+				while (i < lenPositions)
+					positions[i++] = PANGO_PIXELS(pos.x + pos.width);
+				pango_layout_iter_free(iter);
+				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 utfIndex = 0;
+						PangoLayoutIter *iter = pango_layout_get_iter(layout);
+						pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+						while (pango_layout_iter_next_cluster(iter)) {
+							pango_layout_iter_get_cluster_extents (iter, NULL, &pos);
+							int position = PANGO_PIXELS(pos.x);
+							int utfIndexNext = pango_layout_iter_get_index(iter);
+							while (utfIndex < utfIndexNext) {
+								size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
+								//size_t lenChar = mblen(s+i, MB_CUR_MAX);
+								while (lenChar--) {
+									positions[i++] = position;
+									positionsCalculated++;
+								}
+								utfIndex += UTF8CharLength(utfForm+utfIndex);
+							}
+						}
+						while (i < lenPositions)
+							positions[i++] = PANGO_PIXELS(pos.x + pos.width);
+						pango_layout_iter_free(iter);
+						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);
+					PangoLayoutIter *iter = pango_layout_get_iter(layout);
+					pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+					int i = 0;
+					int positionStart = 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.
+					while (pango_layout_iter_next_cluster(iter)) {
+						pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
+						int position = PANGO_PIXELS(pos.x);
+						int distance = position - positionStart;
+						int clusterEnd = pango_layout_iter_get_index(iter);
+						int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
+						PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
+						for (int charInLig=0; charInLig<ligatureLength; charInLig++) {
+							positions[i++] = position - (ligatureLength - 1 - charInLig) * distance / ligatureLength;
+						}
+						positionStart = position;
+						clusterStart = clusterEnd;
+					}
+					while (i < lenPositions)
+						positions[i++] = PANGO_PIXELS(pos.x + pos.width);
+					pango_layout_iter_free(iter);
+					if (useGFree) {
+						g_free(utfForm);
+					} else {
+						delete []utfForm;
+					}
+					PLATFORM_ASSERT(i == lenPositions);
+				}
+			}
+			if (len == 1) {
+				PFont(font_)->SetCharWidth(*s, positions[0], et);
+			}
+			return;
+		}
+#endif
+		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()) {
+#ifdef USE_PANGO
+		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);
+			}
+			PangoLayoutLine *pangoLine = pango_layout_get_line(layout, 0);
+			pango_layout_line_get_extents(pangoLine, NULL, &pos);
+			if (useGFree) {
+				g_free(utfForm);
+			} else {
+				delete []utfForm;
+			}
+			return PANGO_PIXELS(pos.width);
+		}
+#endif
+		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()) {
+#ifdef USE_PANGO
+		if (PFont(font_)->pfd) {
+			return WidthText(font_, &ch, 1);
+		}
+#endif
+		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;
+#ifdef USE_PANGO
+	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;
+	}
+#endif
+	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
+
+#ifdef USE_PANGO
+	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;
+	}
+#endif
+	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 (id)
+		gtk_widget_destroy(GTK_WIDGET(id));
+	id = 0;
+}
+
+bool Window::HasFocus() {
+	return GTK_WIDGET_HAS_FOCUS(id);
+}
+
+PRectangle Window::GetPosition() {
+	// Before any size allocated pretend its 1000 wide so not scrolled
+	PRectangle rc(0, 0, 1000, 1000);
+	if (id) {
+		rc.left = PWidget(id)->allocation.x;
+		rc.top = PWidget(id)->allocation.y;
+		if (PWidget(id)->allocation.width > 20) {
+			rc.right = rc.left + PWidget(id)->allocation.width;
+			rc.bottom = rc.top + PWidget(id)->allocation.height;
+		}
+	}
+	return rc;
+}
+
+void Window::SetPosition(PRectangle rc) {
+#if 1
+	//gtk_widget_set_uposition(id, rc.left, rc.top);
+	GtkAllocation alloc;
+	alloc.x = rc.left;
+	alloc.y = rc.top;
+	alloc.width = rc.Width();
+	alloc.height = rc.Height();
+	gtk_widget_size_allocate(PWidget(id), &alloc);
+#else
+
+	gtk_widget_set_uposition(id, rc.left, rc.top);
+	gtk_widget_set_usize(id, rc.right - rc.left, rc.bottom - rc.top);
+#endif
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window relativeTo) {
+	int ox = 0;
+	int oy = 0;
+	gdk_window_get_origin(PWidget(relativeTo.id)->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_widget_set_uposition(PWidget(id), ox, oy);
+#if 0
+
+	GtkAllocation alloc;
+	alloc.x = rc.left + ox;
+	alloc.y = rc.top + oy;
+	alloc.width = rc.right - rc.left;
+	alloc.height = rc.bottom - rc.top;
+	gtk_widget_size_allocate(id, &alloc);
+#endif
+	gtk_widget_set_usize(PWidget(id), 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(id));
+}
+
+void Window::InvalidateAll() {
+	if (id) {
+		gtk_widget_queue_draw(PWidget(id));
+	}
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+	if (id) {
+		gtk_widget_queue_draw_area(PWidget(id),
+		                           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(id)->window)
+		gdk_window_set_cursor(PWidget(id)->window, gdkCurs);
+	gdk_cursor_destroy(gdkCurs);
+}
+
+void Window::SetTitle(const char *s) {
+	gtk_window_set_title(GTK_WINDOW(id), 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(id)->window, &x_offset, &y_offset);
+
+// gtk 2.2+
+#if GTK_MAJOR_VERSION > 2 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2)
+	{
+		GdkScreen* screen;
+		gint monitor_num;
+		GdkRectangle rect;
+
+		screen = gtk_widget_get_screen(PWidget(id));
+		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;
+#if GTK_MAJOR_VERSION < 2
+	GdkPixmap *pixmap;
+	GdkBitmap *bitmap;
+#else
+	GdkPixbuf *pixbuf;
+#endif
+};
+
+static void list_image_free(gpointer, gpointer value, gpointer) {
+	ListImage *list_image = (ListImage *) value;
+#if GTK_MAJOR_VERSION < 2
+	if (list_image->pixmap)
+		gdk_pixmap_unref(list_image->pixmap);
+	if (list_image->bitmap)
+		gdk_bitmap_unref(list_image->bitmap);
+#else
+	if (list_image->pixbuf)
+		gdk_pixbuf_unref (list_image->pixbuf);
+#endif
+	g_free(list_image);
+}
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+#if GTK_MAJOR_VERSION >= 2
+enum {
+	PIXBUF_COLUMN,
+	TEXT_COLUMN,
+	N_COLUMNS
+};
+#endif
+
+class ListBoxX : public ListBox {
+	WindowID list;
+	WindowID scroller;
+#if GTK_MAJOR_VERSION < 2
+	int current;
+#endif
+	void *pixhash;
+	int lineHeight;
+	XPMSet xset;
+	bool unicodeMode;
+	int desiredVisibleRows;
+	unsigned int maxItemCharacters;
+	unsigned int aveCharWidth;
+public:
+	CallBackAction doubleClickAction;
+	void *doubleClickActionData;
+
+	ListBoxX() : list(0), pixhash(NULL), desiredVisibleRows(5), maxItemCharacters(0),
+		doubleClickAction(NULL), doubleClickActionData(NULL) {
+#if GTK_MAJOR_VERSION < 2
+			current = 0;
+#endif
+	}
+	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;
+}
+
+#if GTK_MAJOR_VERSION < 2
+static void UnselectionAC(GtkWidget *, gint, gint,
+                        GdkEventButton *, gpointer p) {
+	int *pi = reinterpret_cast<int *>(p);
+	*pi = -1;
+}
+static void SelectionAC(GtkWidget *, gint row, gint,
+                        GdkEventButton *, gpointer p) {
+	int *pi = reinterpret_cast<int *>(p);
+	*pi = row;
+}
+#endif
+
+static gboolean ButtonPress(GtkWidget *, GdkEventButton* ev, gpointer p) {
+	ListBoxX* lb = reinterpret_cast<ListBoxX*>(p);
+	if (ev->type == GDK_2BUTTON_PRESS && lb->doubleClickAction != NULL) {
+		lb->doubleClickAction(lb->doubleClickActionData);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+#if GTK_MAJOR_VERSION >= 2
+/* 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]);
+}
+#endif
+
+void ListBoxX::Create(Window &, int, Point, int, bool) {
+	id = 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));
+
+#if GTK_MAJOR_VERSION < 2
+	list = gtk_clist_new(1);
+	GtkWidget *wid = PWidget(list);	// No code inside the GTK_OBJECT macro
+	gtk_widget_show(wid);
+	gtk_container_add(GTK_CONTAINER(PWidget(scroller)), wid);
+	gtk_clist_set_column_auto_resize(GTK_CLIST(wid), 0, TRUE);
+	gtk_clist_set_selection_mode(GTK_CLIST(wid), GTK_SELECTION_BROWSE);
+	gtk_signal_connect(GTK_OBJECT(wid), "unselect_row",
+	                   GTK_SIGNAL_FUNC(UnselectionAC), &current);
+	gtk_signal_connect(GTK_OBJECT(wid), "select_row",
+	                   GTK_SIGNAL_FUNC(SelectionAC), &current);
+	gtk_signal_connect(GTK_OBJECT(wid), "button_press_event",
+	                   GTK_SIGNAL_FUNC(ButtonPress), this);
+	gtk_clist_set_shadow_type(GTK_CLIST(wid), GTK_SHADOW_NONE);
+#else
+	/* 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");
+
+	GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(column, renderer, FALSE);
+	gtk_tree_view_column_add_attribute(column, renderer,
+										"pixbuf", PIXBUF_COLUMN);
+
+	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);
+#endif
+	gtk_widget_realize(PWidget(id));
+}
+
+void ListBoxX::SetFont(Font &scint_font) {
+#if GTK_MAJOR_VERSION < 2
+	GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(PWidget(list)));
+	if (!gdk_font_equal(style->font, PFont(scint_font)->pfont)) {
+		style = gtk_style_copy(style);
+		gdk_font_unref(style->font);
+		style->font = PFont(scint_font)->pfont;
+		gdk_font_ref(style->font);
+		gtk_widget_set_style(GTK_WIDGET(PWidget(list)), style);
+		gtk_style_unref(style);
+	}
+#else
+	// 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);
+	}
+#endif
+}
+
+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 (id) {
+		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
+#if GTK_MAJOR_VERSION < 2
+		int ythickness = PWidget(list)->style->klass->ythickness;
+		height = (rows * GTK_CLIST(list)->row_height
+		          + rows + 1
+		          + 2 * (ythickness
+		                 + GTK_CONTAINER(PWidget(list))->border_width));
+#else
+		// 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));
+#endif
+		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() {
+	return 4 + xset.GetWidth();
+}
+
+void ListBoxX::Clear() {
+#if GTK_MAJOR_VERSION < 2
+	gtk_clist_clear(GTK_CLIST(list));
+#else
+	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
+	gtk_list_store_clear(GTK_LIST_STORE(model));
+#endif
+	maxItemCharacters = 0;
+}
+
+#if GTK_MAJOR_VERSION < 2
+static void init_pixmap(ListImage *list_image, GtkWidget *window) {
+#else
+static void init_pixmap(ListImage *list_image) {
+#endif
+	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 GTK_MAJOR_VERSION < 2
+	if (list_image->pixmap)
+		gdk_pixmap_unref(list_image->pixmap);
+	list_image->pixmap = NULL;
+	if (list_image->bitmap)
+		gdk_bitmap_unref(list_image->bitmap);
+	list_image->bitmap = NULL;
+
+	list_image->pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL
+	             , gtk_widget_get_colormap(window), &(list_image->bitmap), NULL
+	             , (gchar **) xpm_lineform);
+	if (NULL == list_image->pixmap) {
+		if (list_image->bitmap)
+			gdk_bitmap_unref(list_image->bitmap);
+		list_image->bitmap = NULL;
+	}
+#else
+	if (list_image->pixbuf)
+		gdk_pixbuf_unref(list_image->pixbuf);
+	list_image->pixbuf =
+		gdk_pixbuf_new_from_xpm_data((const gchar**)xpm_lineform);
+#endif
+	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));
+	}
+#if GTK_MAJOR_VERSION < 2
+	char * szs[] = { s, NULL };
+	int rownum = gtk_clist_append(GTK_CLIST(list), szs);
+	if (list_image) {
+		if (NULL == list_image->pixmap)
+			init_pixmap(list_image, (GtkWidget *) list);
+		gtk_clist_set_pixtext(GTK_CLIST(list), rownum, 0, s, SPACING
+		                      , list_image->pixmap, list_image->bitmap);
+	}
+#else
+	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);
+		} 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);
+	}
+#endif
+	size_t len = strlen(s);
+	if (maxItemCharacters < len)
+		maxItemCharacters = len;
+}
+
+int ListBoxX::Length() {
+	if (id)
+#if GTK_MAJOR_VERSION < 2
+		return GTK_CLIST(list)->rows;
+#else
+		return gtk_tree_model_iter_n_children(gtk_tree_view_get_model
+											   (GTK_TREE_VIEW(list)), NULL);
+#endif
+	return 0;
+}
+
+void ListBoxX::Select(int n) {
+#if GTK_MAJOR_VERSION < 2
+	if (n == -1) {
+		gtk_clist_unselect_row(GTK_CLIST(list), current, 0);
+	} else {
+		gtk_clist_select_row(GTK_CLIST(list), n, 0);
+		gtk_clist_moveto(GTK_CLIST(list), n, 0, 0.5, 0.5);
+	}
+#else
+	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);
+	}
+#endif
+}
+
+int ListBoxX::GetSelection() {
+#if GTK_MAJOR_VERSION < 2
+	return current;
+#else
+	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;
+#endif
+}
+
+int ListBoxX::Find(const char *prefix) {
+#if GTK_MAJOR_VERSION < 2
+	int count = Length();
+	for (int i = 0; i < count; i++) {
+		char *s = 0;
+		gtk_clist_get_text(GTK_CLIST(list), i, 0, &s);
+		if (s && (0 == strncmp(prefix, s, strlen(prefix)))) {
+			return i;
+		}
+	}
+#else
+	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++;
+	}
+#endif
+	return -1;
+}
+
+void ListBoxX::GetValue(int n, char *value, int len) {
+	char *text = NULL;
+#if GTK_MAJOR_VERSION < 2
+	GtkCellType type = gtk_clist_get_cell_type(GTK_CLIST(list), n, 0);
+	switch (type) {
+	case GTK_CELL_TEXT:
+		gtk_clist_get_text(GTK_CLIST(list), n, 0, &text);
+		break;
+	case GTK_CELL_PIXTEXT:
+		gtk_clist_get_pixtext(GTK_CLIST(list), n, 0, &text, NULL, NULL, NULL);
+		break;
+	default:
+		break;
+	}
+#else
+	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);
+	}
+#endif
+	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 GTK_MAJOR_VERSION < 2
+		if (list_image->pixmap)
+			gdk_pixmap_unref(list_image->pixmap);
+		list_image->pixmap = 0;
+		if (list_image->bitmap)
+			gdk_bitmap_unref(list_image->bitmap);
+		list_image->bitmap = 0;
+#else
+		if (list_image->pixbuf)
+			gdk_pixbuf_unref(list_image->pixbuf);
+		list_image->pixbuf = NULL;
+#endif
+		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() : id(0) {}
+
+void Menu::CreatePopUp() {
+	Destroy();
+	id = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
+}
+
+void Menu::Destroy() {
+	if (id)
+#if GTK_MAJOR_VERSION < 2
+		gtk_object_unref(GTK_OBJECT(id));
+#else
+		g_object_unref(G_OBJECT(id));
+#endif
+	id = 0;
+}
+
+void Menu::Show(Point pt, Window &) {
+	int screenHeight = gdk_screen_height();
+	int screenWidth = gdk_screen_width();
+	GtkItemFactory *factory = reinterpret_cast<GtkItemFactory *>(id);
+	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;
+	}
+#if GTK_MAJOR_VERSION >= 2
+	gtk_item_factory_popup(factory, pt.x - 4, pt.y - 4, 3,
+		gtk_get_current_event_time());
+#else
+	gtk_item_factory_popup(factory, pt.x - 4, pt.y - 4, 3, 0);
+#endif
+}
+
+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
+#ifdef USE_PANGO
+	return "!Sans";
+#else
+	return "lucidatypewriter";
+#endif
+#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 */) {
+	return false;
+}
+
+int Platform::DBCSCharLength(int, const char *s) {
+	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();
+}

Added: trunk/plugins/scintilla/scintilla/PositionCache.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/PositionCache.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,635 @@
+// 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 "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 "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),
+	validity(llInvalid),
+	xHighlightGuide(0),
+	highlightColumn(0),
+	selStart(0),
+	selEnd(0),
+	containsCaret(false),
+	edgeColumn(0),
+	chars(0),
+	styles(0),
+	styleBitsSet(0),
+	indicators(0),
+	positions(0),
+	hsStart(0),
+	hsEnd(0),
+	widthLine(wrapWidthInfinite),
+	lines(1) {
+	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) {
+		int startLine = LineStart(line);
+		int endLine = numCharsInLine;
+		while ((endLine > startLine) && IsEOLChar(chars[endLine-1])) {
+			endLine--;
+		}
+		return endLine;
+	} 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];
+		if (!newLineStarts)
+			return;
+		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;
+}
+
+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) :
+	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 (ll->selStart != ll->selEnd) {
+		Insert(ll->selStart - posLineStart - 1);
+		Insert(ll->selEnd - 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() {
+	return nextBreak;
+}
+
+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 j;
+		for (j = subBreak + 1; j <= nextBreak; j++) {
+			if (IsSpaceOrTab(ll->chars[j - 1]) && !IsSpaceOrTab(ll->chars[j])) {
+				lastGoodBreak = j;
+			}
+			if (ll->chars[j] < 'A') {
+				lastOKBreak = j;
+			}
+			if (((j - subBreak) >= lengthEachSubdivision) && ((lastGoodBreak >= 0) || (lastOKBreak >= 0))) {
+				break;
+			}
+		}
+		if (lastGoodBreak >= 0) {
+			subBreak = lastGoodBreak;
+		} else if (lastOKBreak >= 0) {
+			subBreak = lastOKBreak;
+		} 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) {
+	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);
+	}
+}

Added: trunk/plugins/scintilla/scintilla/PositionCache.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/PositionCache.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,166 @@
+// Scintilla source code edit control
+/** @file PositionCache.h
+ ** 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.
+
+#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;
+	enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
+	int xHighlightGuide;
+	bool highlightColumn;
+	int selStart;
+	int selEnd;
+	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;
+
+	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;
+};
+
+/**
+ */
+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() { 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);
+	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);
+	~BreakFinder();
+	int First();
+	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() { 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

Added: trunk/plugins/scintilla/scintilla/PropSet.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/PropSet.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,755 @@
+// 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>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// The comparison and case changing functions here assume ASCII
+// or extended ASCII such as the normal Windows code page.
+
+static inline char MakeUpperCase(char ch) {
+	if (ch < 'a' || ch > 'z')
+		return ch;
+	else
+		return static_cast<char>(ch - 'a' + 'A');
+}
+
+static inline bool IsLetter(char ch) {
+	return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
+}
+
+inline bool IsASpace(unsigned int ch) {
+    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+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;
+}
+
+bool EqualCaseInsensitive(const char *a, const char *b) {
+	return 0 == CompareCaseInsensitive(a, b);
+}
+
+// Since the CaseInsensitive functions declared in SString
+// are implemented here, I will for now put the non-inline
+// implementations of the SString members here as well, so
+// that I can quickly see what effect this has.
+
+SString::SString(int i) : sizeGrowth(sizeGrowthDefault) {
+	char number[32];
+	sprintf(number, "%0d", i);
+	s = StringAllocate(number);
+	sSize = sLen = (s) ? strlen(s) : 0;
+}
+
+SString::SString(double d, int precision) : sizeGrowth(sizeGrowthDefault) {
+	char number[32];
+	sprintf(number, "%.*f", precision, d);
+	s = StringAllocate(number);
+	sSize = sLen = (s) ? strlen(s) : 0;
+}
+
+bool SString::grow(lenpos_t lenNew) {
+	while (sizeGrowth * 6 < lenNew) {
+		sizeGrowth *= 2;
+	}
+	char *sNew = new char[lenNew + sizeGrowth + 1];
+	if (sNew) {
+		if (s) {
+			memcpy(sNew, s, sLen);
+			delete []s;
+		}
+		s = sNew;
+		s[sLen] = '\0';
+		sSize = lenNew + sizeGrowth;
+	}
+	return sNew != 0;
+}
+
+SString &SString::assign(const char *sOther, lenpos_t sSize_) {
+	if (!sOther) {
+		sSize_ = 0;
+	} else if (sSize_ == measure_length) {
+		sSize_ = strlen(sOther);
+	}
+	if (sSize > 0 && sSize_ <= sSize) {	// Does not allocate new buffer if the current is big enough
+		if (s && sSize_) {
+			memcpy(s, sOther, sSize_);
+		}
+		s[sSize_] = '\0';
+		sLen = sSize_;
+	} else {
+		delete []s;
+		s = StringAllocate(sOther, sSize_);
+		if (s) {
+			sSize = sSize_;	// Allow buffer bigger than real string, thus providing space to grow
+			sLen = sSize_;
+		} else {
+			sSize = sLen = 0;
+		}
+	}
+	return *this;
+}
+
+bool SString::operator==(const SString &sOther) const {
+	if ((s == 0) && (sOther.s == 0))
+		return true;
+	if ((s == 0) || (sOther.s == 0))
+		return false;
+	return strcmp(s, sOther.s) == 0;
+}
+
+bool SString::operator==(const char *sOther) const {
+	if ((s == 0) && (sOther == 0))
+		return true;
+	if ((s == 0) || (sOther == 0))
+		return false;
+	return strcmp(s, sOther) == 0;
+}
+
+SString SString::substr(lenpos_t subPos, lenpos_t subLen) const {
+	if (subPos >= sLen) {
+		return SString();					// return a null string if start index is out of bounds
+	}
+	if ((subLen == measure_length) || (subPos + subLen > sLen)) {
+		subLen = sLen - subPos;		// can't substr past end of source string
+	}
+	return SString(s, subPos, subPos + subLen);
+}
+
+SString &SString::lowercase(lenpos_t subPos, lenpos_t subLen) {
+	if ((subLen == measure_length) || (subPos + subLen > sLen)) {
+		subLen = sLen - subPos;		// don't apply past end of string
+	}
+	for (lenpos_t i = subPos; i < subPos + subLen; i++) {
+		if (s[i] < 'A' || s[i] > 'Z')
+			continue;
+		else
+			s[i] = static_cast<char>(s[i] - 'A' + 'a');
+	}
+	return *this;
+}
+
+SString &SString::uppercase(lenpos_t subPos, lenpos_t subLen) {
+	if ((subLen == measure_length) || (subPos + subLen > sLen)) {
+		subLen = sLen - subPos;		// don't apply past end of string
+	}
+	for (lenpos_t i = subPos; i < subPos + subLen; i++) {
+		if (s[i] < 'a' || s[i] > 'z')
+			continue;
+		else
+			s[i] = static_cast<char>(s[i] - 'a' + 'A');
+	}
+	return *this;
+}
+
+SString &SString::append(const char *sOther, lenpos_t sLenOther, char sep) {
+	if (!sOther) {
+		return *this;
+	}
+	if (sLenOther == measure_length) {
+		sLenOther = strlen(sOther);
+	}
+	int lenSep = 0;
+	if (sLen && sep) {	// Only add a separator if not empty
+		lenSep = 1;
+	}
+	lenpos_t lenNew = sLen + sLenOther + lenSep;
+	// Conservative about growing the buffer: don't do it, unless really needed
+	if ((lenNew < sSize) || (grow(lenNew))) {
+		if (lenSep) {
+			s[sLen] = sep;
+			sLen++;
+		}
+		memcpy(&s[sLen], sOther, sLenOther);
+		sLen += sLenOther;
+		s[sLen] = '\0';
+	}
+	return *this;
+}
+
+SString &SString::insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther) {
+	if (!sOther || pos > sLen) {
+		return *this;
+	}
+	if (sLenOther == measure_length) {
+		sLenOther = strlen(sOther);
+	}
+	lenpos_t lenNew = sLen + sLenOther;
+	// Conservative about growing the buffer: don't do it, unless really needed
+	if ((lenNew < sSize) || grow(lenNew)) {
+		lenpos_t moveChars = sLen - pos + 1;
+		for (lenpos_t i = moveChars; i > 0; i--) {
+			s[pos + sLenOther + i - 1] = s[pos + i - 1];
+		}
+		memcpy(s + pos, sOther, sLenOther);
+		sLen = lenNew;
+	}
+	return *this;
+}
+
+/**
+ * Remove @a len characters from the @a pos position, included.
+ * Characters at pos + len and beyond replace characters at pos.
+ * If @a len is 0, or greater than the length of the string
+ * starting at @a pos, the string is just truncated at @a pos.
+ */
+void SString::remove(lenpos_t pos, lenpos_t len) {
+	if (pos >= sLen) {
+		return;
+	}
+	if (len < 1 || pos + len >= sLen) {
+		s[pos] = '\0';
+		sLen = pos;
+	} else {
+		for (lenpos_t i = pos; i < sLen - len + 1; i++) {
+			s[i] = s[i+len];
+		}
+		sLen -= len;
+	}
+}
+
+bool SString::startswith(const char *prefix) {
+	lenpos_t lenPrefix = strlen(prefix);
+	if (lenPrefix > sLen) {
+		return false;
+	}
+	return strncmp(s, prefix, lenPrefix) == 0;
+}
+
+bool SString::endswith(const char *suffix) {
+	lenpos_t lenSuffix = strlen(suffix);
+	if (lenSuffix > sLen) {
+		return false;
+	}
+	return strncmp(s + sLen - lenSuffix, suffix, lenSuffix) == 0;
+}
+
+int SString::search(const char *sFind, lenpos_t start) const {
+	if (start < sLen) {
+		const char *sFound = strstr(s + start, sFind);
+		if (sFound) {
+			return sFound - s;
+		}
+	}
+	return -1;
+}
+
+int SString::substitute(char chFind, char chReplace) {
+	int c = 0;
+	char *t = s;
+	while (t) {
+		t = strchr(t, chFind);
+		if (t) {
+			*t = chReplace;
+			t++;
+			c++;
+		}
+	}
+	return c;
+}
+
+int SString::substitute(const char *sFind, const char *sReplace) {
+	int c = 0;
+	lenpos_t lenFind = strlen(sFind);
+	lenpos_t lenReplace = strlen(sReplace);
+	int posFound = search(sFind);
+	while (posFound >= 0) {
+		remove(posFound, lenFind);
+		insert(posFound, sReplace, lenReplace);
+		posFound = search(sFind, posFound + lenReplace);
+		c++;
+	}
+	return c;
+}
+
+char *SContainer::StringAllocate(lenpos_t len) {
+	if (len != measure_length) {
+		return new char[len + 1];
+	} else {
+		return 0;
+	}
+}
+
+char *SContainer::StringAllocate(const char *s, lenpos_t len) {
+	if (s == 0) {
+		return 0;
+	}
+	if (len == measure_length) {
+		len = strlen(s);
+	}
+	char *sNew = new char[len + 1];
+	if (sNew) {
+		memcpy(sNew, s, len);
+		sNew[len] = '\0';
+	}
+	return sNew;
+}
+
+// End SString functions
+
+PropSet::PropSet() {
+	superPS = 0;
+	for (int root = 0; root < hashRoots; root++)
+		props[root] = 0;
+}
+
+PropSet::~PropSet() {
+	superPS = 0;
+	Clear();
+}
+
+void PropSet::Set(const char *key, const char *val, int lenKey, int lenVal) {
+	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));
+	unsigned int hash = HashString(key, lenKey);
+	for (Property *p = props[hash % hashRoots]; p; p = p->next) {
+		if ((hash == p->hash) &&
+			((strlen(p->key) == static_cast<unsigned int>(lenKey)) &&
+				(0 == strncmp(p->key, key, lenKey)))) {
+			// Replace current value
+			delete [](p->val);
+			p->val = StringDup(val, lenVal);
+			return;
+		}
+	}
+	// Not found
+	Property *pNew = new Property;
+	if (pNew) {
+		pNew->hash = hash;
+		pNew->key = StringDup(key, lenKey);
+		pNew->val = StringDup(val, lenVal);
+		pNew->next = props[hash % hashRoots];
+		props[hash % hashRoots] = pNew;
+	}
+}
+
+void PropSet::Set(const char *keyVal) {
+	while (IsASpace(*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 PropSet::Unset(const char *key, int lenKey) {
+	if (!*key)	// Empty keys are not supported
+		return;
+	if (lenKey == -1)
+		lenKey = static_cast<int>(strlen(key));
+	unsigned int hash = HashString(key, lenKey);
+	Property *pPrev = NULL;
+	for (Property *p = props[hash % hashRoots]; p; p = p->next) {
+		if ((hash == p->hash) &&
+			((strlen(p->key) == static_cast<unsigned int>(lenKey)) &&
+				(0 == strncmp(p->key, key, lenKey)))) {
+			if (pPrev)
+				pPrev->next = p->next;
+			else
+				props[hash % hashRoots] = p->next;
+			if (p == enumnext)
+				enumnext = p->next; // Not that anyone should mix enum and Set / Unset.
+			delete [](p->key);
+			delete [](p->val);
+			delete p;
+			return;
+		} else {
+			pPrev = p;
+		}
+	}
+}
+
+void PropSet::SetMultiple(const char *s) {
+	const char *eol = strchr(s, '\n');
+	while (eol) {
+		Set(s);
+		s = eol + 1;
+		eol = strchr(s, '\n');
+	}
+	Set(s);
+}
+
+SString PropSet::Get(const char *key) const {
+	unsigned int hash = HashString(key, strlen(key));
+	for (Property *p = props[hash % hashRoots]; p; p = p->next) {
+		if ((hash == p->hash) && (0 == strcmp(p->key, key))) {
+			return p->val;
+		}
+	}
+	if (superPS) {
+		// Failed here, so try in base property set
+		return superPS->Get(key);
+	} 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 PropSet &props, SString &withVars, int maxExpands, const VarChain &blankVars = VarChain()) {
+	int varStart = withVars.search("$(");
+	while ((varStart >= 0) && (maxExpands > 0)) {
+		int varEnd = withVars.search(")", varStart+2);
+		if (varEnd < 0) {
+			break;
+		}
+
+		// For consistency, when we see '$(ab$(cde))', expand the inner variable first,
+		// regardless whether there is actually a degenerate variable named 'ab$(cde'.
+		int innerVarStart = withVars.search("$(", varStart+2);
+		while ((innerVarStart > varStart) && (innerVarStart < varEnd)) {
+			varStart = innerVarStart;
+			innerVarStart = withVars.search("$(", varStart+2);
+		}
+
+		SString var(withVars.c_str(), varStart + 2, varEnd);
+		SString val = props.Get(var.c_str());
+
+		if (blankVars.contains(var.c_str())) {
+			val.clear(); // 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.remove(varStart, varEnd-varStart+1);
+		withVars.insert(varStart, val.c_str(), val.length());
+
+		varStart = withVars.search("$(");
+	}
+
+	return maxExpands;
+}
+
+SString PropSet::GetExpanded(const char *key) const {
+	SString val = Get(key);
+	ExpandAllInPlace(*this, val, 100, VarChain(key));
+	return val;
+}
+
+SString PropSet::Expand(const char *withVars, int maxExpands) const {
+	SString val = withVars;
+	ExpandAllInPlace(*this, val, maxExpands);
+	return val;
+}
+
+int PropSet::GetInt(const char *key, int defaultValue) const {
+	SString val = GetExpanded(key);
+	if (val.length())
+		return val.value();
+	return defaultValue;
+}
+
+bool isprefix(const char *target, const char *prefix) {
+	while (*target && *prefix) {
+		if (*target != *prefix)
+			return false;
+		target++;
+		prefix++;
+	}
+	if (*prefix)
+		return false;
+	else
+		return true;
+}
+
+void PropSet::Clear() {
+	for (int root = 0; root < hashRoots; root++) {
+		Property *p = props[root];
+		while (p) {
+			Property *pNext = p->next;
+			p->hash = 0;
+			delete []p->key;
+			p->key = 0;
+			delete []p->val;
+			p->val = 0;
+			delete p;
+			p = pNext;
+		}
+		props[root] = 0;
+	}
+}
+
+char *PropSet::ToString() const {
+	size_t len=0;
+	for (int r = 0; r < hashRoots; r++) {
+		for (Property *p = props[r]; p; p = p->next) {
+			len += strlen(p->key) + 1;
+			len += strlen(p->val) + 1;
+		}
+	}
+	if (len == 0)
+		len = 1;	// Return as empty string
+	char *ret = new char [len];
+	if (ret) {
+		char *w = ret;
+		for (int root = 0; root < hashRoots; root++) {
+			for (Property *p = props[root]; p; p = p->next) {
+				strcpy(w, p->key);
+				w += strlen(p->key);
+				*w++ = '=';
+				strcpy(w, p->val);
+				w += strlen(p->val);
+				*w++ = '\n';
+			}
+		}
+		ret[len-1] = '\0';
+	}
+	return ret;
+}
+
+/**
+ * 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 = StringDup(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;
+}

Added: trunk/plugins/scintilla/scintilla/RESearch.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/RESearch.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,982 @@
+// 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 "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) {
+	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));
+			}
+		}
+	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;
+}
+

Added: trunk/plugins/scintilla/scintilla/RESearch.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/RESearch.h	Wed Apr  8 20:49:12 2009
@@ -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
+

Added: trunk/plugins/scintilla/scintilla/RunStyles.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/RunStyles.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+	}
+}
+

Added: trunk/plugins/scintilla/scintilla/RunStyles.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/RunStyles.h	Wed Apr  8 20:49:12 2009
@@ -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

Added: trunk/plugins/scintilla/scintilla/SVector.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/SVector.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,135 @@
+// 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
+	bool allocFailure;	///< A memory allocation call has failed
+	
+	/** 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];
+		if (!newv) {
+			allocFailure = true;
+			return;
+		}
+		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() {
+		allocFailure = false;
+		v = 0;
+		len = 0;
+		size = 0;
+	}
+	~SVector() {
+		Free();
+	}
+	/// Constructor from another vector.
+	SVector(const SVector &other) {
+		allocFailure = false;
+		v = 0;
+		len = 0;
+		size = 0;
+		if (other.Length() > 0) {
+			SizeTo(other.Length());
+			if (!allocFailure) {
+				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;
+			allocFailure = false;
+			v = 0;
+			len = 0;
+			size = 0;
+			if (other.Length() > 0) {
+				SizeTo(other.Length());
+				if (!allocFailure) {
+					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

Added: trunk/plugins/scintilla/scintilla/ScintillaBase.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ScintillaBase.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,745 @@
+// 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 "Platform.h"
+
+#include "Scintilla.h"
+#include "PropSet.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 "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 (currentPos <= 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(currentPos - lenEntered);
+				pdoc->DeleteChars(currentPos, lenEntered);
+				SetEmptySelection(currentPos);
+				pdoc->InsertString(currentPos, list, lenInsert);
+				SetEmptySelection(currentPos + lenInsert);
+			} else {
+				SetEmptySelection(currentPos);
+				pdoc->InsertString(currentPos, list + lenEntered, lenInsert - lenEntered);
+				SetEmptySelection(currentPos + lenInsert - lenEntered);
+			}
+			return;
+		}
+	}
+	ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos),
+				lenEntered, vs.lineHeight, IsUnicodeMode());
+
+	PRectangle rcClient = GetClientRectangle();
+	Point pt = LocationFromPosition(currentPos - 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 = LocationFromPosition(currentPos);
+	}
+	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 < currentPos && 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 (currentPos < ac.posStart - ac.startLen) {
+		AutoCompleteCancel();
+	} else if (ac.cancelAtStartPos && (currentPos <= ac.posStart)) {
+		AutoCompleteCancel();
+	} else {
+		AutoCompleteMoveToCurrentWord();
+	}
+}
+
+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);
+
+	listSelected = selected;
+	SCNotification scn = {0};
+	scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
+	scn.message = 0;
+	scn.wParam = listType;
+	scn.listType = listType;
+	Position firstPos = ac.posStart - ac.startLen;
+	scn.lParam = firstPos;
+	scn.text = listSelected.c_str();
+	NotifyParent(scn);
+
+	if (!ac.Active())
+		return;
+	ac.Cancel();
+
+	if (listType > 0)
+		return;
+
+	Position endPos = currentPos;
+	if (ac.dropRestOfWord)
+		endPos = pdoc->ExtendWordSelect(endPos, 1, true);
+	if (endPos < firstPos)
+		return;
+	pdoc->BeginUndoAction();
+	if (endPos != firstPos) {
+		pdoc->DeleteChars(firstPos, endPos - firstPos);
+	}
+	SetEmptySelection(ac.posStart);
+	if (item != -1) {
+		SString piece = selected;
+		pdoc->InsertCString(firstPos, piece.c_str());
+		SetEmptySelection(firstPos + static_cast<int>(piece.length()));
+	}
+	pdoc->EndUndoAction();
+}
+
+int ScintillaBase::AutoCompleteGetCurrent() {
+	return ac.lb->GetSelection();
+}
+
+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(currentPos, 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 && currentPos != anchor);
+		AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
+		AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0));
+		AddToPopUp("Delete", idcmdDelete, writable && currentPos != anchor);
+		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);
+}
+
+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();
+}
+
+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_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: {
+			SString val = props.Get(reinterpret_cast<const char *>(wParam));
+			const int n = val.length();
+			if (lParam != 0) {
+				char *ptr = reinterpret_cast<char *>(lParam);
+				memcpy(ptr, val.c_str(), n);
+				ptr[n] = '\0';	// terminate
+			}
+			return n;	// Not including NUL
+		}
+
+	case SCI_GETPROPERTYEXPANDED: {
+			SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
+			const int n = val.length();
+			if (lParam != 0) {
+				char *ptr = reinterpret_cast<char *>(lParam);
+				memcpy(ptr, val.c_str(), n);
+				ptr[n] = '\0';	// terminate
+			}
+			return n;	// Not including NUL
+		}
+
+	case SCI_GETPROPERTYINT:
+		return props.GetInt(reinterpret_cast<const char *>(wParam), lParam);
+
+	case SCI_SETKEYWORDS:
+		if (wParam < numWordLists) {
+			keyWordLists[wParam]->Clear();
+			keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
+		}
+		break;
+
+	case SCI_SETLEXERLANGUAGE:
+		SetLexerLanguage(reinterpret_cast<const char *>(lParam));
+		break;
+
+	case SCI_GETSTYLEBITSNEEDED:
+		return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
+#endif
+
+	default:
+		return Editor::WndProc(iMessage, wParam, lParam);
+	}
+	return 0l;
+}

Added: trunk/plugins/scintilla/scintilla/ScintillaBase.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ScintillaBase.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,101 @@
+// 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 &) : Editor() {}
+	ScintillaBase &operator=(const ScintillaBase &) { return *this; }
+
+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
+	SString listSelected;	///< Receives listbox selected string
+	int maxListWidth;		/// Maximum width of list, in average character widths
+
+	bool performingStyle;	///< Prevent reentrance
+
+#ifdef SCI_LEXER
+	int lexLanguage;
+	const LexerModule *lexCurrent;
+	PropSet 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();
+	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

Added: trunk/plugins/scintilla/scintilla/ScintillaGTK.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ScintillaGTK.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,2714 @@
+// 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#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 "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 "PositionCache.h"
+#include "Editor.h"
+#include "SString.h"
+#include "ScintillaBase.h"
+#include "UniConversion.h"
+
+#include "gtk/gtksignal.h"
+#include "gtk/gtkmarshal.h"
+#if GLIB_MAJOR_VERSION >= 2
+#include "scintilla-marshal.h"
+#endif
+
+#ifdef SCI_LEXER
+#include <glib.h>
+#include <gmodule.h>
+#include "ExternalLexer.h"
+#endif
+
+#define INTERNATIONAL_INPUT
+
+#if !PLAT_GTK_WIN32 || GTK_MAJOR_VERSION >= 2
+#define USE_CONVERTER
+#endif
+
+#ifdef USE_CONVERTER
+#include "Converter.h"
+#endif
+
+#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
+
+#if GLIB_MAJOR_VERSION < 2
+#define OBJECT_CLASS GtkObjectClass
+#else
+#define OBJECT_CLASS GObjectClass
+#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;
+
+	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
+
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	// Input context used for supporting internationalized key entry
+	GdkIC *ic;
+	GdkICAttr *ic_attr;
+#else
+	Window wPreedit;
+	Window wPreeditDraw;
+	GtkIMContext *im_context;
+#endif
+#endif
+
+	// 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 &) : ScintillaBase() {}
+	ScintillaGTK &operator=(const ScintillaGTK &) { return * this; }
+
+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 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);
+	static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
+	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);
+#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
+	static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
+#endif
+	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);
+#if GTK_MAJOR_VERSION >= 2
+	static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
+	gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
+	static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
+	void CommitThis(char *str);
+	static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
+	void PreeditChangedThis();
+#endif
+	static gint StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
+	static gint RealizeText(GtkWidget *widget, void*);
+#if GLIB_MAJOR_VERSION < 2
+	static void Destroy(GtkObject *object);
+#else
+	static void Destroy(GObject *object);
+#endif
+	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);
+#if GTK_MAJOR_VERSION < 2
+	static gint SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event);
+#endif
+	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 gint IdleCallback(ScintillaGTK *sciThis);
+	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 };
+#if GLIB_MAJOR_VERSION < 2
+static GtkWidgetClass *parent_class = NULL;
+#endif
+
+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), parentClass(0),
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+		ic(NULL),
+		ic_attr(NULL),
+#else
+		im_context(NULL),
+#endif
+#endif
+		lastWheelMouseDirection(0),
+		wheelMouseIntensity(0),
+		rgnUpdate(0) {
+	sci = sci_;
+	wMain = GTK_WIDGET(sci);
+
+#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);
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	if (gdk_im_ready() && (ic_attr = gdk_ic_attr_new()) != NULL) {
+		gint width, height;
+		GdkColormap *colormap;
+		GdkEventMask mask;
+		GdkICAttr *attr = ic_attr;
+		GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
+		GdkIMStyle style;
+		GdkIMStyle supported_style = (GdkIMStyle) (GDK_IM_PREEDIT_NONE |
+		                             GDK_IM_PREEDIT_NOTHING |
+		                             GDK_IM_PREEDIT_POSITION |
+		                             GDK_IM_STATUS_NONE |
+		                             GDK_IM_STATUS_NOTHING);
+
+		if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+			supported_style = (GdkIMStyle) ((int) supported_style & ~GDK_IM_PREEDIT_POSITION);
+
+		attr->style = style = gdk_im_decide_style(supported_style);
+		attr->client_window = widget->window;
+
+		if ((colormap = gtk_widget_get_colormap (widget)) != gtk_widget_get_default_colormap ()) {
+			attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_COLORMAP);
+			attr->preedit_colormap = colormap;
+		}
+
+		switch (style & GDK_IM_PREEDIT_MASK) {
+		case GDK_IM_PREEDIT_POSITION:
+			if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)	{
+				g_warning("over-the-spot style requires fontset");
+				break;
+			}
+
+			attrmask = (GdkICAttributesType) ((int) attrmask | GDK_IC_PREEDIT_POSITION_REQ);
+			gdk_window_get_size(widget->window, &width, &height);
+			attr->spot_location.x = 0;
+			attr->spot_location.y = height;
+			attr->preedit_area.x = 0;
+			attr->preedit_area.y = 0;
+			attr->preedit_area.width = width;
+			attr->preedit_area.height = height;
+			attr->preedit_fontset = widget->style->font;
+
+			break;
+		}
+		ic = gdk_ic_new(attr, attrmask);
+
+		if (ic == NULL) {
+			g_warning("Can't create input context.");
+		} else {
+			mask = gdk_window_get_events(widget->window);
+			mask = (GdkEventMask) ((int) mask | gdk_ic_get_events(ic));
+			gdk_window_set_events(widget->window, mask);
+
+			if (GTK_WIDGET_HAS_FOCUS(widget))
+				gdk_im_begin(ic, widget->window);
+		}
+	}
+#else
+	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);
+#endif
+#endif
+	GtkWidget *widtxt = PWidget(wText);	//	// No code inside the G_OBJECT macro
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_connect_after(GTK_OBJECT(widtxt), "style_set",
+				 GtkSignalFunc(ScintillaGTK::StyleSetText), NULL);
+	gtk_signal_connect_after(GTK_OBJECT(widtxt), "realize",
+				 GtkSignalFunc(ScintillaGTK::RealizeText), NULL);
+#else
+	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);
+#endif
+	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) {
+	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));
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	if (ic) {
+		gdk_ic_destroy(ic);
+		ic = NULL;
+	}
+	if (ic_attr) {
+		gdk_ic_attr_destroy(ic_attr);
+		ic_attr = NULL;
+	}
+#else
+	gtk_widget_unrealize(PWidget(wPreedit));
+	gtk_widget_unrealize(PWidget(wPreeditDraw));
+	g_object_unref(im_context);
+	im_context = NULL;
+#endif
+#endif
+	if (GTK_WIDGET_CLASS(parentClass)->unrealize)
+		GTK_WIDGET_CLASS(parentClass)->unrealize(widget);
+
+	Finalise();
+}
+
+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() {
+	//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);
+}
+
+void ScintillaGTK::Map(GtkWidget *widget) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	sciThis->MapThis();
+}
+
+void ScintillaGTK::UnMapThis() {
+	//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));
+}
+
+void ScintillaGTK::UnMap(GtkWidget *widget) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	sciThis->UnMapThis();
+}
+
+void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) {
+	(*callback) (PWidget(wText), callback_data);
+	(*callback) (PWidget(scrollbarv), callback_data);
+	(*callback) (PWidget(scrollbarh), callback_data);
+}
+
+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);
+	}
+}
+
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+gint ScintillaGTK::CursorMoved(GtkWidget *widget, int xoffset, int yoffset, ScintillaGTK *sciThis) {
+	if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && sciThis->ic &&
+	        (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
+		sciThis->ic_attr->spot_location.x = xoffset;
+		sciThis->ic_attr->spot_location.y = yoffset;
+		gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_SPOT_LOCATION);
+	}
+	return FALSE;
+}
+#else
+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;
+}
+#endif
+#else
+gint ScintillaGTK::CursorMoved(GtkWidget *, int, int, ScintillaGTK *) {
+	return FALSE;
+}
+#endif
+
+gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	//Platform::DebugPrintf("ScintillaGTK::focus in %x\n", sciThis);
+	GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+	sciThis->SetFocusState(true);
+
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	if (sciThis->ic)
+		gdk_im_begin(sciThis->ic, widget->window);
+#else
+	if (sciThis->im_context != NULL) {
+		gchar *str = NULL;
+		gint cursor_pos;
+
+		gtk_im_context_get_preedit_string(sciThis->im_context, &str, NULL, &cursor_pos);
+		if (PWidget(sciThis->wPreedit) != NULL) {
+			if (strlen(str) > 0) {
+				gtk_widget_show(PWidget(sciThis->wPreedit));
+			} else {
+				gtk_widget_hide(PWidget(sciThis->wPreedit));
+			}
+		}
+		g_free(str);
+		gtk_im_context_focus_in(sciThis->im_context);
+	}
+#endif
+#endif
+
+	return FALSE;
+}
+
+gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	//Platform::DebugPrintf("ScintillaGTK::focus out %x\n", sciThis);
+	GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+	sciThis->SetFocusState(false);
+
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	gdk_im_end();
+#else
+	if (PWidget(sciThis->wPreedit) != NULL)
+		gtk_widget_hide(PWidget(sciThis->wPreedit));
+	if (sciThis->im_context != NULL)
+		gtk_im_context_focus_out(sciThis->im_context);
+#endif
+#endif
+
+	return FALSE;
+}
+
+void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) {
+	requisition->width = 600;
+	requisition->height = gdk_screen_height();
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	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) {
+	widget->allocation = *allocation;
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	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);
+
+#ifdef INTERNATIONAL_INPUT
+#if GTK_MAJOR_VERSION < 2
+	if (sciThis->ic && (gdk_ic_get_style(sciThis->ic) & GDK_IM_PREEDIT_POSITION)) {
+		gint width, height;
+
+		gdk_window_get_size(widget->window, &width, &height);
+		sciThis->ic_attr->preedit_area.width = width;
+		sciThis->ic_attr->preedit_area.height = height;
+
+		gdk_ic_set_attr(sciThis->ic, sciThis->ic_attr, GDK_IC_PREEDIT_AREA);
+	}
+#endif
+#endif
+}
+
+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);
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_connect(GTK_OBJECT(widtxt), "expose_event",
+			   GtkSignalFunc(ScintillaGTK::ExposeText), this);
+#else
+	g_signal_connect(G_OBJECT(widtxt), "expose_event",
+			   G_CALLBACK(ScintillaGTK::ExposeText), this);
+#endif
+	gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
+#if GTK_MAJOR_VERSION >= 2
+	// Avoid background drawing flash
+	gtk_widget_set_double_buffered(widtxt, FALSE);
+#endif
+	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);
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_connect(adjustmentv, "value_changed",
+			   GtkSignalFunc(ScrollSignal), this);
+#else
+	g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
+			   G_CALLBACK(ScrollSignal), this);
+#endif
+	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);
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_connect(adjustmenth, "value_changed",
+			   GtkSignalFunc(ScrollHSignal), this);
+#else
+	g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
+			   G_CALLBACK(ScrollHSignal), this);
+#endif
+	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));
+
+#if GLIB_MAJOR_VERSION >= 2
+	// 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;
+	}
+#endif
+
+	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) {
+#if GTK_MAJOR_VERSION < 2
+	return Editor::DragThreshold(ptStart, ptNow);
+#else
+	return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
+		ptStart.x, ptStart.y, ptNow.x, ptNow.y);
+#endif
+}
+
+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));
+}
+
+#ifdef USE_CONVERTER
+static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
+	const char *charSetSource, bool transliterations) {
+	*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))) {
+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;
+}
+#endif
+
+// 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
+#ifdef USE_CONVERTER
+		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);
+			}
+		}
+#else
+		// Fail
+		return 0;
+#endif
+	}
+//~ 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
+#ifdef USE_CONVERTER
+		const char *charSetBuffer = CharacterSetID();
+		if (*charSetBuffer) {
+//~ fprintf(stderr, "Encode %s %d\n", charSetBuffer, inputLength);
+			int outLength = 0;
+			char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
+			if (tmpEncoded) {
+//~ fprintf(stderr, "    \"%s\"\n", tmpEncoded);
+				if (encoded) {
+					memcpy(encoded, tmpEncoded, outLength);
+				}
+				delete []tmpEncoded;
+			}
+			return outLength;
+		} else {
+			if (encoded) {
+				memcpy(encoded, utf8, inputLength);
+			}
+			return inputLength;
+		}
+#endif
+	}
+	// Fail
+	return 0;
+}
+
+bool ScintillaGTK::ValidCodePage(int codePage) const {
+	return codePage == 0 || codePage == SC_CP_UTF8 || codePage == SC_CP_DBCS;
+}
+
+sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+	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*>(wParam));
+		break;
+#endif
+	case SCI_TARGETASUTF8:
+		return TargetAsUTF8(reinterpret_cast<char*>(lParam));
+
+	case SCI_ENCODEDFROMUTF8:
+		return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
+			reinterpret_cast<char*>(lParam));
+
+	default:
+		return ScintillaBase::WndProc(iMessage, wParam, lParam);
+	}
+	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 == false) {
+			idler.state = true;
+			idler.idlerID = reinterpret_cast<IdlerID>
+				(gtk_idle_add((GtkFunction)IdleCallback, this));
+		}
+	} else {
+		// Stop idler, if it's running
+		if (idler.state == true) {
+			idler.state = false;
+			gtk_idle_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() {
+#if GTK_MAJOR_VERSION < 2
+	paintState = painting;
+	rcPaint = GetClientRectangle();
+	//Platform::DebugPrintf("ScintillaGTK::FullPaint %0d,%0d %0d,%0d\n",
+	//	rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom);
+	paintingAllText = true;
+	if ((PWidget(wText))->window) {
+		Surface *sw = Surface::Allocate();
+		if (sw) {
+			sw->Init(PWidget(wText)->window, PWidget(wText));
+			Paint(sw, rcPaint);
+			sw->Release();
+			delete sw;
+		}
+	}
+	paintState = notPainting;
+#else
+	wText.InvalidateAll();
+#endif
+}
+
+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);
+
+#if GTK_MAJOR_VERSION < 2
+	PRectangle rc = GetClientRectangle();
+	GdkGC *gc = gdk_gc_new(wi->window);
+
+	// Set up gc so we get GraphicsExposures from gdk_draw_pixmap
+	//  which calls XCopyArea
+	gdk_gc_set_exposures(gc, TRUE);
+
+	// Redraw exposed bit : scrolling upwards
+	if (diff > 0) {
+		gdk_draw_pixmap(wi->window,
+		                gc, wi->window,
+		                0, diff,
+		                0, 0,
+		                rc.Width()-1, rc.Height() - diff);
+		SyncPaint(PRectangle(0, rc.Height() - diff,
+		                     rc.Width(), rc.Height()+1));
+
+	// Redraw exposed bit : scrolling downwards
+	} else {
+		gdk_draw_pixmap(wi->window,
+		                gc, wi->window,
+		                0, 0,
+		                0, -diff,
+		                rc.Width()-1, rc.Height() + diff);
+		SyncPaint(PRectangle(0, 0, rc.Width(), -diff));
+	}
+
+	// Look for any graphics expose
+	GdkEvent* event;
+	while ((event = gdk_event_get_graphics_expose(wi->window)) != NULL) {
+		gtk_widget_event(wi, event);
+		if (event->expose.count == 0) {
+			gdk_event_free(event);
+			break;
+		}
+		gdk_event_free(event);
+	}
+
+	gdk_gc_unref(gc);
+#else
+	gdk_window_scroll(wi->window, 0, -diff);
+	gdk_window_process_updates(wi->window, FALSE);
+#endif
+}
+
+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() {
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
+	                Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
+#else
+	g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
+	                Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
+#endif
+}
+
+void ScintillaGTK::NotifyFocus(bool focus) {
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL],
+	                Platform::LongFromTwoShorts
+					(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
+#else
+	g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
+	                Platform::LongFromTwoShorts
+					(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
+#endif
+}
+
+void ScintillaGTK::NotifyParent(SCNotification scn) {
+	scn.nmhdr.hwndFrom = PWidget(wMain);
+	scn.nmhdr.idFrom = GetCtrlID();
+#if GLIB_MAJOR_VERSION < 2
+	gtk_signal_emit(GTK_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL],
+	                GetCtrlID(), &scn);
+#else
+	g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
+	                GetCtrlID(), &scn);
+#endif
+}
+
+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);
+}
+
+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 (currentPos != anchor) {
+#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 (selType == selRectangle) {
+			::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);
+#if GLIB_MAJOR_VERSION < 2
+		gtk_signal_connect(GTK_OBJECT(widcdrw), "expose_event",
+				   GtkSignalFunc(ScintillaGTK::ExposeCT), &ct);
+		gtk_signal_connect(GTK_OBJECT(widcdrw), "button_press_event",
+				   GtkSignalFunc(ScintillaGTK::PressCT), static_cast<void *>(this));
+#else
+		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));
+#endif
+		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>"),
+#if GTK_MAJOR_VERSION >= 2
+	    NULL
+#endif
+	};
+	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 (currentPos != anchor && 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'));
+#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);
+#ifdef USE_CONVERTER
+		const char *charSetBuffer = CharacterSetID();
+		if (!IsUnicodeMode() && *charSetBuffer) {
+//fprintf(stderr, "Convert to locale %s\n", CharacterSetID());
+				// 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);
+		}
+#endif
+	}
+}
+
+void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
+	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);
+
+			pdoc->BeginUndoAction();
+			if (selection_data->selection != GDK_SELECTION_PRIMARY) {
+				ClearSelection();
+			}
+			int selStart = SelectionStart();
+
+			if (selText.rectangular) {
+				PasteRectangular(selStart, selText.s, selText.len);
+			} else {
+				pdoc->InsertString(currentPos, selText.s, selText.len);
+				SetEmptySelection(currentPos + selText.len);
+			}
+			pdoc->EndUndoAction();
+			EnsureCaretVisible();
+		}
+	}
+//	else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
+//		(int)(atomUTF8));
+	Redraw();
+}
+
+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
+
+#if GTK_MAJOR_VERSION >= 2
+	// 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)
+	int len = strlen(text->s);
+#if PLAT_GTK_WIN32 == 0
+	if (text->rectangular)
+		len++;
+#endif
+
+	if (info == TARGET_UTF8_STRING) {
+		gtk_selection_data_set_text(selection_data, text->s, len);
+	} else {
+		gtk_selection_data_set(selection_data,
+			static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
+			8, reinterpret_cast<unsigned char *>(text->s), len);
+	}
+	delete converted;
+
+#else /* Gtk 1 */
+	char *selBuffer = text->s;
+
+	char *tmputf = 0;
+	if ((info == TARGET_UTF8_STRING) || (info == TARGET_STRING)) {
+		int len = strlen(selBuffer);
+#ifdef USE_CONVERTER
+		// Possible character set conversion
+		const char *charSetBuffer = ::CharacterSetID(text->characterSet);
+		if (info == TARGET_UTF8_STRING) {
+			//fprintf(stderr, "Copy to clipboard as UTF-8\n");
+			if (text->codePage != SC_CP_UTF8) {
+				// Convert to UTF-8
+	//fprintf(stderr, "Convert to UTF-8 from %s\n", charSetBuffer);
+				tmputf = ConvertText(&len, selBuffer, len, "UTF-8", charSetBuffer, false);
+				selBuffer = tmputf;
+			}
+		} else if (info == TARGET_STRING) {
+			if (text->codePage == SC_CP_UTF8) {
+	//fprintf(stderr, "Convert to locale %s\n", charSetBuffer);
+				// Convert to locale
+				tmputf = ConvertText(&len, selBuffer, len, charSetBuffer, "UTF-8", true);
+				selBuffer = tmputf;
+			}
+		}
+#endif
+
+		// 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)
+#if PLAT_GTK_WIN32 == 0
+		if (text->rectangular)
+			len++;
+#endif
+		gtk_selection_data_set(selection_data,
+					(info == TARGET_STRING) ?
+					static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING) : atomUTF8,
+		                       8, reinterpret_cast<unsigned char *>(selBuffer),
+		                       len);
+	} else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT)) {
+		guchar *text;
+		GdkAtom encoding;
+		gint format;
+		gint new_length;
+
+		gdk_string_to_compound_text(reinterpret_cast<char *>(selBuffer),
+		                            &encoding, &format, &text, &new_length);
+		gtk_selection_data_set(selection_data, encoding, format, text, new_length);
+		gdk_free_compound_text(text);
+	}
+
+	delete []tmputf;
+#endif /* Gtk >= 2 */
+
+#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) {
+	//Platform::DebugPrintf("UnclaimSelection\n");
+	if (selection_event->selection == GDK_SELECTION_PRIMARY) {
+		//Platform::DebugPrintf("UnclaimPrimarySelection\n");
+		if (!OwnPrimarySelection()) {
+			primary.Free();
+			primarySelection = false;
+			FullPaint();
+		}
+	}
+}
+
+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;
+	int verticalScrollBarHeight = scrollBarWidth;
+	if (!verticalScrollBarVisible)
+		verticalScrollBarHeight = 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);
+}
+
+gint ScintillaGTK::PressThis(GdkEventButton *event) {
+	//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 control instead of alt
+		// This is because most X window managers grab alt + click for moving
+#if !PLAT_GTK_WIN32
+		ButtonDown(pt, event->time,
+				    (event->state & GDK_SHIFT_MASK) != 0,
+				    (event->state & GDK_CONTROL_MASK) != 0,
+				    (event->state & GDK_CONTROL_MASK) != 0);
+#else
+		ButtonDown(pt, event->time,
+				    (event->state & GDK_SHIFT_MASK) != 0,
+				    (event->state & GDK_CONTROL_MASK) != 0,
+				    (event->state & GDK_MOD1_MASK) != 0);
+#endif
+	} else if (event->button == 2) {
+		// Grab the primary selection if it exists
+		Position pos = PositionFromLocation(pt);
+		if (OwnPrimarySelection() && primary.s == NULL)
+			CopySelectionRange(&primary);
+
+		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);
+	}
+#if GTK_MAJOR_VERSION >= 2
+	return TRUE;
+#else
+	return FALSE;
+#endif
+}
+
+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);
+	//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);
+	}
+	return FALSE;
+}
+
+// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
+// button4/5/6/7 events to the GTK app
+#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
+gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
+                               GdkEventScroll *event) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+
+	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;
+}
+#endif
+
+gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	//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);
+	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) {
+	//fprintf(stderr, "SC-key: %d %x [%s]\n",
+	//	event->keyval, event->state, (event->length > 0) ? event->string : "empty");
+#if GTK_MAJOR_VERSION >= 2
+	if (gtk_im_context_filter_keypress(im_context, event)) {
+		return 1;
+	}
+#endif
+	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);
+#if GTK_MAJOR_VERSION < 2
+	else if (!IsUnicodeMode() && (key >= 0x100) && (key < 0x1000))
+		key &= 0xff;
+#endif
+
+	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;
+}
+
+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;
+}
+
+#if GTK_MAJOR_VERSION >= 2
+gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
+	return sciThis->ExposePreeditThis(widget, ose);
+}
+
+gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
+	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);
+	return TRUE;
+}
+
+void ScintillaGTK::Commit(GtkIMContext *, char  *str, ScintillaGTK *sciThis) {
+	sciThis->CommitThis(str);
+}
+
+void ScintillaGTK::CommitThis(char *utfVal) {
+	//~ 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);
+				}
+			}
+		}
+	}
+}
+
+void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
+	sciThis->PreeditChangedThis();
+}
+
+void ScintillaGTK::PreeditChangedThis() {
+	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 = LocationFromPosition(currentPos);
+		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);
+}
+#endif
+
+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;
+}
+
+#if GLIB_MAJOR_VERSION < 2
+void ScintillaGTK::Destroy(GtkObject *object)
+#else
+void ScintillaGTK::Destroy(GObject *object)
+#endif
+{
+	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();
+
+#if GLIB_MAJOR_VERSION < 2
+	if (GTK_OBJECT_CLASS(parent_class)->destroy)
+		(* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
+#else
+	// IS ANYTHING NEEDED ?
+#endif
+
+	delete sciThis;
+	scio->pscin = 0;
+}
+
+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);
+	//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);
+	}
+
+#ifdef INTERNATIONAL_INPUT
+	Point pt = sciThis->LocationFromPosition(sciThis->currentPos);
+	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);
+#endif
+}
+
+gint ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) {
+	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);
+#if GTK_MAJOR_VERSION >= 2
+	rgnUpdate = gdk_region_copy(ose->region);
+#endif
+	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;
+
+	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) {
+	//fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
+	//ose->area.x, ose->area.y, ose->area.width, ose->area.height);
+
+#if GTK_MAJOR_VERSION < 2
+
+	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;
+
+	PRectangle rcClient = GetClientRectangle();
+	paintingAllText = rcPaint.Contains(rcClient);
+	Surface *surfaceWindow = Surface::Allocate();
+	if (surfaceWindow) {
+		surfaceWindow->Init(PWidget(wMain)->window, PWidget(wMain));
+
+		// Fill the corner between the scrollbars
+		if (verticalScrollBarVisible) {
+			if (horizontalScrollBarVisible && (wrapState == eWrapNone)) {
+				PRectangle rcCorner = wMain.GetClientPosition();
+				rcCorner.left = rcCorner.right - scrollBarWidth + 1;
+				rcCorner.top = rcCorner.bottom - scrollBarHeight + 1;
+				//fprintf(stderr, "Corner %0d,%0d %0d,%0d\n",
+				//rcCorner.left, rcCorner.top, rcCorner.right, rcCorner.bottom);
+				surfaceWindow->FillRectangle(rcCorner,
+					vs.styles[STYLE_LINENUMBER].back.allocated);
+			}
+		}
+
+		//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;
+
+#else
+	// For GTK+ 2, 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);
+#endif
+
+	return FALSE;
+}
+
+void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
+	sciThis->ScrollTo(static_cast<int>(adj->value), false);
+}
+
+void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
+	sciThis->HorizontalScrollTo(static_cast<int>(adj->value * 2));
+}
+
+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);
+	//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
+}
+
+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);
+}
+
+#if GTK_MAJOR_VERSION < 2
+gint ScintillaGTK::SelectionNotify(GtkWidget *widget, GdkEventSelection *selection_event) {
+	//Platform::DebugPrintf("Selection notify\n");
+	return gtk_selection_notify(widget, selection_event);
+}
+#endif
+
+void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
+	//Platform::DebugPrintf("DragBegin\n");
+}
+
+gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
+                                 gint x, gint y, guint dragtime) {
+	Point npt(x, y);
+	SetDragPosition(PositionFromLocation(npt));
+	GdkDragAction preferredAction = context->suggested_action;
+	int pos = PositionFromLocation(npt);
+	if ((inDragDrop == ddDragging) && (0 == PositionInSelection(pos))) {
+		// 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);
+	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);
+	sciThis->SetDragPosition(invalidPosition);
+	//Platform::DebugPrintf("DragLeave %x\n", sciThis);
+}
+
+void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	// If drag did not result in drop here or elsewhere
+	if (!sciThis->dragWasDropped)
+		sciThis->SetEmptySelection(sciThis->posDrag);
+	sciThis->SetDragPosition(invalidPosition);
+	//Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
+	sciThis->inDragDrop = ddNone;
+}
+
+gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/,
+                            gint, gint, guint) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	//Platform::DebugPrintf("Drop %x\n", sciThis);
+	sciThis->SetDragPosition(invalidPosition);
+	return FALSE;
+}
+
+void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/,
+                                    gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	sciThis->ReceivedDrop(selection_data);
+	sciThis->SetDragPosition(invalidPosition);
+}
+
+void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
+                               GtkSelectionData *selection_data, guint info, guint) {
+	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
+	sciThis->dragWasDropped = true;
+	if (sciThis->currentPos != sciThis->anchor) {
+		sciThis->GetSelection(selection_data, info, &sciThis->drag);
+	}
+	if (context->action == GDK_ACTION_MOVE) {
+		int selStart = sciThis->SelectionStart();
+		int selEnd = sciThis->SelectionEnd();
+		if (sciThis->posDrop > selStart) {
+			if (sciThis->posDrop > selEnd)
+				sciThis->posDrop = sciThis->posDrop - (selEnd - selStart);
+			else
+				sciThis->posDrop = selStart;
+			sciThis->posDrop = sciThis->pdoc->ClampPositionIntoDocument(sciThis->posDrop);
+		}
+		sciThis->ClearSelection();
+	}
+	sciThis->SetDragPosition(invalidPosition);
+}
+
+int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
+	sciThis->Tick();
+	return 1;
+}
+
+int ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
+	// Idler will be automatically stoped, 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;
+}
+
+void ScintillaGTK::PopUpCB(ScintillaGTK *sciThis, guint action, GtkWidget *) {
+	if (action) {
+		sciThis->Command(action);
+	}
+}
+
+gint ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
+	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();
+#if GTK_MAJOR_VERSION >= 2
+	return TRUE;
+#else
+	return FALSE;
+#endif
+}
+
+gint ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
+	Surface *surfaceWindow = Surface::Allocate();
+	if (surfaceWindow) {
+		surfaceWindow->Init(widget->window, widget);
+		ctip->PaintCT(surfaceWindow);
+		surfaceWindow->Release();
+		delete surfaceWindow;
+	}
+	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();
+
+#if GLIB_MAJOR_VERSION < 2
+GtkType scintilla_get_type() {
+	static GtkType scintilla_type = 0;
+
+	if (!scintilla_type) {
+		Platform_Initialise();
+		static GtkTypeInfo scintilla_info = {
+		    "Scintilla",
+		    sizeof (ScintillaObject),
+		    sizeof (ScintillaClass),
+		    (GtkClassInitFunc) scintilla_class_init,
+		    (GtkObjectInitFunc) scintilla_init,
+		    (gpointer) NULL,
+		    (gpointer) NULL,
+		    0
+		};
+
+		scintilla_type = gtk_type_unique(gtk_container_get_type(), &scintilla_info);
+	}
+
+	return scintilla_type;
+}
+#else
+GType scintilla_get_type() {
+	static GType scintilla_type = 0;
+
+	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);
+		}
+	}
+
+	return scintilla_type;
+}
+#endif
+
+void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
+#if GLIB_MAJOR_VERSION >= 2
+	Platform_Initialise();
+#endif
+	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?)
+
+#if GLIB_MAJOR_VERSION < 2
+	object_class->destroy = Destroy;
+#else
+	object_class->finalize = Destroy;
+#endif
+	widget_class->size_request = SizeRequest;
+	widget_class->size_allocate = SizeAllocate;
+	widget_class->expose_event = ExposeMain;
+#if GTK_MAJOR_VERSION < 2
+	widget_class->draw = Draw;
+#endif
+	widget_class->motion_notify_event = Motion;
+	widget_class->button_press_event = Press;
+	widget_class->button_release_event = MouseRelease;
+#if PLAT_GTK_WIN32 || (GTK_MAJOR_VERSION >= 2)
+	widget_class->scroll_event = ScrollEvent;
+#endif
+	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;
+#if GTK_MAJOR_VERSION < 2
+	widget_class->selection_notify_event = SelectionNotify;
+#endif
+
+	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;
+}
+
+#if GLIB_MAJOR_VERSION < 2
+#define GTK_CLASS_TYPE(c) (c->type)
+#define SIG_MARSHAL gtk_marshal_NONE__INT_POINTER
+#define MARSHAL_ARGUMENTS GTK_TYPE_INT, GTK_TYPE_POINTER
+#else
+#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
+#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER
+#endif
+
+static void scintilla_class_init(ScintillaClass *klass) {
+	OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass;
+	GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
+	GtkContainerClass *container_class = (GtkContainerClass*) klass;
+
+#if GLIB_MAJOR_VERSION < 2
+	parent_class = (GtkWidgetClass*) gtk_type_class(gtk_container_get_type());
+
+	scintilla_signals[COMMAND_SIGNAL] = gtk_signal_new(
+	                                        "command",
+	                                        GTK_RUN_LAST,
+	                                        GTK_CLASS_TYPE(object_class),
+	                                        GTK_SIGNAL_OFFSET(ScintillaClass, command),
+	                                        SIG_MARSHAL,
+	                                        GTK_TYPE_NONE,
+	                                        2, MARSHAL_ARGUMENTS);
+
+	scintilla_signals[NOTIFY_SIGNAL] = gtk_signal_new(
+	                                       SCINTILLA_NOTIFY,
+	                                       GTK_RUN_LAST,
+	                                       GTK_CLASS_TYPE(object_class),
+	                                       GTK_SIGNAL_OFFSET(ScintillaClass, notify),
+	                                       SIG_MARSHAL,
+	                                       GTK_TYPE_NONE,
+	                                       2, MARSHAL_ARGUMENTS);
+	gtk_object_class_add_signals(object_class,
+	                             reinterpret_cast<unsigned int *>(scintilla_signals), LAST_SIGNAL);
+#else
+	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);
+#endif
+	klass->command = NULL;
+	klass->notify = NULL;
+
+	ScintillaGTK::ClassInit(object_class, widget_class, container_class);
+}
+
+static void scintilla_init(ScintillaObject *sci) {
+	GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS);
+	sci->pscin = new ScintillaGTK(sci);
+}
+
+GtkWidget* scintilla_new() {
+#if GLIB_MAJOR_VERSION < 2
+	return GTK_WIDGET(gtk_type_new(scintilla_get_type()));
+#else
+	return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
+#endif
+}
+
+void scintilla_set_id(ScintillaObject *sci, uptr_t id) {
+	ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
+	psci->ctrlID = id;
+}
+
+void scintilla_release_resources(void) {
+	Platform_Finalise();
+}

Added: trunk/plugins/scintilla/scintilla/SplitVector.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/SplitVector.h	Wed Apr  8 20:49:12 2009
@@ -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) {
+			if (growSize * 6 < size)
+				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

Added: trunk/plugins/scintilla/scintilla/Style.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Style.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,158 @@
+// 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;
+}
+
+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, bool 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, ' ');
+}

Added: trunk/plugins/scintilla/scintilla/Style.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/Style.h	Wed Apr  8 20:49:12 2009
@@ -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, bool extraFontFlag = false);
+	bool IsProtected() const { return !(changeable && visible);};
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif

Added: trunk/plugins/scintilla/scintilla/StyleContext.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/StyleContext.cxx	Wed Apr  8 20:49:12 2009
@@ -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);
+}

Added: trunk/plugins/scintilla/scintilla/StyleContext.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/StyleContext.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,179 @@
+// 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&) {
+		return *this;
+	}
+	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() {
+		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) {
+		return ch == static_cast<unsigned char>(ch0);
+	}
+	bool Match(char ch0, char ch1) {
+		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));
+	}
+}

Added: trunk/plugins/scintilla/scintilla/UniConversion.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/UniConversion.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,119 @@
+// Scintilla source code edit control
+/** @file UniConversion.cxx
+ ** Functions to handle UFT-8 and UCS-2 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 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;
+}

Added: trunk/plugins/scintilla/scintilla/UniConversion.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/UniConversion.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,12 @@
+// Scintilla source code edit control
+/** @file UniConversion.h
+ ** Functions to handle UFT-8 and UCS-2 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 UTF16Length(const char *s, unsigned int len);
+unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);
+

Added: trunk/plugins/scintilla/scintilla/ViewStyle.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ViewStyle.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,359 @@
+// 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;
+	selbackset = source.selbackset;
+	selbackground.desired = source.selbackground.desired;
+	selbackground2.desired = source.selbackground2.desired;
+	selAlpha = source.selAlpha;
+	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;
+	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;
+	viewIndentationGuides = source.viewIndentationGuides;
+	viewEOL = source.viewEOL;
+	showMarkedLines = source.showMarkedLines;
+	extraFontFlag = source.extraFontFlag;
+}
+
+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);
+	selbackset = true;
+	selbackground.desired = ColourDesired(0xc0, 0xc0, 0xc0);
+	selbackground2.desired = ColourDesired(0xb0, 0xb0, 0xb0);
+	selAlpha = 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);
+	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;
+	viewIndentationGuides = ivNone;
+	viewEOL = false;
+	showMarkedLines = true;
+	extraFontFlag = false;
+}
+
+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(selbackground, 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(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;
+		}
+	}
+
+	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;
+}

Added: trunk/plugins/scintilla/scintilla/ViewStyle.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/ViewStyle.h	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,124 @@
+// 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;
+	bool selbackset;
+	ColourPair selbackground;
+	ColourPair selbackground2;
+	int selAlpha;
+	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;
+	IndentView viewIndentationGuides;
+	bool viewEOL;
+	bool showMarkedLines;
+	ColourPair caretcolour;
+	bool showCaretLineBackground;
+	ColourPair caretLineBackground;
+	int caretLineAlpha;
+	ColourPair edgecolour;
+	int edgeState;
+	int caretStyle;
+	int caretWidth;
+	bool someStylesProtected;
+	bool extraFontFlag;
+
+	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;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif

Added: trunk/plugins/scintilla/scintilla/WindowAccessor.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/WindowAccessor.cxx	Wed Apr  8 20:49:12 2009
@@ -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;
+
+	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);
+	}
+}

Added: trunk/plugins/scintilla/scintilla/XPM.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/XPM.cxx	Wed Apr  8 20:49:12 2009
@@ -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) {
+	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;
+}

Added: trunk/plugins/scintilla/scintilla/XPM.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/XPM.h	Wed Apr  8 20:49:12 2009
@@ -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 id;		// Assigned by container
+	int height;
+	int width;
+	int nColours;
+	char *data;
+	char codeTransparent;
+	char *codes;
+	ColourPair *colours;
+	ColourAllocated ColourFromCode(int ch);
+	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 id_) { id = id_; }
+	int GetId() { return id; }
+	int GetHeight() { return height; }
+	int GetWidth() { 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

Added: trunk/plugins/scintilla/scintilla/scintilla-marshal.c
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/scintilla-marshal.c	Wed Apr  8 20:49:12 2009
@@ -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);
+}
+

Added: trunk/plugins/scintilla/scintilla/scintilla-marshal.h
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/scintilla-marshal.h	Wed Apr  8 20:49:12 2009
@@ -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__ */
+

Added: trunk/plugins/scintilla/scintilla/scintilla-marshal.list
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/scintilla-marshal.list	Wed Apr  8 20:49:12 2009
@@ -0,0 +1 @@
+NONE:INT,POINTER

Added: trunk/plugins/scintilla/scintilla/test-scintilla.cxx
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/test-scintilla.cxx	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,116 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <Platform.h>
+#include <Scintilla.h>
+#include <ScintillaWidget.h>
+
+void SetOneStyle(GtkWidget *sci, int style, const char *s) {
+	char *val = strdup(s);
+	char *opt = val;
+	while (opt) {
+		char *cpComma = strchr(opt, ',');
+		if (cpComma)
+			*cpComma = '\0';
+		char *colon = strchr(opt, ':');
+		if (colon)
+			*colon++ = '\0';
+		if (0 == strcmp(opt, "italics"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETITALIC, style, 1);
+		if (0 == strcmp(opt, "notitalics"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETITALIC, style, 0);
+		if (0 == strcmp(opt, "bold"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETBOLD, style, 1);
+		if (0 == strcmp(opt, "notbold"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETBOLD, style, 0);
+		if (0 == strcmp(opt, "font"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETFONT, style, reinterpret_cast<long>(colon));
+		if (0 == strcmp(opt, "fore"))
+			//scintilla_send_message(SCINTILLA(sci), SCI_STYLESETFORE, style, ColourFromString(colon).AsLong());
+		if (0 == strcmp(opt, "back"))
+			//scintilla_send_message(SCINTILLA(sci), SCI_STYLESETBACK, style, ColourFromString(colon).AsLong());
+		if (0 == strcmp(opt, "size"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETSIZE, style, atoi(colon));
+		if (0 == strcmp(opt, "eolfilled"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETEOLFILLED, style, 1);
+		if (0 == strcmp(opt, "noteolfilled"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETEOLFILLED, style, 0);
+		if (0 == strcmp(opt, "underlined"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETUNDERLINE, style, 1);
+		if (0 == strcmp(opt, "notunderlined"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETUNDERLINE, style, 0);
+		if (0 == strcmp(opt, "case")) {
+			if (*colon == 'u') {
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCASE, style, SC_CASE_UPPER);
+			} else if (*colon == 'l') {
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCASE, style, SC_CASE_LOWER);
+			} else {
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCASE, style, SC_CASE_MIXED);
+			}
+		}
+		if (0 == strcmp(opt, "visible"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETVISIBLE, style, 1);
+		if (0 == strcmp(opt, "notvisible"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETVISIBLE, style, 0);
+		if (0 == strcmp(opt, "changeable"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCHANGEABLE, style, 1);
+		if (0 == strcmp(opt, "notchangeable"))
+			scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCHANGEABLE, style, 0);
+		if (cpComma)
+			opt = cpComma + 1;
+		else
+			opt = 0;
+	}
+	if (val)
+		delete []val;
+	// scintilla_send_message(SCINTILLA(sci), SCI_STYLESETCHARACTERSET, style, characterSet);
+}
+
+int main(int argc, char **argv)
+{
+	GtkWidget *sci;
+	GtkWidget *win;
+	FILE *fp;
+	size_t read_bytes = 0;
+	char buffer[1025];
+	
+	gtk_init (&argc, &argv);
+	if (argc != 2)
+	{
+		printf ("Usage: test-scintilla filename\n");
+		exit(1);
+	}
+	win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	sci = scintilla_new();
+	SetOneStyle (sci, STYLE_DEFAULT,
+		"font:bitstream vera sans mono,size:10,back:#EFEFEF");
+	scintilla_send_message(SCINTILLA(sci), SCI_SETWRAPMODE, SC_WRAP_WORD, 0);
+	scintilla_send_message(SCINTILLA(sci), SCI_SETHSCROLLBAR, 0, 0);
+	scintilla_send_message(SCINTILLA(sci), SCI_SETCODEPAGE, SC_CP_UTF8, 0);
+	scintilla_send_message(SCINTILLA(sci), SCI_SETMARGINWIDTHN, 0, 40);
+	//scintilla_set_id(SCINTILLA(sci), 0);
+	gtk_container_add (GTK_CONTAINER(win), sci);
+	g_signal_connect (G_OBJECT (win), "delete-event",
+					  G_CALLBACK (gtk_main_quit), NULL);
+	gtk_widget_set_usize (GTK_WIDGET (win), 500, 600);
+	gtk_window_set_default_size (GTK_WINDOW (win), 500, 600);
+	gtk_widget_show (sci);
+	gtk_widget_show (win);
+	fp = fopen (argv[1], "r");
+	if (!fp)
+	{
+		perror ("Unable to open file\n");
+		exit(1);
+	}
+	while ((read_bytes = fread (buffer, 1, 1024, fp)) > 0)
+	{
+		buffer[read_bytes] = '\0';
+		scintilla_send_message(SCINTILLA(sci), SCI_APPENDTEXT, read_bytes, reinterpret_cast<long>(buffer));
+	}
+	fclose (fp);
+	gtk_main();
+	return 0;
+}

Added: trunk/plugins/scintilla/scintilla/update-properties.pl
==============================================================================
--- (empty file)
+++ trunk/plugins/scintilla/scintilla/update-properties.pl	Wed Apr  8 20:49:12 2009
@@ -0,0 +1,374 @@
+#!/usr/bin/perl -w
+# 
+# Copyright (C) 2008 SÃbastien Granjoux  <seb sfo free fr>
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ 
+# This program read all *.properties file containing style defintion and copy
+# their content in the output file with all style definitions at the end.
+# You are supposed to edit all the style definition to use properties defined
+# by Anjuta. If the output file already exist, the style definition already
+# existing are kept.
+#
+# The -stat options allow to see when each anjuta style is used.
+
+use strict;
+use File::Copy;
+use File::Basename;
+use Getopt::Long;
+
+my %anjuta_defs;
+
+my %anjuta_stat;
+
+# Get command line argument
+my $stat = "";
+
+GetOptions ("stat" => \$stat);
+
+my $output_file = $ARGV[0];
+my $prop_directory = $ARGV[1];
+
+if (!defined($prop_directory))
+{
+	die "Usage: update-properties.pl [-stat] output_properties_file input_directory";
+}
+
+
+# Read old definition, copy all file
+%anjuta_defs = read_style_definition ($output_file);
+copy($output_file, $output_file.".bak");
+if ($stat) {%anjuta_stat = create_stat_hash (\%anjuta_defs);}
+
+# Open output file for writing
+open (OUTFILE, ">$output_file") or die "Unable to open file $output_file for writing\n";
+print OUTFILE <<EOF;
+###############################################################################
+#
+# Created by update-properties.pl from all SciTE properties files
+#
+# This file is divided in 2 parts:
+#   * The first part concatenate all SciTE *.properties file containing style
+#     definition but without these definitions. 
+#   * The second part group all style definitions. The style definition should
+#     be modified to use anjuta style properties. If the output file already
+#     exists the second part is read before overwriting it, so you can keep
+#     any change done here.
+EOF
+
+# Read properties in new file
+opendir (PROPDIR, $prop_directory) or die "Unable to open directory $prop_directory\n";
+foreach my $filename (sort readdir(PROPDIR))
+{
+	if (($filename ne "Embedded.properties") &&
+	    ($filename ne "anjuta.properties") &&
+	    ($filename ne basename ($output_file)) &&
+	    ($filename =~ /\w+\.properties/))
+	{
+		my %defs;
+
+		%defs = read_style_definition ($prop_directory."/".$filename);
+
+		if (%defs)
+		{
+			copy_non_style_definition (\*OUTFILE, $prop_directory."/".$filename);
+
+			# Gather some stats
+			if ($stat) {gather_stat (\%anjuta_stat, \%anjuta_defs, \%defs);}
+
+			# Merge with anjuta propertes
+			merge_style_definition (\%anjuta_defs, \%defs);
+		}
+	}
+}
+closedir(PROPDIR);
+
+# Write style values
+print OUTFILE "\n\n\n\n";
+
+# Write languages style definition
+for my $lang (sort keys %anjuta_defs)
+{
+	write_style_definition (\*OUTFILE, $anjuta_defs{$lang}, $lang);
+}
+
+close(OUTFILE);
+
+if ($stat) {display_stat (\%anjuta_stat);}
+
+
+
+# Read a properties file and keep only style definition
+sub read_style_definition
+{ 
+	my ($filename) = @_;
+
+	my %defs = ();
+	my $last_comment = "";
+	my $line = "";
+
+	if (open (INFILE, "<$filename"))
+	{
+		while ($line = <INFILE>)
+		{
+			if ($line =~ /^\s*#\s*style\.\w+\.\d+\s*=.+$/)
+			{
+				# Style put in comment, just discard
+				;
+			}
+			elsif ($line =~ /^\s*#(.+)$/)
+			{
+				# Comment keep the last one
+				$last_comment = $1;
+			}
+			elsif ($line =~ /^\s*style\.([\w*]+)\.(\d+)\s*=\s*(.+)\s*$/)
+			{
+				# Style line add it into the hash
+				if (($1 ne '*') && 
+				    ($2 ne "32") && 
+				    ($2 ne "33") && 
+ 				    ($2 ne "34") &&
+				    ($2 ne "35") &&
+ 				    ($2 ne "36") &&
+				    ($2 ne "37"))
+				{
+					# Keep only language style
+					$defs{$1}{$2}{"value"} = $3;
+					$defs{$1}{$2}{"comment"} = $last_comment;
+					$defs{$1}{$2}{"filename"} = basename ($filename, "");
+					$last_comment = ""
+				}
+			}
+			elsif ($line =~ /^\s*$/)
+			{
+				# Empty line, just skip
+				;
+			}
+			else
+			{
+				# Remove last comment
+				$last_comment = "";
+			}
+		}
+		close (INFILE);
+	}
+
+	return %defs;	
+}
+
+# Copy all non properties line of the given file in the output stream
+sub copy_non_style_definition
+{ 
+	my ($out, $filename) = @_;
+
+	my %defs = ();
+	my $last_comment = "";
+	my $line = "";
+
+	print $out "\n\n\n###############################################################################\n";
+	my $basename = basename ($filename, "");
+	print $out "# From $basename\n";
+
+	print "Open file $filename...\n";
+	if (open (INFILE, "<$filename"))
+	{
+		while ($line = <INFILE>)
+		{
+			if ($line =~ /^\s*#\s*style\.\w+\.\d+\s*=.+$/)
+			{
+				# Style put in comment, just discard
+				;
+			}
+			elsif ($line =~ /^\s*#(.+)$/)
+			{
+				# Comment, print previous one and keep current one
+				if ($last_comment)
+				{
+					print $out "#$last_comment\n";
+					$last_comment = "";
+				}
+				$last_comment = $1;
+			}
+			elsif ($line =~ /^\s*style\.([\w*]+)\.(\d+)\s*=\s*(.*)\s*$/)
+			{
+				# Style line, discard it with the last comment
+				$last_comment = "";
+			}
+			elsif ($line =~ /^\s*$/)
+			{
+				# Empty line, add it
+				if ($last_comment)
+				{
+					$last_comment = $last_comment . "\n";
+				}
+				else
+				{
+					print $out "\n";
+				}
+			}
+			else
+			{
+				# Other line
+				if ($last_comment)
+				{
+					print $out "#$last_comment\n";
+					$last_comment = "";
+				}
+				print $out $line;
+			}
+		}
+		close (INFILE);
+		if ($last_comment) {print $out "#$last_comment\n";}
+	}
+
+	return %defs;	
+}
+
+# Merge new definitions in anjuta defintions
+sub merge_style_definition
+{
+	my ($anjuta_defs, $defs) = @_;
+
+	for my $lang (keys %$defs)
+	{
+		for my $style (keys %{$defs->{$lang}})
+		{
+			if ((exists $anjuta_defs->{$lang}) && (exists $anjuta_defs->{$lang}{$style}))
+			{
+				if ($anjuta_defs->{$lang}{$style}{"filename"} ne basename ($output_file))
+				{
+					# Properties defined in two SciTE files
+					my $file1 = $anjuta_defs->{$lang}{$style}{"filename"};
+					my $file2 = $defs->{$lang}{$style}{"filename"};
+					print "Warning: properties style.$lang.$style defined in file $file1 and $file2 \n";
+				}
+				else
+				{
+					$anjuta_defs->{$lang}{$style}{"comment"} = $defs->{$lang}{$style}{"comment"};
+					$anjuta_defs->{$lang}{$style}{"filename"} = $defs->{$lang}{$style}{"filename"};
+				}
+			}
+			else
+			{
+				# Add properties
+				$anjuta_defs->{$lang}{$style}{"value"} = $defs->{$lang}{$style}{"value"};
+				$anjuta_defs->{$lang}{$style}{"comment"} = $defs->{$lang}{$style}{"comment"};
+				$anjuta_defs->{$lang}{$style}{"filename"} = $defs->{$lang}{$style}{"filename"};
+			}
+				
+		}
+	}
+}
+
+# Write style defintions
+sub write_style_definition
+{
+	my ($out, $defs, $lang) = @_;
+	my $filename = "";	
+
+	for my $style (sort {$a <=> $b} keys %{$defs})
+	{
+		my $comment;
+		my $value;
+		if ($defs->{$style}{"filename"} eq basename ($output_file))
+		{
+			print "Warning: style.$lang.$style is not defined anymore. It has been commented\n";
+			$comment = $defs->{$style}{"comment"};
+			$value = $defs->{$style}{"value"};
+			print $out "#$comment\n";
+			print $out "#style.$lang.$style=$value\n";
+		}
+		else
+		{
+			if (!$filename)
+			{
+				$filename = $defs->{$style}{"filename"};
+				print $out "\n###############################################################################\n";
+				print $out "# Style for $lang from file $filename\n\n"
+			}
+			elsif ($filename ne $defs->{$style}{"filename"})
+			{
+				my $file2 = $defs->{$style}{"filename"};
+				print "Warning: style.$lang.$style is defined in file $filename and $file2\n";
+			}
+			
+			$comment = $defs->{$style}{"comment"};
+			$value = $defs->{$style}{"value"};
+			print $out "#$comment\n";
+			print $out "\tstyle.$lang.$style=$value\n";
+
+			if (!($value =~ /\$\(style\.anjuta\.\w+\)\s*$/) &&
+			   !($value =~ /\$\(style\.gnome\.\w+\)\s*$/))
+			{
+				print "Warning: style.$lang.$style does not use anjuta properties\n";
+			}
+		}
+	}
+	print $out "\n\n";
+}
+
+# Create stats hash
+sub create_stat_hash
+{
+	my ($defs) = @_;
+	my %stat = ();
+
+	for my $lang (keys %$defs)
+	{
+		for my $style (keys %{$defs->{$lang}})
+		{
+			my $value = $defs->{$lang}{$style}{"value"};
+			$stat{$value} = [];
+		}
+	}
+
+	return %stat;
+}
+
+# Get statistic about used anjuta value 
+sub gather_stat
+{
+	my ($stat, $anjuta_defs, $defs) = @_;
+
+	for my $lang (keys %$defs)
+	{
+		for my $style (keys %{$defs->{$lang}})
+		{
+			if ((exists $anjuta_defs->{$lang}) && (exists $anjuta_defs->{$lang}{$style}))
+			{
+				my $anjuta_value = $anjuta_defs->{$lang}{$style}{"value"};
+				my $value = $defs->{$lang}{$style}{"value"}." ($lang.$style)";
+				
+				$stat->{$anjuta_value} = [ {$stat->{$anjuta_value}}, $value];
+			}
+		}
+	}
+}
+
+# Display statistic about used anjuta value
+sub display_stat
+{
+	my ($stat) = @_;
+
+	for my $anjuta_value (sort keys %$stat)
+	{
+		print "$anjuta_value\n";
+		foreach my $value (sort @{$stat->{$anjuta_value}})
+		{
+			print "\t$value\n";
+		}
+	}
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]