]> git.saurik.com Git - wxWidgets.git/commitdiff
Initial version of wxStyledTextCtrl, a Scintilla wrapper. There is
authorRobin Dunn <robin@alldunn.com>
Thu, 9 Mar 2000 19:42:06 +0000 (19:42 +0000)
committerRobin Dunn <robin@alldunn.com>
Thu, 9 Mar 2000 19:42:06 +0000 (19:42 +0000)
still LOTS and LOTS to be done, but this is already very functional.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6555 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

94 files changed:
contrib/include/wx/stc/stc.h [new file with mode: 0644]
contrib/samples/stc/.cvsignore [new file with mode: 0644]
contrib/samples/stc/makefile.vc [new file with mode: 0644]
contrib/samples/stc/stctest.cpp [new file with mode: 0644]
contrib/samples/stc/stctest.rc [new file with mode: 0644]
contrib/src/stc/PlatWX.cpp [new file with mode: 0644]
contrib/src/stc/README.txt [new file with mode: 0644]
contrib/src/stc/ScintillaWX.cpp [new file with mode: 0644]
contrib/src/stc/ScintillaWX.h [new file with mode: 0644]
contrib/src/stc/makefile.vc [new file with mode: 0644]
contrib/src/stc/scintilla/README.txt [new file with mode: 0644]
contrib/src/stc/scintilla/include/Accessor.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/KeyWords.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/Platform.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/PropSet.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/SciLexer.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/Scintilla.h [new file with mode: 0644]
contrib/src/stc/scintilla/include/WinDefs.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/Accessor.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/AutoComplete.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/AutoComplete.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/CallTip.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/CallTip.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/CellBuffer.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/CellBuffer.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/ContractionState.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/ContractionState.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/Document.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/Document.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/Editor.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/Editor.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/Indicator.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/Indicator.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/KeyMap.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/KeyMap.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/KeyWords.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LineMarker.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LineMarker.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/PropSet.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/SVector.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/ScintillaBase.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/ScintillaBase.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/Style.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/Style.h [new file with mode: 0644]
contrib/src/stc/scintilla/src/ViewStyle.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/ViewStyle.h [new file with mode: 0644]
contrib/src/stc/stc.cpp [new file with mode: 0644]
include/wx/stc/stc.h [new file with mode: 0644]
samples/stc/.cvsignore [new file with mode: 0644]
samples/stc/makefile.vc [new file with mode: 0644]
samples/stc/stctest.cpp [new file with mode: 0644]
samples/stc/stctest.rc [new file with mode: 0644]
src/stc/PlatWX.cpp [new file with mode: 0644]
src/stc/README.txt [new file with mode: 0644]
src/stc/ScintillaWX.cpp [new file with mode: 0644]
src/stc/ScintillaWX.h [new file with mode: 0644]
src/stc/makefile.vc [new file with mode: 0644]
src/stc/scintilla/README.txt [new file with mode: 0644]
src/stc/scintilla/include/Accessor.h [new file with mode: 0644]
src/stc/scintilla/include/KeyWords.h [new file with mode: 0644]
src/stc/scintilla/include/Platform.h [new file with mode: 0644]
src/stc/scintilla/include/PropSet.h [new file with mode: 0644]
src/stc/scintilla/include/SciLexer.h [new file with mode: 0644]
src/stc/scintilla/include/Scintilla.h [new file with mode: 0644]
src/stc/scintilla/include/WinDefs.h [new file with mode: 0644]
src/stc/scintilla/src/Accessor.cxx [new file with mode: 0644]
src/stc/scintilla/src/AutoComplete.cxx [new file with mode: 0644]
src/stc/scintilla/src/AutoComplete.h [new file with mode: 0644]
src/stc/scintilla/src/CallTip.cxx [new file with mode: 0644]
src/stc/scintilla/src/CallTip.h [new file with mode: 0644]
src/stc/scintilla/src/CellBuffer.cxx [new file with mode: 0644]
src/stc/scintilla/src/CellBuffer.h [new file with mode: 0644]
src/stc/scintilla/src/ContractionState.cxx [new file with mode: 0644]
src/stc/scintilla/src/ContractionState.h [new file with mode: 0644]
src/stc/scintilla/src/Document.cxx [new file with mode: 0644]
src/stc/scintilla/src/Document.h [new file with mode: 0644]
src/stc/scintilla/src/Editor.cxx [new file with mode: 0644]
src/stc/scintilla/src/Editor.h [new file with mode: 0644]
src/stc/scintilla/src/Indicator.cxx [new file with mode: 0644]
src/stc/scintilla/src/Indicator.h [new file with mode: 0644]
src/stc/scintilla/src/KeyMap.cxx [new file with mode: 0644]
src/stc/scintilla/src/KeyMap.h [new file with mode: 0644]
src/stc/scintilla/src/KeyWords.cxx [new file with mode: 0644]
src/stc/scintilla/src/LineMarker.cxx [new file with mode: 0644]
src/stc/scintilla/src/LineMarker.h [new file with mode: 0644]
src/stc/scintilla/src/PropSet.cxx [new file with mode: 0644]
src/stc/scintilla/src/SVector.h [new file with mode: 0644]
src/stc/scintilla/src/ScintillaBase.cxx [new file with mode: 0644]
src/stc/scintilla/src/ScintillaBase.h [new file with mode: 0644]
src/stc/scintilla/src/Style.cxx [new file with mode: 0644]
src/stc/scintilla/src/Style.h [new file with mode: 0644]
src/stc/scintilla/src/ViewStyle.cxx [new file with mode: 0644]
src/stc/scintilla/src/ViewStyle.h [new file with mode: 0644]
src/stc/stc.cpp [new file with mode: 0644]

diff --git a/contrib/include/wx/stc/stc.h b/contrib/include/wx/stc/stc.h
new file mode 100644 (file)
index 0000000..4920f70
--- /dev/null
@@ -0,0 +1,547 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        stc.h
+// Purpose:     A wxWindows implementation of Scintilla.  This class is the
+//              one meant to be used directly by wx applications.  It does not
+//              derive directly from the Scintilla classes, and in fact there
+//              is no mention of Scintilla classes at all in this header.
+//              This class delegates all method calls and events to the
+//              Scintilla objects and so forth.  This allows the use of
+//              Scintilla without polluting the namespace with all the
+//              classes and itentifiers from Scintilla.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __stc_h__
+#define __stc_h__
+
+
+#include <wx/wx.h>
+
+
+//----------------------------------------------------------------------
+// constants and stuff
+
+enum wxSTC_UndoType {
+    wxSTC_UndoCollectNone,
+    wxSTC_UndoCollectAutoStart
+};
+
+
+enum wxSTC_EOL {
+    wxSTC_EOL_CRLF,
+    wxSTC_EOL_CR,
+    wxSTC_EOL_LF
+};
+
+enum wxSTC_EDGE {
+    wxSTC_EDGE_NONE,
+    wxSTC_EDGE_LINE,
+    wxSTC_EDGE_BACKGROUND
+};
+
+
+
+const int wxSTC_LEX_STYLE_MAX     = 31;
+const int wxSTC_STYLE_DEFAULT     = 32;
+const int wxSTC_STYLE_LINENUMBER  = 33;
+const int wxSTC_STYLE_BRACELIGHT  = 34;
+const int wxSTC_STYLE_BRACEBAD    = 35;
+const int wxSTC_STYLE_CONTROLCHAR = 36;
+const int wxSTC_STYLE_MAX         = 63;
+const int wxSTC_STYLE_MASK        = 31;
+
+const int wxSTC_MARKER_MAX        = 31;
+const int wxSTC_MARK_CIRCLE       = 0;
+const int wxSTC_MARK_ROUNDRECT    = 1;
+const int wxSTC_MARK_ARROW        = 2;
+const int wxSTC_MARK_SMALLRECT    = 3;
+const int wxSTC_MARK_SHORTARROW   = 4;
+const int wxSTC_MARK_EMPTY        = 5;
+
+const int wxSTC_INDIC_PLAIN       = 0;
+const int wxSTC_INDIC_SQUIGGLE    = 1;
+const int wxSTC_INDIC_TT          = 2;
+const int wxSTC_INDIC0_MASK       = 32;
+const int wxSTC_INDIC1_MASK       = 64;
+const int wxSTC_INDIC2_MASK       = 128;
+const int wxSTC_INDICS_MASK       = (wxSTC_INDIC0_MASK | wxSTC_INDIC1_MASK | wxSTC_INDIC2_MASK);
+
+
+// key commands
+enum {
+    wxSTC_CMD_LINEDOWN = 2300,
+    wxSTC_CMD_LINEDOWNEXTEND,
+    wxSTC_CMD_LINEUP,
+    wxSTC_CMD_LINEUPEXTEND,
+    wxSTC_CMD_CHARLEFT,
+    wxSTC_CMD_CHARLEFTEXTEND,
+    wxSTC_CMD_CHARRIGHT,
+    wxSTC_CMD_CHARRIGHTEXTEND,
+    wxSTC_CMD_WORDLEFT,
+    wxSTC_CMD_WORDLEFTEXTEND,
+    wxSTC_CMD_WORDRIGHT,
+    wxSTC_CMD_WORDRIGHTEXTEND,
+    wxSTC_CMD_HOME,
+    wxSTC_CMD_HOMEEXTEND,
+    wxSTC_CMD_LINEEND,
+    wxSTC_CMD_LINEENDEXTEND,
+    wxSTC_CMD_DOCUMENTSTART,
+    wxSTC_CMD_DOCUMENTSTARTEXTEND,
+    wxSTC_CMD_DOCUMENTEND,
+    wxSTC_CMD_DOCUMENTENDEXTEND,
+    wxSTC_CMD_PAGEUP,
+    wxSTC_CMD_PAGEUPEXTEND,
+    wxSTC_CMD_PAGEDOWN,
+    wxSTC_CMD_PAGEDOWNEXTEND,
+    wxSTC_CMD_EDITTOGGLEOVERTYPE,
+    wxSTC_CMD_CANCEL,
+    wxSTC_CMD_DELETEBACK,
+    wxSTC_CMD_TAB,
+    wxSTC_CMD_BACKTAB,
+    wxSTC_CMD_NEWLINE,
+    wxSTC_CMD_FORMFEED,
+    wxSTC_CMD_VCHOME,
+    wxSTC_CMD_VCHOMEEXTEND,
+    wxSTC_CMD_ZOOMIN,
+    wxSTC_CMD_ZOOMOUT,
+    wxSTC_CMD_DELWORDLEFT,
+    wxSTC_CMD_DELWORDRIGHT
+};
+
+
+enum wxSTC_LEX {
+    wxSTC_LEX_CONTAINER=0,
+    wxSTC_LEX_NULL,
+    wxSTC_LEX_PYTHON,
+    wxSTC_LEX_CPP,
+    wxSTC_LEX_HTML,
+    wxSTC_LEX_XML,
+    wxSTC_LEX_PERL,
+    wxSTC_LEX_SQL,
+    wxSTC_LEX_VB,
+    wxSTC_LEX_PROPERTIES,
+    wxSTC_LEX_ERRORLIST,
+    wxSTC_LEX_MAKEFILE,
+    wxSTC_LEX_BATCH,
+};
+
+
+
+const int wxSTC_CARET_SLOP    = 0x01;
+const int WXSTC_CARET_CENTER  = 0x02;
+const int wxSTC_CARET_STRICT  = 0x04;
+
+const int wxSTC_MARGIN_SYMBOL = 0;
+const int wxSTC_MARGIN_NUMBER = 1;
+
+
+class  ScintillaWX;                      // forward declare
+class  WordList;
+struct SCNotification;
+
+
+extern const wxChar* wxSTCNameStr;
+
+//----------------------------------------------------------------------
+
+class wxStyledTextCtrl : public wxControl {
+public:
+
+    wxStyledTextCtrl(wxWindow *parent, wxWindowID id,
+                     const wxPoint& pos = wxDefaultPosition,
+                     const wxSize& size = wxDefaultSize, long style = 0,
+                     const wxString& name = wxSTCNameStr);
+    ~wxStyledTextCtrl();
+
+
+
+    // Text retrieval and modification
+    wxString GetText();
+    bool     SetText(const wxString& text);
+    wxString GetLine(int line);
+    void     ReplaceSelection(const wxString& text);
+    void     SetReadOnly(bool readOnly);
+    bool     GetReadOnly();
+    wxString GetTextRange(int startPos, int endPos);
+    wxString GetStyledTextRange(int startPos, int endPos);
+    void     GetTextRange(int startPos, int endPos, char* buff);
+    void     GetStyledTextRange(int startPos, int endPos, char* buff);
+    void     AddText(const wxString& text);
+    void     AddStyledText(const wxString& text);
+    void     InsertText(int pos, const wxString& text);
+    void     ClearAll();
+    char     GetCharAt(int pos);
+    char     GetStyleAt(int pos);
+    void     SetStyleBits(int bits);
+    int      GetStyleBits();
+
+
+    // Clipboard
+    void     Cut();
+    void     Copy();
+    void     Paste();
+    bool     CanPaste();
+    void     ClearClipbrd();  // avoiding name conflict with virtual in wxWindow
+
+
+    // Undo and Redo
+    void     Undo();
+    bool     CanUndo();
+    void     EmptyUndoBuffer();
+    void     Redo();
+    bool     CanRedo();
+    void     SetUndoCollection(wxSTC_UndoType type);
+    wxSTC_UndoType GetUndoCollection();
+    void     BeginUndoAction();
+    void     EndUndoAction();
+
+
+    // Selection and information
+    void     GetSelection(int* startPos, int* endPos);
+    void     SetSelection(int  startPos, int  endPos);
+    wxString GetSelectedText();
+    void     HideSelection(bool hide);
+    bool     GetHideSelection();
+
+    int      GetTextLength();
+    int      GetFirstVisibleLine();
+    bool     GetModified();
+    int      GetLineCount();
+    wxRect   GetRect();
+    int      GetLineFromPos(int pos);
+    int      GetLineStartPos(int line);
+    int      GetLineLengthAtPos(int pos);
+    int      GetLineLength(int line);
+    wxString GetCurrentLineText(int* linePos=NULL);
+    int      GetCurrentLine();
+    int      PositionFromPoint(wxPoint pt);
+    int      LineFromPoint(wxPoint pt);
+    wxPoint  PointFromPosition(int pos);
+    int      GetCurrentPos();
+    int      GetAnchor();
+    void     SelectAll();
+    void     SetCurrentPosition(int pos);
+    void     SetAnchor(int pos);
+    void     GotoPos(int pos);
+    void     GotoLine(int line);
+    void     ChangePosition(int delta, bool extendSelection);
+    void     PageMove(int cmdKey, bool extendSelection);
+
+    void     ScrollBy(int columnDelta, int lineDelta);
+    void     ScrollToLine(int line);
+    void     ScrollToColumn(int column);
+    void     EnsureCaretVisible();
+    void     SetCaretPolicy(int policy, int slop=0);
+    int      GetSelectionType();
+
+
+
+    // Searching
+    int      FindText(int minPos, int maxPos, const wxString& text,
+                      bool caseSensitive, bool wholeWord);
+    void     SearchAnchor();
+    int      SearchNext(const wxString& text, bool caseSensitive, bool wholeWord);
+    int      SearchPrev(const wxString& text, bool caseSensitive, bool wholeWord);
+
+
+    // Visible whitespace
+    bool     GetViewWhitespace();
+    void     SetViewWhitespace(bool visible);
+
+
+    // Line endings
+    wxSTC_EOL GetEOLMode();
+    void     SetEOLMode(wxSTC_EOL mode);
+    bool     GetViewEOL();
+    void     SetViewEOL(bool visible);
+    void     ConvertEOL(wxSTC_EOL mode);
+
+
+    // Styling
+    int      GetEndStyled();
+    void     StartStyling(int pos, int mask);
+    void     SetStyleFor(int length, int style);
+    void     SetStyleBytes(int length, char* styleBytes);
+
+
+    // Style Definition
+    void     StyleClearAll();
+    void     StyleResetDefault();
+    void     StyleSetSpec(int styleNum, const wxString& spec);
+    void     StyleSetForeground(int styleNum, const wxColour& colour);
+    void     StyleSetBackground(int styleNum, const wxColour& colour);
+    void     StyleSetFont(int styleNum, wxFont& font);
+    void     StyleSetFontAttr(int styleNum, int size, const wxString& faceName, bool bold, bool italic);
+    void     StyleSetBold(int styleNum, bool bold);
+    void     StyleSetItalic(int styleNum, bool italic);
+    void     StyleSetFaceName(int styleNum, const wxString& faceName);
+    void     StyleSetSize(int styleNum, int pointSize);
+    void     StyleSetEOLFilled(int styleNum, bool fillEOL);
+
+
+    // Margins in the edit area
+    int      GetLeftMargin();
+    int      GetRightMargin();
+    void     SetMargins(int left, int right);
+
+
+    // Margins for selection, markers, etc.
+    void SetMarginType(int margin, int type);
+    int  GetMarginType(int margin);
+    void SetMarginWidth(int margin, int pixelWidth);
+    int  GetMarginWidth(int margin);
+    void SetMarginMask(int margin, int mask);
+    int  GetMarginMask(int margin);
+    void SetMarginSensitive(int margin, bool sensitive);
+    bool GetMarginSensitive(int margin);
+
+
+    // Selection and Caret styles
+    void     SetSelectionForeground(const wxColour& colour);
+    void     SetSelectionBackground(const wxColour& colour);
+    void     SetCaretForeground(const wxColour& colour);
+    int      GetCaretPeriod();
+    void     SetCaretPeriod(int milliseconds);
+
+
+    // Other settings
+    void     SetBufferedDraw(bool isBuffered);
+    void     SetTabWidth(int numChars);
+    void     SetWordChars(const wxString& wordChars);
+
+
+    // Brace highlighting
+    void     BraceHighlight(int pos1, int pos2);
+    void     BraceBadlight(int pos);
+    int      BraceMatch(int pos, int maxReStyle=0);
+
+
+    // Markers
+    void     MarkerDefine(int markerNumber, int markerSymbol,
+                          const wxColour& foreground,
+                          const wxColour& background);
+    void     MarkerSetType(int markerNumber, int markerSymbol);
+    void     MarkerSetForeground(int markerNumber, const wxColour& colour);
+    void     MarkerSetBackground(int markerNumber, const wxColour& colour);
+    int      MarkerAdd(int line, int markerNumber);
+    void     MarkerDelete(int line, int markerNumber);
+    void     MarkerDeleteAll(int markerNumber);
+    int      MarkerGet(int line);
+    int      MarkerGetNextLine(int lineStart, int markerMask);
+    int      MarkerGetPrevLine(int lineStart, int markerMask);
+    int      MarkerLineFromHandle(int handle);
+    void     MarkerDeleteHandle(int handle);
+
+
+    // Indicators
+    void     IndicatorSetStyle(int indicNum, int indicStyle);
+    int      IndicatorGetStyle(int indicNum);
+    void     IndicatorSetColour(int indicNum, const wxColour& colour);
+
+
+    // Auto completion
+    void     AutoCompShow(const wxString& listOfWords);
+    void     AutoCompCancel();
+    bool     AutoCompActive();
+    int      AutoCompPosAtStart();
+    void     AutoCompComplete();
+    void     AutoCompStopChars(const wxString& stopChars);
+
+
+    // Call tips
+    void     CallTipShow(int pos, const wxString& text);
+    void     CallTipCancel();
+    bool     CallTipActive();
+    int      CallTipPosAtStart();
+    void     CallTipSetHighlight(int start, int end);
+    void     CallTipSetBackground(const wxColour& colour);
+
+
+    // Key bindings
+    void     CmdKeyAssign(int key, int modifiers, int cmd);
+    void     CmdKeyClear(int key, int modifiers);
+    void     CmdKeyClearAll();
+    void     CmdKeyExecute(int cmd);
+
+
+    // Print formatting
+    int      FormatRange(bool   doDraw,
+                         int    startPos,
+                         int    endPos,
+                         wxDC*  draw,
+                         wxDC*  target,  // Why does it use two? Can they be the same?
+                         wxRect renderRect,
+                         wxRect pageRect);
+
+
+    // Document Sharing (multiple views)
+    void*    GetDocument();
+    void     SetDocument(void* document);
+    // TODO: create a wx wrapper for Scintilla's document class
+
+
+    // TODO: Folding
+
+
+    // Long Lines
+    int      GetEdgeColumn();
+    void     SetEdgeColumn(int column);
+    wxSTC_EDGE GetEdgeMode();
+    void     SetEdgeMode(wxSTC_EDGE mode);
+    wxColour GetEdgeColour();
+    void     SetEdgeColour(const wxColour& colour);
+
+
+    // Lexer
+    void     SetLexer(wxSTC_LEX lexer);
+    wxSTC_LEX GetLexer();
+    void     Colourise(int start, int end);
+    void     SetProperty(const wxString& key, const wxString& value);
+    void     SetKeywords(int keywordSet, const wxString& keywordList);
+
+
+
+private:
+    // Event handlers
+    void OnPaint(wxPaintEvent& evt);
+    void OnScrollWin(wxScrollWinEvent& evt);
+    void OnSize(wxSizeEvent& evt);
+    void OnMouseLeftDown(wxMouseEvent& evt);
+    void OnMouseMove(wxMouseEvent& evt);
+    void OnMouseLeftUp(wxMouseEvent& evt);
+    void OnMouseRightUp(wxMouseEvent& evt);
+    void OnChar(wxKeyEvent& evt);
+    void OnLoseFocus(wxFocusEvent& evt);
+    void OnGainFocus(wxFocusEvent& evt);
+    void OnSysColourChanged(wxSysColourChangedEvent& evt);
+    void OnEraseBackground(wxEraseEvent& evt);
+    void OnMenu(wxCommandEvent& evt);
+
+
+    // Turn notifications from Scintilla into events
+    void NotifyChange();
+    void NotifyParent(SCNotification* scn);
+
+    long SendMsg(int msg, long wp=0, long lp=0);
+
+private:
+    DECLARE_EVENT_TABLE()
+
+    ScintillaWX*        m_swx;
+    wxStopWatch         m_stopWatch;
+    bool                m_readOnly;
+    wxSTC_UndoType      m_undoType;
+
+
+    friend class ScintillaWX;
+    friend class Platform;
+};
+
+//----------------------------------------------------------------------
+
+class wxStyledTextEvent : public wxCommandEvent {
+public:
+    wxStyledTextEvent(wxEventType commandType, int id);
+    ~wxStyledTextEvent() {}
+
+    void SetPosition(int pos)        { m_position = pos; }
+    void SetKey(int k)               { m_key = k; }
+    void SetModifiers(int m)         { m_modifiers = m; }
+    void SetModificationType(int t)  { m_modificationType = t; }
+    void SetText(const char* t)      { m_text = t; }
+    void SetLength(int len)          { m_length = len; }
+    void SetLinesAdded(int num)      { m_linesAdded = num; }
+    void SetLine(int val)            { m_line = val; }
+    void SetFoldLevelNow(int val)    { m_foldLevelNow = val; }
+    void SetFoldLevelPrev(int val)   { m_foldLevelPrev = val; }
+    void SetMargin(int val)          { m_margin = val; }
+    void SetMessage(int val)         { m_message = val; }
+    void SetWParam(int val)          { m_wParam = val; }
+    void SetLParam(int val)          { m_lParam = val; }
+
+    int  GetPosition() const         { return m_position; }
+    int  GetKey()  const             { return m_key; }
+    int  GetModifiers() const        { return m_modifiers; }
+    int  GetModificationType() const { return m_modificationType; }
+    wxString GetText() const         { return m_text; }
+    int  GetLength() const           { return m_length; }
+    int  GetLinesAdded() const       { return m_linesAdded; }
+    int  GetLine() const             { return m_line; }
+    int  GetFoldLevelNow() const     { return m_foldLevelNow; }
+    int  GetFoldLevelPrev() const    { return m_foldLevelPrev; }
+    int  GetMargin() const           { return m_margin; }
+    int  GetMessage() const          { return m_message; }
+    int  GetWParam() const           { return m_wParam; }
+    int  GetLParam() const           { return m_lParam; }
+
+    bool GetShift() const;
+    bool GetControl() const;
+    bool GetAlt() const;
+
+    void CopyObject(wxObject& obj) const;
+
+private:
+    int  m_position;
+    int  m_key;
+    int  m_modifiers;
+
+    int  m_modificationType;    // wxEVT_STC_MODIFIED
+    wxString m_text;
+    int  m_length;
+    int  m_linesAdded;
+    int  m_line;
+    int  m_foldLevelNow;
+    int  m_foldLevelPrev;
+
+    int  m_margin;              // wxEVT_STC_MARGINCLICK
+
+    int  m_message;             // wxEVT_STC_MACRORECORD
+    int  m_wParam;
+    int  m_lParam;
+
+};
+
+
+
+enum {
+    wxEVT_STC_CHANGE = 1650,
+    wxEVT_STC_STYLENEEDED,
+    wxEVT_STC_CHARADDED,
+    wxEVT_STC_UPDATEUI,
+    wxEVT_STC_SAVEPOINTREACHED,
+    wxEVT_STC_SAVEPOINTLEFT,
+    wxEVT_STC_ROMODIFYATTEMPT,
+    wxEVT_STC_DOUBLECLICK,
+    wxEVT_STC_MODIFIED,
+    wxEVT_STC_KEY,
+    wxEVT_STC_MACRORECORD,
+    wxEVT_STC_MARGINCLICK,
+    wxEVT_STC_NEEDSHOWN
+};
+
+typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
+
+#define EVT_STC_CHANGE(id, fn) { wxEVT_STC_CHANGE, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_STYLENEEDED(id, fn) { wxEVT_STC_STYLENEEDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_CHARADDED(id, fn) { wxEVT_STC_CHARADDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_UPDATEUI(id, fn) { wxEVT_STC_UPDATEUI, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_SAVEPOINTREACHED(id, fn) { wxEVT_STC_SAVEPOINTREACHED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_SAVEPOINTLEFT(id, fn) { wxEVT_STC_SAVEPOINTLEFT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_ROMODIFYATTEMPT(id, fn) { wxEVT_STC_ROMODIFYATTEMPT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_DOUBLECLICK(id, fn) { wxEVT_STC_DOUBLECLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_MODIFIED(id, fn) { wxEVT_STC_MODIFIED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_CMDKEY(id, fn) { wxEVT_STC_CMDKEY, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_UNKNOWNCMDKEY(id, fn) { wxEVT_STC_UNKNOWNCMDKEY, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+#endif
+
+
diff --git a/contrib/samples/stc/.cvsignore b/contrib/samples/stc/.cvsignore
new file mode 100644 (file)
index 0000000..bfe355b
--- /dev/null
@@ -0,0 +1 @@
+stctest.res
diff --git a/contrib/samples/stc/makefile.vc b/contrib/samples/stc/makefile.vc
new file mode 100644 (file)
index 0000000..956b781
--- /dev/null
@@ -0,0 +1,14 @@
+# File:                makefile.vc  For stectrl
+# Author:      Robin Dunn
+# Created:     1-Feb-2000
+# Updated:
+
+WXDIR = $(WXWIN)
+PROGRAM = stctest
+
+OBJECTS = $(PROGRAM).obj
+EXTRALIBS = $(WXDIR)\contrib\lib\stc$(LIBEXT).lib
+EXTRAINC = -I$(WXDIR)\contrib\include
+
+!include $(WXDIR)\src\makeprog.vc
+
diff --git a/contrib/samples/stc/stctest.cpp b/contrib/samples/stc/stctest.cpp
new file mode 100644 (file)
index 0000000..fe337aa
--- /dev/null
@@ -0,0 +1,204 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        stctest.cpp
+// Purpose:     sample of using wxStyledTextCtrl
+// Author:      Robin Dunn
+// Modified by:
+// Created:     3-Feb-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+    #pragma implementation "stctest.cpp"
+    #pragma interface "stctest.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+// for all others, include the necessary headers (this file is usually all you
+// need because it includes almost all "standard" wxWindows headers
+#ifndef WX_PRECOMP
+    #include "wx/wx.h"
+#endif
+
+#include <wx/wfstream.h>
+
+#include <wx/stc/stc.h>
+
+//----------------------------------------------------------------------
+
+class MyApp : public wxApp
+{
+public:
+    virtual bool OnInit();
+};
+
+//----------------------------------------------------------------------
+
+// Define a new frame type: this is going to be our main frame
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
+
+    void OnQuit(wxCommandEvent& event);
+    void OnAbout(wxCommandEvent& event);
+    void OnStyleNeeded(wxStyledTextEvent& event);
+
+private:
+    wxStyledTextCtrl* ed;
+
+    DECLARE_EVENT_TABLE()
+};
+
+
+// IDs for the controls and the menu commands
+enum
+{
+    // menu items
+    ID_Quit = 1,
+    ID_About,
+    ID_ED
+};
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU            (ID_Quit,  MyFrame::OnQuit)
+    EVT_MENU            (ID_About, MyFrame::OnAbout)
+    EVT_STC_STYLENEEDED (ID_ED, MyFrame::OnStyleNeeded)
+END_EVENT_TABLE()
+
+IMPLEMENT_APP(MyApp)
+
+//----------------------------------------------------------------------
+// `Main program' equivalent: the program execution "starts" here
+
+bool MyApp::OnInit()
+{
+    MyFrame *frame = new MyFrame("Testing wxStyledTextCtrl",
+                                 wxPoint(5, 5), wxSize(400, 600));
+
+    frame->Show(TRUE);
+    return TRUE;
+}
+
+//----------------------------------------------------------------------
+
+// frame constructor
+MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
+       : wxFrame((wxFrame *)NULL, -1, title, pos, size)
+{
+#ifdef __WXMAC__
+    // we need this in order to allow the about menu relocation, since ABOUT is
+    // not the default id of the about menu
+    wxApp::s_macAboutMenuItemId = ID_About;
+#endif
+
+
+    // create a menu bar
+    wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF);
+
+    // the "About" item should be in the help menu
+    wxMenu *helpMenu = new wxMenu;
+    helpMenu->Append(ID_About, "&About...\tCtrl-A", "Show about dialog");
+
+    menuFile->Append(ID_Quit, "E&xit\tAlt-X", "Quit this program");
+
+    // now append the freshly created menu to the menu bar...
+    wxMenuBar *menuBar = new wxMenuBar();
+    menuBar->Append(menuFile, "&File");
+    menuBar->Append(helpMenu, "&Help");
+
+    // ... and attach this menu bar to the frame
+    SetMenuBar(menuBar);
+
+#if wxUSE_STATUSBAR
+    CreateStatusBar(2);
+    SetStatusText("Testing wxStyledTextCtrl");
+#endif // wxUSE_STATUSBAR
+
+
+    //----------------------------------------
+    // Setup the editor
+    ed = new wxStyledTextCtrl(this, ID_ED);
+
+    // Default font
+    wxFont font(8, wxMODERN, wxNORMAL, wxNORMAL);
+    ed->StyleSetFont(wxSTC_STYLE_DEFAULT, font);
+    ed->StyleClearAll();
+
+    ed->StyleSetForeground(0,  wxColour(0x80, 0x80, 0x80));
+    ed->StyleSetForeground(1,  wxColour(0x00, 0x7f, 0x00));
+    //ed->StyleSetForeground(2,  wxColour(0x00, 0x7f, 0x00));
+    ed->StyleSetForeground(3,  wxColour(0x7f, 0x7f, 0x7f));
+    ed->StyleSetForeground(4,  wxColour(0x00, 0x7f, 0x7f));
+    ed->StyleSetForeground(5,  wxColour(0x00, 0x00, 0x7f));
+    ed->StyleSetForeground(6,  wxColour(0x7f, 0x00, 0x7f));
+    ed->StyleSetForeground(7,  wxColour(0x7f, 0x00, 0x7f));
+    ed->StyleSetForeground(8,  wxColour(0x00, 0x7f, 0x7f));
+    ed->StyleSetForeground(9,  wxColour(0x7f, 0x7f, 0x7f));
+    ed->StyleSetForeground(10, wxColour(0x00, 0x00, 0x00));
+    ed->StyleSetForeground(11, wxColour(0x00, 0x00, 0x00));
+    ed->StyleSetBold(5,  TRUE);
+    ed->StyleSetBold(10, TRUE);
+
+#ifdef __WXMSW__
+    ed->StyleSetSpec(2, "fore:#007f00,bold,face:Arial,size:7");
+#else
+    ed->StyleSetSpec(2, "fore:#007f00,bold,face:Helvetica,size:7");
+#endif
+
+    // give it some text to play with
+    wxFile   file("stctest.cpp");
+    wxString st;
+
+    char* buff = st.GetWriteBuf(file.Length());
+    file.Read(buff, file.Length());
+    st.UngetWriteBuf();
+
+    ed->InsertText(0, st);
+    ed->EmptyUndoBuffer();
+
+    ed->SetLexer(wxSTC_LEX_CPP);
+    ed->SetKeywords(0,
+                    "asm auto bool break case catch char class const "
+                    "const_cast continue default delete do double "
+                    "dynamic_cast else enum explicit export extern "
+                    "false float for friend goto if inline int long "
+                    "mutable namespace new operator private protected "
+                    "public register reinterpret_cast return short signed "
+                    "sizeof static static_cast struct switch template this "
+                    "throw true try typedef typeid typename union unsigned "
+                    "using virtual void volatile wchar_t while");
+
+}
+
+
+// event handlers
+
+void MyFrame::OnStyleNeeded(wxStyledTextEvent& event) {
+    int currEndStyled = ed->GetEndStyled();
+    ed->Colourise(currEndStyled, event.GetPosition());
+}
+
+
+
+
+void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+    // TRUE is to force the frame to close
+    Close(TRUE);
+}
+
+void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+    wxString msg;
+    msg.Printf( _T("Testing wxStyledTextCtrl...\n"));
+
+    wxMessageBox(msg, "About This Test", wxOK | wxICON_INFORMATION, this);
+}
diff --git a/contrib/samples/stc/stctest.rc b/contrib/samples/stc/stctest.rc
new file mode 100644 (file)
index 0000000..b86c4e2
--- /dev/null
@@ -0,0 +1 @@
+#include "wx/msw/wx.rc"
diff --git a/contrib/src/stc/PlatWX.cpp b/contrib/src/stc/PlatWX.cpp
new file mode 100644 (file)
index 0000000..0dbd3d5
--- /dev/null
@@ -0,0 +1,585 @@
+// Scintilla source code edit control
+// PlatWX.cxx - implementation of platform facilities on wxWindows
+// Copyright 1998-1999 by Neil Hodgson <neilh@scintilla.org>
+//                        Robin Dunn <robin@aldunn.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+
+#include "Platform.h"
+#include "wx/stc/stc.h"
+
+Point Point::FromLong(long lpoint) {
+    return Point(lpoint & 0xFFFF, lpoint >> 32);
+}
+
+wxRect wxRectFromPRectangle(PRectangle prc) {
+    wxRect rc(prc.left, prc.top,
+              prc.right-prc.left+1, prc.bottom-prc.top+1);
+    return rc;
+}
+
+PRectangle PRectangleFromwxRect(wxRect rc) {
+    return PRectangle(rc.GetLeft(), rc.GetTop(), rc.GetRight(), rc.GetBottom());
+}
+
+Colour::Colour(long lcol) {
+    co.Set(lcol & 0xff, (lcol >> 8) & 0xff, (lcol >> 16) & 0xff);
+}
+
+Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
+    co.Set(red, green, blue);
+}
+
+bool Colour::operator==(const Colour &other) const {
+    return co == other.co;
+}
+
+long Colour::AsLong() const {
+    return (((long)co.Blue()  << 16) |
+            ((long)co.Green() <<  8) |
+            ((long)co.Red()));
+}
+
+unsigned int Colour::GetRed() {
+    return co.Red();
+}
+
+unsigned int Colour::GetGreen() {
+    return co.Green();
+}
+
+unsigned int Colour::GetBlue() {
+    return co.Blue();
+}
+
+Palette::Palette() {
+    used = 0;
+    allowRealization = false;
+}
+
+Palette::~Palette() {
+    Release();
+}
+
+void Palette::Release() {
+    used = 0;
+}
+
+// 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 < numEntries) {
+            entries[used].desired = cp.desired;
+            entries[used].allocated = cp.desired;
+            used++;
+        }
+    } else {
+        for (int i=0; i < used; i++) {
+            if (entries[i].desired == cp.desired) {
+                cp.allocated = entries[i].allocated;
+                return;
+            }
+        }
+        cp.allocated = cp.desired;
+    }
+}
+
+void Palette::Allocate(Window &) {
+    if (allowRealization) {
+    }
+}
+
+
+Font::Font() {
+    id = 0;
+    ascent = 0;
+}
+
+Font::~Font() {
+}
+
+void Font::Create(const char *faceName, int size, bool bold, bool italic) {
+    Release();
+    id = new wxFont(size,
+                    wxDEFAULT,
+                    italic ? wxITALIC :  wxNORMAL,
+                    bold ? wxBOLD : wxNORMAL,
+                    false,
+                    faceName);
+}
+
+
+void Font::Release() {
+    if (id)
+        delete id;
+    id = 0;
+}
+
+
+Surface::Surface() :
+    hdc(0), hdcOwned(0), bitmap(0),
+    x(0), y(0) {
+}
+
+Surface::~Surface() {
+    Release();
+}
+
+void Surface::Release() {
+    if (bitmap) {
+        ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
+        delete bitmap;
+        bitmap = 0;
+    }
+    if (hdcOwned) {
+        delete hdc;
+        hdc = 0;
+        hdcOwned = false;
+    }
+}
+
+
+bool Surface::Initialised() {
+    return hdc != 0;
+}
+
+void Surface::Init() {
+    Release();
+    hdc = new wxMemoryDC();
+    hdcOwned = true;
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::Init(SurfaceID hdc_) {
+    Release();
+    hdc = hdc_;
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::InitPixMap(int width, int height, Surface *surface_) {
+    Release();
+    hdc = new wxMemoryDC(surface_->hdc);
+    hdcOwned = true;
+    bitmap = new wxBitmap(width, height);
+    ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::PenColour(Colour fore) {
+    hdc->SetPen(wxPen(fore.co, 1, wxSOLID));
+}
+
+void Surface::BrushColor(Colour back) {
+    hdc->SetBrush(wxBrush(back.co, wxSOLID));
+}
+
+void Surface::SetFont(Font &font_) {
+    hdc->SetFont(*font_.GetID());
+}
+
+int Surface::LogPixelsY() {
+    return hdc->GetPPI().y;
+}
+
+void Surface::MoveTo(int x_, int y_) {
+    x = x_;
+    y = y_;
+}
+
+void Surface::LineTo(int x_, int y_) {
+    hdc->DrawLine(x,y, x_,y_);
+    x = x_;
+    y = y_;
+}
+
+void Surface::Polygon(Point *pts, int npts, Colour fore,
+                      Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawPolygon(npts, (wxPoint*)pts);
+}
+
+void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::FillRectangle(PRectangle rc, Colour back) {
+    BrushColor(back);
+    hdc->SetPen(*wxTRANSPARENT_PEN);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+    wxBrush br;
+    if (surfacePattern.bitmap)
+        br = wxBrush(*surfacePattern.bitmap);
+    else    // Something is wrong so display in red
+        br = wxBrush(*wxRED, wxSOLID);
+    hdc->SetPen(*wxTRANSPARENT_PEN);
+    hdc->SetBrush(br);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 8);
+}
+
+void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawEllipse(wxRectFromPRectangle(rc));
+}
+
+void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+    hdc->Blit(rc.left, rc.top, rc.Width(), rc.Height(),
+              surfaceSource.hdc, from.x, from.y, wxCOPY);
+}
+
+void Surface::DrawText(PRectangle rc, Font &font, int ybase,
+                       const char *s, int len, Colour fore, Colour back) {
+    SetFont(font);
+    hdc->SetTextForeground(fore.co);
+    hdc->SetTextBackground(back.co);
+    FillRectangle(rc, back);
+
+    // ybase is where the baseline should be, but wxWin uses the upper left
+    // corner, so I need to calculate the real position for the text...
+    hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
+}
+
+void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) {
+    SetFont(font);
+    hdc->SetTextForeground(fore.co);
+    hdc->SetTextBackground(back.co);
+    FillRectangle(rc, back);
+    hdc->SetClippingRegion(wxRectFromPRectangle(rc));
+
+    // see comments above
+    hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
+    hdc->DestroyClippingRegion();
+}
+
+int Surface::WidthText(Font &font, const char *s, int len) {
+    SetFont(font);
+    int w;
+    int h;
+    hdc->GetTextExtent(wxString(s, len), &w, &h);
+    return w;
+}
+
+void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) {
+    SetFont(font);
+    int totalWidth = 0;
+    for (int i=0; i<len; i++) {
+        int w;
+        int h;
+        hdc->GetTextExtent(s[i], &w, &h);
+        totalWidth += w;
+        positions[i] = totalWidth;
+    }
+}
+
+int Surface::WidthChar(Font &font, char ch) {
+    SetFont(font);
+    int w;
+    int h;
+    hdc->GetTextExtent(ch, &w, &h);
+    return w;
+}
+
+#define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+int Surface::Ascent(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    font.ascent = h - d;
+    return font.ascent;
+}
+
+int Surface::Descent(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    return d;
+}
+
+int Surface::InternalLeading(Font &font) {
+    return 0;
+}
+
+int Surface::ExternalLeading(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    return e;
+}
+
+int Surface::Height(Font &font) {
+    SetFont(font);
+    return hdc->GetCharHeight();
+}
+
+int Surface::AverageCharWidth(Font &font) {
+    SetFont(font);
+    return hdc->GetCharWidth();
+}
+
+int Surface::SetPalette(Palette *pal, bool inBackGround) {
+    return 0;  // **** figure out what to do with palettes...
+}
+
+void Surface::SetClip(PRectangle rc) {
+    hdc->SetClippingRegion(wxRectFromPRectangle(rc));
+}
+
+
+
+Window::~Window() {
+}
+
+void Window::Destroy() {
+    if (id)
+        id->Destroy();
+    id = 0;
+}
+
+bool Window::HasFocus() {
+    return wxWindow::FindFocus() == id;
+}
+
+PRectangle Window::GetPosition() {
+    wxRect rc(id->GetPosition(), id->GetSize());
+    return PRectangleFromwxRect(rc);
+}
+
+void Window::SetPosition(PRectangle rc) {
+    id->SetSize(rc.left, rc.top, rc.Width(), rc.Height());
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window) {
+    SetPosition(rc);  // ????
+}
+
+PRectangle Window::GetClientPosition() {
+    wxSize sz = id->GetClientSize();
+    return  PRectangle(0, 0, sz.x - 1, sz.y - 1);
+}
+
+void Window::Show(bool show) {
+    id->Show(show);
+}
+
+void Window::InvalidateAll() {
+    id->Refresh(false);
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+    id->Refresh(false, &wxRectFromPRectangle(rc));
+}
+
+void Window::SetFont(Font &font) {
+    id->SetFont(*font.GetID());
+}
+
+void Window::SetCursor(Cursor curs) {
+    int cursorId;
+
+    switch (curs) {
+    case cursorText:
+        cursorId = wxCURSOR_IBEAM;
+        break;
+    case cursorArrow:
+        cursorId = wxCURSOR_ARROW;
+        break;
+    case cursorUp:
+        cursorId = wxCURSOR_ARROW; // ** no up arrow...  wxCURSOR_UPARROW;
+        break;
+    case cursorWait:
+        cursorId = wxCURSOR_WAIT;
+        break;
+    case cursorHoriz:
+        cursorId = wxCURSOR_SIZEWE;
+        break;
+    case cursorVert:
+        cursorId = wxCURSOR_SIZENS;
+        break;
+    case cursorReverseArrow:
+        cursorId = wxCURSOR_POINT_RIGHT;
+        break;
+    default:
+        cursorId = wxCURSOR_ARROW;
+        break;
+    }
+
+    id->SetCursor(wxCursor(cursorId));
+}
+
+
+void Window::SetTitle(const char *s) {
+    id->SetTitle(s);
+}
+
+
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+void ListBox::Create(Window &parent, int ctrlID) {
+    id = new wxListBox(parent.id, ctrlID, wxDefaultPosition, wxDefaultSize,
+                       0, NULL, wxLB_SINGLE | wxLB_SORT);
+}
+
+void ListBox::Clear() {
+    ((wxListBox*)id)->Clear();
+}
+
+void ListBox::Append(char *s) {
+    ((wxListBox*)id)->Append(s);
+}
+
+int ListBox::Length() {
+    return ((wxListBox*)id)->Number();
+}
+
+void ListBox::Select(int n) {
+    ((wxListBox*)id)->SetSelection(n);
+}
+
+int ListBox::GetSelection() {
+    return ((wxListBox*)id)->GetSelection();
+}
+
+int ListBox::Find(const char *prefix) {
+    return ((wxListBox*)id)->FindString(prefix);
+}
+
+void ListBox::GetValue(int n, char *value, int len) {
+    wxString text = ((wxListBox*)id)->GetString(n);
+    strncpy(value, text.c_str(), len);
+    value[len-1] = '\0';
+}
+
+void ListBox::Sort() {
+    // wxWindows keeps sorted so no need to sort
+}
+
+
+Menu::Menu() : id(0) {
+}
+
+void Menu::CreatePopUp() {
+    Destroy();
+    id = new wxMenu();
+}
+
+void Menu::Destroy() {
+    if (id)
+        delete id;
+    id = 0;
+}
+
+void Menu::Show(Point pt, Window &w) {
+    w.GetID()->PopupMenu(id, pt.x - 4, pt.y);
+    Destroy();
+}
+
+
+Colour Platform::Chrome() {
+    wxColour c;
+    c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
+    return Colour(c.Red(), c.Green(), c.Blue());
+}
+
+Colour Platform::ChromeHighlight() {
+    wxColour c;
+    c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT);
+    return Colour(c.Red(), c.Green(), c.Blue());
+}
+
+const char *Platform::DefaultFont() {
+    return wxNORMAL_FONT->GetFaceName();
+}
+
+int Platform::DefaultFontSize() {
+    return 8;
+}
+
+unsigned int Platform::DoubleClickTime() {
+    return 500;   // **** ::GetDoubleClickTime();
+}
+
+void Platform::DebugDisplay(const char *s) {
+    wxLogDebug(s);
+}
+
+bool Platform::IsKeyDown(int key) {
+    return false;  // I don't think we'll need this.
+}
+
+long Platform::SendScintilla(WindowID w,
+                             unsigned int msg,
+                             unsigned long wParam,
+                             long lParam) {
+
+    wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
+    return stc->SendMsg(msg, wParam, lParam);
+}
+
+
+// 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
+
+void Platform::DebugPrintf(const char *format, ...) {
+#ifdef TRACE
+    char buffer[2000];
+    va_list pArguments;
+    va_start(pArguments, format);
+    vsprintf(buffer,format,pArguments);
+    va_end(pArguments);
+    Platform::DebugDisplay(buffer);
+#endif
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+    if (val > maxVal)
+        val = maxVal;
+    if (val < minVal)
+        val = minVal;
+    return val;
+}
+
+
+
+
+
+
diff --git a/contrib/src/stc/README.txt b/contrib/src/stc/README.txt
new file mode 100644 (file)
index 0000000..46bc58f
--- /dev/null
@@ -0,0 +1,47 @@
+This contrib is the wxStyledTextCtrl, which is a wrapper around the
+Scintilla edit control.  (See www.scintilla.org)
+
+There is still VERY MUCH to be done, most notable of which is a more
+advanced sample that exercises more of the code.  (I havn't tested
+AutoComplete or CallTips, or most of the event types at all yet.)  And
+also documentation, adding wrappers for some new scintilla
+functionality, building and testing on wxGTK, etc.  Be patient, it all
+will get there soon.
+
+
+
+Let me describe a bit about the architecture I am implementing...
+Obviously there is the Platform layer which implements the varioius
+platform classes by using wxWindows classes and filling in where
+needed.  Then there is a ScintillaWX class that is derived from
+ScintillaBase and implements the necessary virtual methods that
+Scintilla needs to fully funciton.  This class however is not meant to
+ever be used directly by wx programmers.  I call it one end of the
+bridge between the wx and Scintilla worlds.  The other end of the
+bridge is a class called wxStyledTextCtrl that looks, feels and acts
+like other classes in wxWindows.  Here is a diagram:
+
+
+ +------------------+          +-------------------+
+ | wxStyledTextCtrl |--bridge--|    ScintillaWX    |
+ +------------------+          +-------------------+
+                               |   ScintillaBase   |
+                               +-------------------+
+                               |       Editor      |
+                               +-------------------+
+                               |     PlatWX        |
+                               +-------------------+
+
+
+wxStyledTextCtrl derives from wxControl so it has a window that can be
+drawn upon.  When a wxStyledTextCtrl is constructed it constructs a
+ScintillaWX for itself and passes itself to the scintilla object to be
+set as the wMain and wDraw attributes.  All method calls on the STC
+are sent over the bridge in the form of calls to ScintiallWX::WndProc.
+All notifications are sent back over the bridge and turned into
+wxEvents.
+
+
+Robin
+
+
diff --git a/contrib/src/stc/ScintillaWX.cpp b/contrib/src/stc/ScintillaWX.cpp
new file mode 100644 (file)
index 0000000..5b82473
--- /dev/null
@@ -0,0 +1,457 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        ScintillaWX.cxx
+// Purpose:     A wxWindows implementation of Scintilla.  A class derived
+//              from ScintillaBase that uses the "wx platform" defined in
+//              PlatformWX.cxx  This class is one end of a bridge between
+//              the wx world and the Scintilla world.  It needs a peer
+//              object of type wxStyledTextCtrl to function.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#include "ScintillaWX.h"
+#include "wx/stc/stc.h"
+
+
+//----------------------------------------------------------------------
+
+const int H_SCROLL_MAX  = 2000;
+const int H_SCROLL_STEP = 20;
+const int H_SCROLL_PAGE = 200;
+
+//----------------------------------------------------------------------
+// Helper classes
+
+class wxSTCTimer : public wxTimer {
+public:
+    wxSTCTimer(ScintillaWX* swx) {
+        this->swx = swx;
+    }
+
+    void Notify() {
+        swx->DoTick();
+    }
+
+private:
+    ScintillaWX* swx;
+};
+
+
+
+bool wxSTCDropTarget::OnDropText(wxCoord x, wxCoord y, const wxString& data) {
+    return swx->DoDropText(x, y, data);
+}
+
+wxDragResult  wxSTCDropTarget::OnEnter(wxCoord x, wxCoord y, wxDragResult def) {
+    return swx->DoDragEnter(x, y, def);
+}
+
+wxDragResult  wxSTCDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult def) {
+    return swx->DoDragOver(x, y, def);
+}
+
+void  wxSTCDropTarget::OnLeave() {
+    swx->DoDragLeave();
+}
+
+
+
+//----------------------------------------------------------------------
+// Constructor/Destructor
+
+
+ScintillaWX::ScintillaWX(wxStyledTextCtrl* win) {
+    capturedMouse = false;
+    wMain = win;
+    wDraw = win;
+    stc   = win;
+    Initialise();
+}
+
+
+ScintillaWX::~ScintillaWX() {
+    SetTicking(false);
+}
+
+//----------------------------------------------------------------------
+// base class virtuals
+
+
+void ScintillaWX::Initialise() {
+    //ScintillaBase::Initialise();
+    dropTarget.SetScintilla(this);
+    stc->SetDropTarget(&dropTarget);
+}
+
+
+void ScintillaWX::Finalise() {
+    ScintillaBase::Finalise();
+}
+
+
+void ScintillaWX::StartDrag() {
+    wxDropSource        source;
+    wxTextDataObject    data(dragChars);
+    wxDragResult        result;
+
+    source.SetData(data);
+    result = source.DoDragDrop(TRUE);
+    if (result == wxDragMove && dropWentOutside)
+        ClearSelection();
+    inDragDrop = FALSE;
+    SetDragPosition(invalidPosition);
+}
+
+
+void ScintillaWX::SetTicking(bool on) {
+    wxSTCTimer* steTimer;
+    if (timer.ticking != on) {
+        timer.ticking = on;
+        if (timer.ticking) {
+            steTimer = new wxSTCTimer(this);
+            steTimer->Start(timer.tickSize);
+            timer.tickerID = (int)steTimer;
+        } else {
+            steTimer = (wxSTCTimer*)timer.tickerID;
+            steTimer->Stop();
+            delete steTimer;
+            timer.tickerID = 0;
+        }
+    }
+    timer.ticksToWait = caret.period;
+}
+
+
+void ScintillaWX::SetMouseCapture(bool on) {
+    if (on)
+        wMain.GetID()->CaptureMouse();
+    else
+        wMain.GetID()->ReleaseMouse();
+    capturedMouse = on;
+}
+
+
+bool ScintillaWX::HaveMouseCapture() {
+    return capturedMouse;
+}
+
+
+void ScintillaWX::ScrollText(int linesToMove) {
+    int dy = vs.lineHeight * (linesToMove);
+    // TODO: calculate the rectangle to refreshed...
+    wMain.GetID()->ScrollWindow(0, dy);
+}
+
+void ScintillaWX::SetVerticalScrollPos() {
+    wMain.GetID()->SetScrollPos(wxVERTICAL, topLine);
+}
+
+void ScintillaWX::SetHorizontalScrollPos() {
+    wMain.GetID()->SetScrollPos(wxHORIZONTAL, xOffset);
+}
+
+
+bool ScintillaWX::ModifyScrollBars(int nMax, int nPage) {
+    bool modified = false;
+    int  sbMax    = wMain.GetID()->GetScrollRange(wxVERTICAL);
+    int  sbThumb  = wMain.GetID()->GetScrollThumb(wxVERTICAL);
+    int  sbPos    = wMain.GetID()->GetScrollPos(wxVERTICAL);
+
+
+    if (sbMax != nMax || sbThumb != nPage) {
+        wMain.GetID()->SetScrollbar(wxVERTICAL, sbPos, nPage, nMax);
+        modified = true;
+    }
+
+    sbMax    = wMain.GetID()->GetScrollRange(wxHORIZONTAL);
+    sbThumb  = wMain.GetID()->GetScrollThumb(wxHORIZONTAL);
+    if ((sbMax != H_SCROLL_MAX) || (sbThumb != H_SCROLL_STEP)) {
+        wMain.GetID()->SetScrollbar(wxHORIZONTAL, 0, H_SCROLL_STEP, H_SCROLL_MAX);
+        modified = true;
+    }
+    return modified;
+}
+
+
+void ScintillaWX::NotifyChange() {
+    stc->NotifyChange();
+}
+
+
+void ScintillaWX::NotifyParent(SCNotification scn) {
+    stc->NotifyParent(&scn);
+}
+
+
+
+void ScintillaWX::Copy() {
+    if (currentPos != anchor) {
+        char* text = CopySelectionRange();
+        textDO.SetText(text);
+        wxTheClipboard->Open();
+        wxTheClipboard->SetData(&textDO);
+        wxTheClipboard->Close();
+    }
+}
+
+
+void ScintillaWX::Paste() {
+    pdoc->BeginUndoAction();
+    ClearSelection();
+
+    wxTextDataObject data;
+    bool canPaste;
+
+    wxTheClipboard->Open();
+    canPaste = wxTheClipboard->GetData(data);
+    wxTheClipboard->Close();
+    if (canPaste) {
+        wxString str = data.GetText();
+        int      len = str.Length();
+        pdoc->InsertString(currentPos, str.c_str(), len);
+        SetEmptySelection(currentPos + len);
+    }
+
+    pdoc->EndUndoAction();
+    NotifyChange();
+    Redraw();
+}
+
+
+bool ScintillaWX::CanPaste() {
+    wxTextDataObject data;
+    bool canPaste;
+
+    wxTheClipboard->Open();
+    canPaste = wxTheClipboard->GetData(data);
+    wxTheClipboard->Close();
+
+    return canPaste;
+}
+
+void ScintillaWX::CreateCallTipWindow(PRectangle) {
+    ct.wCallTip = new wxWindow(wDraw.GetID(), -1);
+    ct.wDraw = ct.wCallTip;
+}
+
+
+void ScintillaWX::AddToPopUp(const char *label, int cmd, bool enabled) {
+    if (!label[0])
+        popup.GetID()->AppendSeparator();
+    else
+        popup.GetID()->Append(cmd, label);
+
+    if (!enabled)
+        popup.GetID()->Enable(cmd, enabled);
+
+    // TODO:  need to create event handler mappings for the cmd ID
+}
+
+
+void ScintillaWX::ClaimSelection() {
+
+}
+
+
+LRESULT ScintillaWX::DefWndProc(UINT /*iMessage*/, WPARAM /*wParam*/, LPARAM /*lParam*/) {
+    return 0;
+}
+
+LRESULT ScintillaWX::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+    switch (iMessage) {
+    case EM_CANPASTE:
+        return CanPaste();
+    default:
+        return ScintillaBase::WndProc(iMessage, wParam, lParam);
+    }
+    return 0;
+}
+
+
+
+//----------------------------------------------------------------------
+// Event delegates
+
+void ScintillaWX::DoPaint(wxDC* dc, wxRect rect) {
+
+    paintState = painting;
+    Surface surfaceWindow;
+    surfaceWindow.Init(dc);
+    PRectangle rcPaint = PRectangleFromwxRect(rect);
+    dc->BeginDrawing();
+    Paint(&surfaceWindow, rcPaint);
+    dc->EndDrawing();
+    surfaceWindow.Release();
+    if (paintState == paintAbandoned) {
+        // Painting area was insufficient to cover new styling or brace highlight positions
+        FullPaint();
+    }
+    paintState = notPainting;
+}
+
+
+void ScintillaWX::DoHScroll(int type, int pos) {
+    int xPos = xOffset;
+    switch (type) {
+    case wxEVT_SCROLLWIN_LINEUP:
+        xPos -= H_SCROLL_STEP;
+        break;
+    case wxEVT_SCROLLWIN_LINEDOWN:
+        xPos += H_SCROLL_STEP;
+        break;
+    case wxEVT_SCROLLWIN_PAGEUP:
+        xPos -= H_SCROLL_PAGE;
+        break;
+    case wxEVT_SCROLLWIN_PAGEDOWN:
+        xPos += H_SCROLL_PAGE;
+        break;
+    case wxEVT_SCROLLWIN_TOP:
+        xPos = 0;
+        break;
+    case wxEVT_SCROLLWIN_BOTTOM:
+        xPos = H_SCROLL_MAX;
+        break;
+    case wxEVT_SCROLLWIN_THUMBTRACK:
+        xPos = pos;
+        break;
+    }
+    HorizontalScrollTo(xPos);
+}
+
+void ScintillaWX::DoVScroll(int type, int pos) {
+    int topLineNew = topLine;
+    switch (type) {
+    case wxEVT_SCROLLWIN_LINEUP:
+        topLineNew -= 1;
+        break;
+    case wxEVT_SCROLLWIN_LINEDOWN:
+        topLineNew += 1;
+        break;
+    case wxEVT_SCROLLWIN_PAGEUP:
+        topLineNew -= LinesToScroll();
+        break;
+    case wxEVT_SCROLLWIN_PAGEDOWN:
+        topLineNew += LinesToScroll();
+        break;
+    case wxEVT_SCROLLWIN_TOP:
+        topLineNew = 0;
+        break;
+    case wxEVT_SCROLLWIN_BOTTOM:
+        topLineNew = MaxScrollPos();
+        break;
+    case wxEVT_SCROLLWIN_THUMBTRACK:
+        topLineNew = pos;
+        break;
+    }
+    ScrollTo(topLineNew);
+}
+
+void ScintillaWX::DoSize(int width, int height) {
+    PRectangle rcClient(0,0,width,height);
+    SetScrollBarsTo(rcClient);
+    DropGraphics();
+}
+
+void ScintillaWX::DoLoseFocus(){
+    DropCaret();
+}
+
+void ScintillaWX::DoGainFocus(){
+    ShowCaretAtCurrentPosition();
+}
+
+void ScintillaWX::DoSysColourChange() {
+    InvalidateStyleData();
+}
+
+void ScintillaWX::DoButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+    ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+void ScintillaWX::DoButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+    ButtonUp(pt, curTime, ctrl);
+}
+
+void ScintillaWX::DoButtonMove(Point pt) {
+    ButtonMove(pt);
+}
+
+
+void ScintillaWX::DoAddChar(char ch) {
+    AddChar(ch);
+}
+
+int  ScintillaWX::DoKeyDown(int key, bool shift, bool ctrl, bool alt) {
+    return KeyDown(key, shift, ctrl, alt);
+}
+
+
+void ScintillaWX::DoCommand(int ID) {
+    Command(ID);
+}
+
+
+void ScintillaWX::DoContextMenu(Point pt) {
+    ContextMenu(pt);
+}
+
+
+//----------------------------------------------------------------------
+
+bool ScintillaWX::DoDropText(long x, long y, const wxString& data) {
+    SetDragPosition(invalidPosition);
+    int movePos = PositionFromLocation(Point(x,y));
+    DropAt(movePos, data, dragResult == wxDragMove, FALSE); // TODO: rectangular?
+    return TRUE;
+}
+
+
+wxDragResult ScintillaWX::DoDragEnter(wxCoord x, wxCoord y, wxDragResult def) {
+    return def;
+}
+
+
+wxDragResult ScintillaWX::DoDragOver(wxCoord x, wxCoord y, wxDragResult def) {
+    SetDragPosition(PositionFromLocation(Point(x, y)));
+    dragResult = def;
+    return def;
+}
+
+
+void ScintillaWX::DoDragLeave() {
+    SetDragPosition(invalidPosition);
+}
+
+//----------------------------------------------------------------------
+
+// Redraw all of text area. This paint will not be abandoned.
+void ScintillaWX::FullPaint() {
+    paintState = painting;
+    rcPaint = GetTextRectangle();
+    wxClientDC dc(wMain.GetID());
+    Surface surfaceWindow;
+    surfaceWindow.Init(&dc);
+    Paint(&surfaceWindow, rcPaint);
+    surfaceWindow.Release();
+    paintState = notPainting;
+}
+
+
+void ScintillaWX::DoScrollToLine(int line) {
+    ScrollTo(line);
+}
+
+
+void ScintillaWX::DoScrollToColumn(int column) {
+    HorizontalScrollTo(column * vs.spaceWidth);
+}
+
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
diff --git a/contrib/src/stc/ScintillaWX.h b/contrib/src/stc/ScintillaWX.h
new file mode 100644 (file)
index 0000000..d25eb18
--- /dev/null
@@ -0,0 +1,148 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        ScintillaWX.h
+// Purpose:     A wxWindows implementation of Scintilla.  A class derived
+//              from ScintillaBase that uses the "wx platform" defined in
+//              PlatWX.cpp.  This class is one end of a bridge between
+//              the wx world and the Scintilla world.  It needs a peer
+//              object of type wxStyledTextCtrl to function.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ScintillaWX_h__
+#define __ScintillaWX_h__
+
+//----------------------------------------------------------------------
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+#include <wx/wx.h>
+#include <wx/dataobj.h>
+#include <wx/clipbrd.h>
+#include <wx/dnd.h>
+
+//----------------------------------------------------------------------
+
+class wxStyledTextCtrl;           // forward
+class ScintillaWX;
+
+
+//----------------------------------------------------------------------
+// Helper classes
+
+class wxSTCDropTarget : public wxTextDropTarget {
+public:
+    void SetScintilla(ScintillaWX* swx) {
+        this->swx = swx;
+    }
+
+    bool OnDropText(wxCoord x, wxCoord y, const wxString& data);
+    wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def);
+    wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def);
+    void OnLeave();
+
+private:
+    ScintillaWX* swx;
+};
+
+
+//----------------------------------------------------------------------
+
+class ScintillaWX : public ScintillaBase {
+public:
+
+    ScintillaWX(wxStyledTextCtrl* win);
+    ~ScintillaWX();
+
+    // base class virtuals
+    virtual void Initialise();
+    virtual void Finalise();
+    virtual void StartDrag();
+    virtual void SetTicking(bool on);
+    virtual void SetMouseCapture(bool on);
+    virtual bool HaveMouseCapture();
+    virtual void ScrollText(int linesToMove);
+    virtual void SetVerticalScrollPos();
+    virtual void SetHorizontalScrollPos();
+    virtual bool ModifyScrollBars(int nMax, int nPage);
+    virtual void Copy();
+    virtual void Paste();
+    virtual void CreateCallTipWindow(PRectangle rc);
+    virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+    virtual void ClaimSelection();
+
+    virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+    virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+
+    virtual void NotifyChange();
+    virtual void NotifyParent(SCNotification scn);
+
+
+    // Event delegates
+    void DoPaint(wxDC* dc, wxRect rect);
+    void DoHScroll(int type, int pos);
+    void DoVScroll(int type, int pos);
+    void DoSize(int width, int height);
+    void DoLoseFocus();
+    void DoGainFocus();
+    void DoSysColourChange();
+    void DoButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+    void DoButtonUp(Point pt, unsigned int curTime, bool ctrl);
+    void DoButtonMove(Point pt);
+    void DoAddChar(char ch);
+    int  DoKeyDown(int key, bool shift, bool ctrl, bool alt);
+    void DoTick() { Tick(); }
+
+    bool DoDropText(long x, long y, const wxString& data);
+    wxDragResult DoDragEnter(wxCoord x, wxCoord y, wxDragResult def);
+    wxDragResult DoDragOver(wxCoord x, wxCoord y, wxDragResult def);
+    void DoDragLeave();
+
+    void DoCommand(int ID);
+    void DoContextMenu(Point pt);
+
+
+    // helpers
+    void FullPaint();
+    bool CanPaste();
+    bool GetHideSelection() { return hideSelection; }
+    void DoScrollToLine(int line);
+    void DoScrollToColumn(int column);
+
+private:
+    bool                capturedMouse;
+    wxStyledTextCtrl*   stc;
+
+    wxTextDataObject    textDO;
+    wxSTCDropTarget     dropTarget;
+    wxDragResult        dragResult;
+};
+
+//----------------------------------------------------------------------
+#endif
diff --git a/contrib/src/stc/makefile.vc b/contrib/src/stc/makefile.vc
new file mode 100644 (file)
index 0000000..8e91828
--- /dev/null
@@ -0,0 +1,106 @@
+# File:                makefile.vc  For stectrl
+# Author:      Robin Dunn
+# Created:     1-Feb-2000
+# Updated:
+
+
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+SCINTILLA=.\scintilla
+S=$(SCINTILLA)\src
+EXTRAINC=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)\contrib\include
+NOPCH=1
+
+!include $(WXDIR)\src\makevc.env
+
+OBJECTS = \
+       $(D)\Accessor.obj       \
+       $(D)\AutoComplete.obj   \
+       $(D)\CallTip.obj        \
+       $(D)\CellBuffer.obj     \
+       $(D)\ContractionState.obj\
+       $(D)\Document.obj       \
+       $(D)\Editor.obj         \
+       $(D)\Indicator.obj      \
+       $(D)\KeyMap.obj         \
+       $(D)\KeyWords.obj       \
+       $(D)\LineMarker.obj     \
+       $(D)\PropSet.obj        \
+       $(D)\ScintillaBase.obj  \
+       $(D)\Style.obj          \
+       $(D)\ViewStyle.obj      \
+                               \
+       $(D)\PlatWX.obj         \
+       $(D)\ScintillaWX.obj    \
+       $(D)\stc.obj            \
+
+
+
+
+LIBTARGET = $(WXDIR)\contrib\lib\stc$(LIBEXT).lib
+
+all:    $(D) $(LIBTARGET)
+
+$(D) :
+       mkdir $(D)
+
+wx:
+        cd $(WXDIR)\src\msw
+        nmake -f makefile.vc FINAL=$(FINAL)
+        cd $(THISDIR)
+
+wxclean:
+        cd $(WXDIR)\src\msw
+        nmake -f makefile.vc clean
+        cd $(THISDIR)
+
+
+
+
+$(LIBTARGET): $(OBJECTS)
+       -erase $(LIBTARGET)
+       $(implib) @<<
+-out:$(LIBTARGET)
+-machine:$(CPU)
+$(OBJECTS)
+<<
+
+
+$(PROGRAM).exe: $(D)\$(PROGRAM).obj  $(DUMMYOBJ) $(WXLIB) $(LIBTARGET) $(PROGRAM).res
+       $(link) @<<
+-out:$(PROGRAM).exe
+$(LINKFLAGS)
+$(DUMMYOBJ) $(D)\$(PROGRAM).obj $(LIBTARGET) $(PROGRAM).res
+$(LIBS)
+<<
+
+$(PROGRAM).res :      $(PROGRAM).rc $(WXDIR)\include\wx\msw\wx.rc
+    $(rc) -r /i$(WXDIR)\include -fo$@ $(PROGRAM).rc
+
+
+
+{$(S)}.cxx{$(D)}.obj:
+       $(cc) @<<
+$(CPPFLAGS) /c /Fo$@ /Tp $<
+<<
+
+{}.cpp{$(D)}.obj:
+       $(cc) @<<
+$(CPPFLAGS) /c /Fo$@ /Tp $<
+<<
+
+
+show:
+       @echo $(CPPFLAGS)
+
+
+clean:
+        -erase $(D)\*.obj
+        -erase *.sbr
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.pdb
+        -erase $(LIBTARGET)
+
diff --git a/contrib/src/stc/scintilla/README.txt b/contrib/src/stc/scintilla/README.txt
new file mode 100644 (file)
index 0000000..705fb99
--- /dev/null
@@ -0,0 +1,7 @@
+This directory contains copies of the scintilla/src and
+scintilla/include directories from the Scintilla/SCiTE source
+distribution.  All other code needed to implement Scintilla on top of
+wxWindows is located in the directory above this one.
+
+The current version of the Scintilla code is somewhere between 1.22
+and 1.23, (from their CVS.)
diff --git a/contrib/src/stc/scintilla/include/Accessor.h b/contrib/src/stc/scintilla/include/Accessor.h
new file mode 100644 (file)
index 0000000..1bba4af
--- /dev/null
@@ -0,0 +1,76 @@
+// SciTE - Scintilla based Text Editor
+// Accessor.h - rapid easy access to contents of a Scintilla
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+class Accessor {
+protected:
+       // bufferSize is a trade off between time taken to copy the characters and SendMessage overhead
+       // slopSize positions the buffer before the desired position in case there is some backtracking
+       enum {bufferSize=4000, slopSize=bufferSize/8};
+       char buf[bufferSize+1];
+       WindowID id;
+       PropSet &props;
+       int startPos;
+       int endPos;
+       int lenDoc;
+       int offset;     // Optional but including an offset makes GCC generate better code 
+       void Fill(int position);
+public:
+       Accessor(WindowID id_, PropSet &props_, int offset_=0) : 
+                       id(id_), props(props_), startPos(0x7FFFFFFF), endPos(0), 
+                       lenDoc(-1), offset(offset_) {
+       }
+       char operator[](int position) {
+               position += offset;
+               if (position < startPos || position >= endPos) {
+                       Fill(position);
+               }
+               return buf[position - startPos];
+       }
+       char SafeGetCharAt(int position, char chDefault=' ') {
+               // Safe version of operator[], returning a defined value for invalid position 
+               position += offset;
+               if (position < startPos || position >= endPos) {
+                       Fill(position);
+                       if (position < startPos || position >= endPos) {
+                               // Position is outside range of document 
+                               return chDefault;
+                       }
+               }
+               return buf[position - startPos];
+       }
+       char StyleAt(int position);
+       int GetLine(int position);
+       int LineStart(int line);
+       int LevelAt(int line);
+       int Length();
+       void Flush() {
+               startPos = 0x7FFFFFFF;
+               lenDoc = -1;
+       }
+       int GetLineState(int line);
+       int SetLineState(int line, int state);
+       PropSet &GetPropSet() { return props; }
+};
+
+class StylingContext : public Accessor {
+       char styleBuf[bufferSize];
+       int validLen;
+       char chFlags;
+       char chWhile;
+       unsigned int startSeg;
+public:
+       StylingContext(WindowID id_, PropSet &props_, int offset_=0) : 
+               Accessor(id_,props_,offset_), validLen(0), chFlags(0) {}
+       void StartAt(unsigned int start, char chMask=31);
+       void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
+       void ColourSegment(unsigned int start, unsigned int end, int chAttr);
+       unsigned int GetStartSegment() { return startSeg; }
+       void StartSegment(unsigned int pos);
+       void ColourTo(unsigned int pos, int chAttr);
+       int GetLine(int position);
+       void SetLevel(int line, int level);
+       void Flush();
+};
+
diff --git a/contrib/src/stc/scintilla/include/KeyWords.h b/contrib/src/stc/scintilla/include/KeyWords.h
new file mode 100644 (file)
index 0000000..2cc03b7
--- /dev/null
@@ -0,0 +1,8 @@
+// SciTE - Scintilla based Text Editor
+// KeyWords.h - colourise for particular languages
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle, 
+       int language, WordList *keywordlists[], StylingContext &styler);
+
diff --git a/contrib/src/stc/scintilla/include/Platform.h b/contrib/src/stc/scintilla/include/Platform.h
new file mode 100644 (file)
index 0000000..3a5e981
--- /dev/null
@@ -0,0 +1,392 @@
+// Scintilla source code edit control
+// Platform.h - interface to platform facilities
+// Also includes some basic utilities
+// Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+// PLAT_GTK = GTK+ on Linux, PLAT_WIN = Win32 API on Win32 OS
+// PLAT_WX is wxWindows on any supported platform
+// Could also have PLAT_GTKWIN = GTK+ on Win32 OS in future
+
+#define PLAT_GTK 0
+#define PLAT_WIN 0
+#define PLAT_WX  0
+
+#if defined(__WX__)
+#undef PLAT_WX
+#define PLAT_WX  1
+
+#elif defined(GTK)
+#undef PLAT_GTK
+#define PLAT_GTK 1
+
+#else
+#undef PLAT_WIN
+#define PLAT_WIN 1
+
+#endif
+
+
+// Include the main header for each platform
+
+#if PLAT_GTK
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#endif
+
+#if PLAT_WIN
+#define _WIN32_WINNT  0x0400 // Otherwise some required stuff gets ifdef'd out
+// Vassili Bourdo: shut up annoying Visual C++ warnings:
+#ifdef _MSC_VER
+#pragma warning(disable: 4800 4244 4309)
+#endif
+#include <windows.h>
+#include <richedit.h>
+#endif
+
+#if PLAT_WX
+#include <wx/wx.h>
+#endif
+
+// Underlying the implementation of the platform classes are platform specific types.
+// Sometimes these need to be passed around by client code so they are defined here
+
+#if PLAT_GTK
+typedef GdkColor ColourID;
+typedef GdkFont* FontID;
+typedef GdkDrawable* SurfaceID;
+typedef GtkWidget* WindowID;
+typedef GtkItemFactory* MenuID;
+#endif
+
+#if PLAT_WIN
+typedef COLORREF ColourID;
+typedef HFONT FontID;
+typedef HDC SurfaceID;
+typedef HWND WindowID;
+typedef HMENU MenuID;
+#endif
+
+#if PLAT_WX
+typedef wxColour ColourID;
+typedef wxFont* FontID;
+typedef wxDC* SurfaceID;
+typedef wxWindow* WindowID;
+typedef wxMenu* MenuID;
+#endif
+
+#if PLAT_GTK || PLAT_WX
+#define SHIFT_PRESSED 1
+#define LEFT_CTRL_PRESSED 2
+#define LEFT_ALT_PRESSED 4
+#endif
+
+// Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably
+
+class Point {
+public:
+       int x;
+       int y;
+       
+       Point(int x_=0, int y_=0) : x(x_), y(y_) {
+       }
+
+       // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+       
+       static Point FromLong(long lpoint);
+};
+
+// PRectangle is exactly the same as the Win32 RECT so can be used interchangeably
+// PRectangles contain their top and left sides, but not their right and bottom sides
+class PRectangle {
+public:
+       int left;
+       int top;
+       int right;
+       int bottom;
+
+       PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) :
+               left(left_), top(top_), right(right_), bottom(bottom_) {
+       }
+
+       // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+
+       bool Contains(Point pt) {
+               return (pt.x >= left) && (pt.x <= right) &&
+                       (pt.y >= top) && (pt.y <= bottom);
+       }
+       bool Contains(PRectangle rc) {
+               return (rc.left >= left) && (rc.right <= right) &&
+                       (rc.top >= top) && (rc.bottom <= bottom);
+       }
+       bool Intersects(PRectangle other) {
+               return (right >= other.left) && (left <= other.right) &&
+                       (bottom >= other.top) && (top <= other.bottom);
+       }
+       int Width() { return right - left; }
+       int Height() { return bottom - top; }
+};
+
+#if PLAT_WX
+wxRect wxRectFromPRectangle(PRectangle prc);
+PRectangle PRectangleFromwxRect(wxRect rc);
+#endif
+
+class Colour {
+       ColourID co;
+public:
+       Colour(long lcol=0);
+       Colour(unsigned int red, unsigned int green, unsigned int blue);
+       bool operator==(const Colour &other) const;
+       long AsLong() const;
+       unsigned int GetRed();
+       unsigned int GetGreen();
+       unsigned int GetBlue();
+       
+       friend class Surface;
+       friend class Palette;
+};
+
+// Colour pairs hold a desired colour and the colour that the graphics engine
+// allocates to approximate the desired colour.
+// To make palette management more automatic, ColourPairs could register at 
+// construction time with a palette management object.
+struct ColourPair {
+       Colour desired;
+       Colour allocated;
+
+       ColourPair(Colour desired_=Colour(0,0,0)) {
+               desired = desired_;
+               allocated = desired;
+       }
+};
+
+class Window;  // Forward declaration for Palette
+
+class Palette {
+       int used;
+       enum {numEntries = 100};
+       ColourPair entries[numEntries];
+#if PLAT_GTK
+       GdkColor *allocatedPalette;
+       int allocatedLen;
+#elif PLAT_WIN
+       HPALETTE hpal;
+#elif PLAT_WX
+       // wxPalette* pal;  // **** Is this needed?
+#endif
+public:
+       bool allowRealization;
+       
+       Palette();
+       ~Palette();
+
+       void Release();
+       
+       // This method either adds a colour to the list of wanted colours (want==true)
+       // or retrieves the allocated colour back to the ColourPair.
+       // This is one method to make it easier to keep the code for wanting and retrieving in sync.
+       void WantFind(ColourPair &cp, bool want);
+
+       void Allocate(Window &w);
+       
+       friend class Surface;
+};
+
+class Font {
+       FontID id;
+#if PLAT_WX
+       int ascent;
+#endif
+       // Private so Font objects can not be copied
+       Font(const Font &) {}
+       Font &operator=(const Font &) { id=0; return *this; }
+public:
+       Font();
+       ~Font();
+
+       void Create(const char *faceName, int size, bool bold=false, bool italic=false);
+       void Release();
+
+       FontID GetID() { return id; }
+       friend class Surface;
+};
+
+// A surface abstracts a place to draw
+class Surface {
+private:
+#if PLAT_GTK
+       GdkDrawable *drawable;
+       GdkGC *gc;
+       GdkPixmap *ppixmap;
+       int x;
+       int y;
+       bool inited;
+       bool createdGC;
+#elif PLAT_WIN
+       HDC hdc;
+       bool hdcOwned;
+       HPEN pen;
+       HPEN penOld;
+       HBRUSH brush;
+       HBRUSH brushOld;
+       HFONT font;
+       HFONT fontOld;
+       HBITMAP bitmap;
+       HBITMAP bitmapOld;
+       HPALETTE paletteOld;
+#elif PLAT_WX
+       wxDC* hdc;
+       bool hdcOwned;
+       wxBitmap* bitmap;
+       int x;
+       int y;
+#endif
+
+       // Private so Surface objects can not be copied
+       Surface(const Surface &) {}
+       Surface &operator=(const Surface &) { return *this; }
+#if PLAT_WIN || PLAT_WX
+       void BrushColor(Colour back);
+       void SetFont(Font &font_);
+#endif
+public:
+       Surface();
+       ~Surface();
+       
+       void Init();
+       void Init(SurfaceID hdc_);
+       void InitPixMap(int width, int height, Surface *surface_);
+
+       void Release();
+       bool Initialised();
+       void PenColour(Colour fore);
+       int LogPixelsY();
+       void MoveTo(int x_, int y_);
+       void LineTo(int x_, int y_);
+       void Polygon(Point *pts, int npts, Colour fore, Colour back);
+       void RectangleDraw(PRectangle rc, Colour fore, Colour back);
+       void FillRectangle(PRectangle rc, Colour back);
+       void FillRectangle(PRectangle rc, Surface &surfacePattern);
+       void RoundedRectangle(PRectangle rc, Colour fore, Colour back);
+       void Ellipse(PRectangle rc, Colour fore, Colour back);
+       void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+       void DrawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back);
+       void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back);
+       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);
+};
+
+// Class to hide the details of window manipulation
+// Does not own the window which will normally have a longer life than this object
+class Window {
+       friend class ListBox;
+protected:
+       WindowID id;
+public:
+       Window() : id(0) {}
+       virtual ~Window();
+       Window &operator=(WindowID id_) {
+               id = id_;
+               return *this;
+       }
+       WindowID GetID() { return id; }
+       bool Created() { return id != 0; }
+       void Destroy();
+       bool HasFocus();
+       PRectangle GetPosition();
+       void SetPosition(PRectangle rc);
+       void SetPositionRelative(PRectangle rc, Window relativeTo);
+       PRectangle GetClientPosition();
+       void Show(bool show=true);
+       void InvalidateAll();
+       void InvalidateRectangle(PRectangle rc);
+       void SetFont(Font &font);
+       enum Cursor { cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow };
+       void SetCursor(Cursor curs);
+       void SetTitle(const char *s);
+#if PLAT_WIN
+       LRESULT SendMessage(UINT msg, WPARAM wParam=0, LPARAM lParam=0);
+       int GetDlgCtrlID();
+       HINSTANCE GetInstance();
+#endif
+};
+
+class ListBox : public Window {
+#if PLAT_GTK
+       WindowID list;
+       WindowID scroller;
+       int current;
+#endif
+public:
+       ListBox();
+       virtual ~ListBox();
+       ListBox &operator=(WindowID id_) {
+               id = id_;
+               return *this;
+       }
+       void Create(Window &parent, int ctrlID);
+       void Clear();
+       void Append(char *s);
+       int Length();
+       void Select(int n);
+       int GetSelection();
+       int Find(const char *prefix);
+       void GetValue(int n, char *value, int len);
+       void Sort();
+};
+
+class Menu {
+       MenuID id;
+public:
+       Menu();
+       MenuID GetID() { return id; }
+       void CreatePopUp();
+       void Destroy();
+       void Show(Point pt, Window &w);
+};
+
+// Platform class used to retrieve system wide parameters such as double click speed
+// and chrome colour. Not a creatable object, more of a module with several functions.
+class Platform {
+       // Private so Platform objects can not be copied
+       Platform(const Platform &) {}
+       Platform &operator=(const Platform &) { return *this; }
+public:
+       // Should be private because no new Platforms are ever created
+       // but gcc warns about this
+       Platform() {}
+       ~Platform() {}
+       static Colour Chrome();
+       static Colour ChromeHighlight();
+       static const char *DefaultFont();
+       static int DefaultFontSize();
+       static unsigned int DoubleClickTime();
+       static void DebugDisplay(const char *s);
+       static bool IsKeyDown(int key);
+       static long SendScintilla(
+               WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
+       
+       // These are utility functions not really tied to a platform
+       static int Minimum(int a, int b);
+       static int Maximum(int a, int b);
+       static void DebugPrintf(const char *format, ...);
+       static int Clamp(int val, int minVal, int maxVal);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/include/PropSet.h b/contrib/src/stc/scintilla/include/PropSet.h
new file mode 100644 (file)
index 0000000..31da01f
--- /dev/null
@@ -0,0 +1,180 @@
+// SciTE - Scintilla based Text Editor
+// PropSet.h - a java style properties file module
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PROPSET_H
+#define PROPSET_H
+
+bool EqualCaseInsensitive(const char *a, const char *b);
+
+// Define another string class.
+// While it would be 'better' to use std::string, that doubles the executable size.
+
+inline char *StringDup(const char *s) {
+       if (!s)
+               return 0;
+       char *sNew = new char[strlen(s) + 1];
+       if (sNew)
+               strcpy(sNew, s);
+       return sNew;
+}
+
+class SString {
+       char *s;
+public:
+       SString() {
+               s = 0;
+       }
+       SString(const SString &source) {
+               s = StringDup(source.s);
+       }
+       SString(const char *s_) {
+               s = StringDup(s_);
+       }
+       SString(int i) {
+               char number[100];
+               sprintf(number, "%0d", i);
+               //itoa(i, number, 10);
+               s = StringDup(number);
+       }
+       ~SString() {
+               delete []s;
+               s = 0;
+       }
+       SString &operator=(const SString &source) {
+               if (this != &source) {
+                       delete []s;
+                       s = StringDup(source.s);
+               }
+               return *this;
+       }
+       bool operator==(const SString &other) const {
+               if ((s == 0) && (other.s == 0))
+                       return true;
+               if ((s == 0) || (other.s == 0))
+                       return false;
+               return strcmp(s, other.s) == 0;
+       }
+       bool operator==(const char *sother) const {
+               if ((s == 0) && (sother == 0))
+                       return true;
+               if ((s == 0) || (sother == 0))
+                       return false;
+               return strcmp(s, sother) == 0;
+       }
+       const char *c_str() const {
+               if (s)
+                       return s;
+               else
+                       return "";
+       }
+       int length() const {
+               if (s)
+                       return strlen(s);
+               else
+                       return 0;
+       }
+       char operator[](int i) {
+               if (s)
+                       return s[i];
+               else
+                       return '\0';
+       }
+       SString &operator +=(const char *sother) {
+               int len = length();
+               int lenOther = strlen(sother);
+               char *sNew = new char[len + lenOther + 1];
+               if (sNew) {
+                       if (s)
+                               memcpy(sNew, s, len);
+                       memcpy(sNew + len, sother, lenOther);
+                       sNew[len + lenOther] = '\0';
+                       delete []s;
+                       s = sNew;
+               }
+               return *this;
+       }
+       int value() {
+               if (s)
+                       return atoi(s);
+               else 
+                       return 0;
+       }
+};
+
+class PropSet {
+private:
+       char **vals;
+       int size;
+       int used;
+public:
+       PropSet *superPS;
+       PropSet();
+       ~PropSet();
+       void EnsureCanAddEntry();
+       void Set(const char *key, const char *val);
+       void Set(char *keyval);
+       SString Get(const char *key);
+       int GetInt(const char *key, int defaultValue=0);
+       SString GetWild(const char *keybase, const char *filename);
+       SString GetNewExpand(const char *keybase, const char *filename);
+       void Clear();
+       void ReadFromMemory(const char *data, int len);
+       void Read(const char *filename);
+};
+
+// This is a fixed length list of strings suitable for display  in combo boxes
+// as a memory of user entries
+template<int sz>
+class EntryMemory {
+       SString entries[sz];
+public:
+       void Insert(SString s) {
+               for (int i=0;i<sz;i++) {
+                       if (entries[i] == s) {
+                               for (int j=i;j>0;j--) {
+                                       entries[j] = entries[j-1];
+                               }
+                               entries[0] = s;
+                               return;
+                       }
+               }
+               for (int k=sz-1;k>0;k--) {
+                       entries[k] = entries[k-1];
+               }
+               entries[0] = s;
+       }
+       int Length() const {
+               int len = 0;
+               for (int i=0;i<sz;i++)
+                       if (entries[i].length())
+                               len++;
+               return len;
+       }
+       SString At(int n) const {
+               return entries[n];
+       }
+};
+
+class WordList {
+public:
+       // Each word contains at least one character - a empty word acts as sentinal at the end.
+       char **words;
+       char *list;
+       int len;
+       bool onlyLineEnds;      // Delimited by any white space or only line ends
+       int starts[256];
+       WordList(bool onlyLineEnds_ = false) : 
+               words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {}
+       ~WordList() { Clear(); }
+       operator bool() { return list; }
+       const char *operator[](int ind) { return words[ind]; }
+       void Clear();
+       void Set(const char *s);
+       char *Allocate(int size);
+       void SetFromAllocated();
+       bool InList(const char *s);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/include/SciLexer.h b/contrib/src/stc/scintilla/include/SciLexer.h
new file mode 100644 (file)
index 0000000..d6667e4
--- /dev/null
@@ -0,0 +1,134 @@
+// Scintilla source code edit control
+// SciLexer - interface to the added lexer functions in the SciLexer version of the edit control
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCILEXER_H
+#define SCILEXER_H
+
+// SciLexer features - not in standard Scintilla
+
+#define SCLEX_CONTAINER 0
+#define SCLEX_NULL 1
+#define SCLEX_PYTHON 2
+#define SCLEX_CPP 3
+#define SCLEX_HTML 4
+#define SCLEX_XML 5
+#define SCLEX_PERL 6
+#define SCLEX_SQL 7
+#define SCLEX_VB 8
+#define SCLEX_PROPERTIES 9
+#define SCLEX_ERRORLIST 10
+#define SCLEX_MAKEFILE 11
+#define SCLEX_BATCH 12
+
+// Lexical states for SCLEX_PYTHON
+#define SCE_P_DEFAULT 0
+#define SCE_P_COMMENTLINE 1
+#define SCE_P_NUMBER 2
+#define SCE_P_STRING 3
+#define SCE_P_CHARACTER 4
+#define SCE_P_WORD 5
+#define SCE_P_TRIPLE 6
+#define SCE_P_TRIPLEDOUBLE 7
+#define SCE_P_CLASSNAME 8
+#define SCE_P_DEFNAME 9
+#define SCE_P_OPERATOR 10
+#define SCE_P_IDENTIFIER 11
+
+// Lexical states for SCLEX_CPP, SCLEX_VB
+#define SCE_C_DEFAULT 0
+#define SCE_C_COMMENT 1
+#define SCE_C_COMMENTLINE 2
+#define SCE_C_COMMENTDOC 3
+#define SCE_C_NUMBER 4
+#define SCE_C_WORD 5
+#define SCE_C_STRING 6
+#define SCE_C_CHARACTER 7
+#define SCE_C_PUNTUATION 8
+#define SCE_C_PREPROCESSOR 9
+#define SCE_C_OPERATOR 10
+#define SCE_C_IDENTIFIER 11
+#define SCE_C_STRINGEOL 12
+
+// Lexical states for SCLEX_HTML, SCLEX_xML
+#define SCE_H_DEFAULT 0
+#define SCE_H_TAG 1
+#define SCE_H_TAGUNKNOWN 2
+#define SCE_H_ATTRIBUTE 3
+#define SCE_H_ATTRIBUTEUNKNOWN 4
+#define SCE_H_NUMBER 5
+#define SCE_H_DOUBLESTRING 6
+#define SCE_H_SINGLESTRING 7
+#define SCE_H_OTHER 8
+#define SCE_H_COMMENT 9
+#define SCE_H_ENTITY 10
+// Embedded Javascript
+#define SCE_HJ_START 11
+#define SCE_HJ_DEFAULT 12
+#define SCE_HJ_COMMENT 13
+#define SCE_HJ_COMMENTLINE 14
+#define SCE_HJ_COMMENTDOC 15
+#define SCE_HJ_NUMBER 16
+#define SCE_HJ_WORD 17
+#define SCE_HJ_KEYWORD 18
+#define SCE_HJ_DOUBLESTRING 19
+#define SCE_HJ_SINGLESTRING 20
+#define SCE_HJ_SYMBOLS 21
+#define SCE_HJ_STRINGEOL 28
+// XML and ASP
+#define SCE_H_TAGEND 22
+#define SCE_H_XMLSTART 23
+#define SCE_H_XMLEND 24
+#define SCE_H_SCRIPT 25
+#define SCE_H_ASP 26
+#define SCE_H_ASPAT 27
+// Embedded VBScript
+#define SCE_HB_START 40
+#define SCE_HB_DEFAULT 41
+#define SCE_HB_COMMENTLINE 42
+#define SCE_HB_NUMBER 43
+#define SCE_HB_WORD 44
+#define SCE_HB_STRING 45
+#define SCE_HB_IDENTIFIER 46
+#define SCE_HB_STRINGEOL 47
+// Embedded Python
+#define SCE_HP_START 50
+#define SCE_HP_DEFAULT 51
+#define SCE_HP_COMMENTLINE 52
+#define SCE_HP_NUMBER 53
+#define SCE_HP_STRING 54
+#define SCE_HP_CHARACTER 55
+#define SCE_HP_WORD 56
+#define SCE_HP_TRIPLE 57
+#define SCE_HP_TRIPLEDOUBLE 58
+#define SCE_HP_CLASSNAME 59
+#define SCE_HP_DEFNAME 60
+#define SCE_HP_OPERATOR 61
+#define SCE_HP_IDENTIFIER 62
+
+// Lexical states for SCLEX_PERL
+#define SCE_PL_DEFAULT 0
+#define SCE_PL_HERE 1
+#define SCE_PL_COMMENTLINE 2
+#define SCE_PL_POD 3
+#define SCE_PL_NUMBER 4
+#define SCE_PL_WORD 5
+#define SCE_PL_STRING 6
+#define SCE_PL_CHARACTER 7
+#define SCE_PL_PUNCTUATION 8
+#define SCE_PL_PREPROCESSOR 9
+#define SCE_PL_OPERATOR 10
+#define SCE_PL_IDENTIFIER 11
+#define SCE_PL_SCALAR 12
+#define SCE_PL_ARRAY 13
+#define SCE_PL_HASH 14
+#define SCE_PL_SYMBOLTABLE 15
+#define SCE_PL_REF 16
+#define SCE_PL_REGEX 17
+#define SCE_PL_REGSUBST 18
+#define SCE_PL_LONGQUOTE 19
+#define SCE_PL_BACKTICKS 20
+#define SCE_PL_DATASECTION 21
+    
+#endif
diff --git a/contrib/src/stc/scintilla/include/Scintilla.h b/contrib/src/stc/scintilla/include/Scintilla.h
new file mode 100644 (file)
index 0000000..0757216
--- /dev/null
@@ -0,0 +1,415 @@
+// Scintilla source code edit control
+// Scintilla.h - interface to the edit control
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCINTILLA_H
+#define SCINTILLA_H
+
+// Compile-time configuration options
+#define MACRO_SUPPORT 1  // Comment out to remove macro hooks
+
+#if PLAT_GTK
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SCINTILLA(obj)          GTK_CHECK_CAST (obj, scintilla_get_type (), ScintillaObject)
+#define SCINTILLA_CLASS(klass)  GTK_CHECK_CLASS_CAS    T (klass, scintilla_get_type (), ScintillaClass)
+#define IS_SCINTILLA(obj)       GTK_CHECK_TYPE (obj, scintilla_get_type ())
+
+       typedef struct _ScintillaObject ScintillaObject;
+       typedef struct _ScintillaClass  ScintillaClass;
+
+       struct _ScintillaObject
+       {
+               GtkFixed vbox;
+               void *pscin;
+       };
+
+       struct _ScintillaClass
+       {
+               GtkFixedClass parent_class;
+
+               void (* command) (ScintillaObject *ttt);
+               void (* notify) (ScintillaObject *ttt);
+       };
+
+       guint           scintilla_get_type      (void);
+       GtkWidget*      scintilla_new           (void);
+       void            scintilla_set_id        (ScintillaObject *sci,int id);
+       long            scintilla_send_message  (ScintillaObject *sci,int iMessage,int wParam,int lParam);
+
+#include "WinDefs.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#if PLAT_WX
+#include "WinDefs.h"
+#endif
+
+// Both GTK and Windows
+
+#define INVALID_POSITION -1 
+
+// Define start of Scintilla messages to be greater than all edit (EM_*) messages
+// as many EM_ messages can be used.
+#define SCI_START 2000
+#define SCI_OPTIONAL_START 3000
+#define SCI_LEXER_START 4000
+
+#define SCI_ADDTEXT SCI_START + 1
+#define SCI_ADDSTYLEDTEXT SCI_START + 2
+#define SCI_INSERTTEXT SCI_START + 3
+#define SCI_CLEARALL SCI_START + 4
+#define SCI_GETLENGTH SCI_START + 6
+#define SCI_GETCHARAT SCI_START + 7
+#define SCI_GETCURRENTPOS SCI_START + 8
+#define SCI_GETANCHOR SCI_START + 9
+#define SCI_GETSTYLEAT SCI_START + 10
+
+#define SCI_REDO SCI_START + 11
+#define SCI_SETUNDOCOLLECTION SCI_START + 12
+#define SCI_SELECTALL SCI_START + 13
+#define SCI_SETSAVEPOINT SCI_START + 14
+#define SCI_GETSTYLEDTEXT SCI_START + 15
+#define SCI_CANREDO SCI_START + 16
+#define SCI_MARKERLINEFROMHANDLE SCI_START + 17
+#define SCI_MARKERDELETEHANDLE SCI_START + 18
+
+#define SC_UNDOCOLLECT_NONE 0
+#define SC_UNDOCOLLECT_AUTOSTART 1
+
+#define SCI_GETVIEWWS SCI_START + 20
+#define SCI_SETVIEWWS SCI_START + 21
+#define SCI_CHANGEPOSITION SCI_START + 22
+#define SCI_GOTOLINE SCI_START + 24
+#define SCI_GOTOPOS SCI_START + 25
+#define SCI_SETANCHOR SCI_START + 26
+#define SCI_GETCURLINE SCI_START + 27
+#define SCI_GETENDSTYLED SCI_START + 28
+#define SCI_CONVERTEOLS SCI_START + 29
+
+#define SCI_GETEOLMODE SCI_START + 30
+#define SCI_SETEOLMODE SCI_START + 31
+
+#define SC_EOL_CRLF 0
+#define SC_EOL_CR 1
+#define SC_EOL_LF 2
+
+#define SCI_STARTSTYLING SCI_START + 32
+#define SCI_SETSTYLING SCI_START + 33
+
+#define SCI_SETBUFFEREDDRAW SCI_START + 35
+#define SCI_SETTABWIDTH SCI_START + 36
+#define SCI_SETCODEPAGE SCI_START + 37
+#define SCI_SETUSEPALETTE SCI_START + 39
+
+#define MARKER_MAX 31
+
+#define SC_MARK_CIRCLE 0
+#define SC_MARK_ROUNDRECT 1
+#define SC_MARK_ARROW 2
+#define SC_MARK_SMALLRECT 3
+#define SC_MARK_SHORTARROW 4
+#define SC_MARK_EMPTY 5
+#define SC_MARK_ARROWDOWN 6
+#define SC_MARK_MINUS 7
+#define SC_MARK_PLUS 8
+
+#define SCI_MARKERDEFINE SCI_START + 40
+#define SCI_MARKERSETFORE SCI_START + 41
+#define SCI_MARKERSETBACK SCI_START + 42
+#define SCI_MARKERADD SCI_START + 43
+#define SCI_MARKERDELETE SCI_START + 44
+#define SCI_MARKERDELETEALL SCI_START + 45
+#define SCI_MARKERGET SCI_START + 46
+#define SCI_MARKERNEXT SCI_START + 47
+#define SCI_MARKERPREVIOUS SCI_START + 48
+
+#define SC_MARKNUM_FOLDER 30
+#define SC_MARKNUM_FOLDEROPEN 31
+
+#define SC_MASK_FOLDERS ((1<<SC_MARKNUM_FOLDER) | (1<<SC_MARKNUM_FOLDEROPEN))
+
+#define SC_MARGIN_SYMBOL 0
+#define SC_MARGIN_NUMBER 1
+
+#define SCI_SETMARGINTYPEN SCI_START + 240
+#define SCI_GETMARGINTYPEN SCI_START + 241
+#define SCI_SETMARGINWIDTHN SCI_START + 242
+#define SCI_GETMARGINWIDTHN SCI_START + 243
+#define SCI_SETMARGINMASKN SCI_START + 244
+#define SCI_GETMARGINMASKN SCI_START + 245
+#define SCI_SETMARGINSENSITIVEN SCI_START + 246
+#define SCI_GETMARGINSENSITIVEN SCI_START + 247
+
+#define STYLE_DEFAULT 32
+#define STYLE_LINENUMBER 33
+#define STYLE_BRACELIGHT 34
+#define STYLE_BRACEBAD 35
+#define STYLE_CONTROLCHAR 36
+#define STYLE_MAX 63
+
+#define SCI_STYLECLEARALL SCI_START + 50
+#define SCI_STYLESETFORE SCI_START + 51
+#define SCI_STYLESETBACK SCI_START + 52
+#define SCI_STYLESETBOLD SCI_START + 53
+#define SCI_STYLESETITALIC SCI_START + 54
+#define SCI_STYLESETSIZE SCI_START + 55
+#define SCI_STYLESETFONT SCI_START + 56
+#define SCI_STYLESETEOLFILLED SCI_START + 57
+#define SCI_STYLERESETDEFAULT SCI_START + 58
+
+#define SCI_SETSELFORE SCI_START + 67
+#define SCI_SETSELBACK SCI_START + 68
+#define SCI_SETCARETFORE SCI_START + 69
+
+#define SCI_ASSIGNCMDKEY SCI_START + 70
+#define SCI_CLEARCMDKEY SCI_START + 71
+#define SCI_CLEARALLCMDKEYS SCI_START + 72
+
+#define SCI_SETSTYLINGEX SCI_START + 73
+
+#define SCI_GETCARETPERIOD SCI_START + 75
+#define SCI_SETCARETPERIOD SCI_START + 76
+#define SCI_SETWORDCHARS SCI_START + 77
+
+#define SCI_BEGINUNDOACTION SCI_START + 78
+#define SCI_ENDUNDOACTION SCI_START + 79
+
+#define INDIC_MAX 7
+
+#define INDIC_PLAIN 0
+#define INDIC_SQUIGGLE 1
+#define INDIC_TT 2
+
+#define INDIC0_MASK 32
+#define INDIC1_MASK 64
+#define INDIC2_MASK 128
+#define INDICS_MASK (INDIC0_MASK | INDIC1_MASK | INDIC2_MASK)
+
+#define SCI_INDICSETSTYLE SCI_START + 80
+#define SCI_INDICGETSTYLE SCI_START + 81
+#define SCI_INDICSETFORE SCI_START + 82
+#define SCI_INDICGETFORE SCI_START + 83
+
+#define SCI_SETSTYLEBITS SCI_START + 90
+#define SCI_GETSTYLEBITS SCI_START + 91
+#define SCI_SETLINESTATE SCI_START + 92
+#define SCI_GETLINESTATE SCI_START + 93
+#define SCI_GETMAXLINESTATE SCI_START + 94
+
+#define SCI_AUTOCSHOW SCI_START + 100
+#define SCI_AUTOCCANCEL SCI_START + 101
+#define SCI_AUTOCACTIVE SCI_START + 102
+#define SCI_AUTOCPOSSTART SCI_START + 103
+#define SCI_AUTOCCOMPLETE SCI_START + 104
+#define SCI_AUTOCSTOPS SCI_START + 105
+
+#define SCI_CALLTIPSHOW SCI_START + 200
+#define SCI_CALLTIPCANCEL SCI_START + 201
+#define SCI_CALLTIPACTIVE SCI_START + 202
+#define SCI_CALLTIPPOSSTART SCI_START + 203
+#define SCI_CALLTIPSETHLT SCI_START + 204
+#define SCI_CALLTIPSETBACK SCI_START + 205
+
+#define SC_FOLDLEVELBASE 0x400
+#define SC_FOLDLEVELWHITEFLAG 0x1000
+#define SC_FOLDLEVELHEADERFLAG 0x2000
+#define SC_FOLDLEVELNUMBERMASK 0x0FFF
+
+#define SCI_VISIBLEFROMDOCLINE SCI_START + 220
+#define SCI_DOCLINEFROMVISIBLE SCI_START + 221
+#define SCI_SETFOLDLEVEL SCI_START + 222
+#define SCI_GETFOLDLEVEL SCI_START + 223
+#define SCI_GETLASTCHILD SCI_START + 224
+#define SCI_GETFOLDPARENT SCI_START + 225
+#define SCI_SHOWLINES SCI_START + 226
+#define SCI_HIDELINES SCI_START + 227
+#define SCI_GETLINEVISIBLE SCI_START + 228
+#define SCI_SETFOLDEXPANDED SCI_START + 229
+#define SCI_GETFOLDEXPANDED SCI_START + 230
+#define SCI_TOGGLEFOLD SCI_START + 231
+#define SCI_ENSUREVISIBLE SCI_START + 232
+#define SCI_SETFOLDFLAGS SCI_START + 233
+
+// Key messages
+#define SCI_LINEDOWN SCI_START + 300
+#define SCI_LINEDOWNEXTEND SCI_START + 301
+#define SCI_LINEUP SCI_START + 302
+#define SCI_LINEUPEXTEND SCI_START + 303
+#define SCI_CHARLEFT SCI_START + 304
+#define SCI_CHARLEFTEXTEND SCI_START + 305
+#define SCI_CHARRIGHT SCI_START + 306
+#define SCI_CHARRIGHTEXTEND SCI_START + 307
+#define SCI_WORDLEFT SCI_START + 308
+#define SCI_WORDLEFTEXTEND SCI_START + 309
+#define SCI_WORDRIGHT SCI_START + 310
+#define SCI_WORDRIGHTEXTEND SCI_START + 311
+#define SCI_HOME SCI_START + 312
+#define SCI_HOMEEXTEND SCI_START + 313
+#define SCI_LINEEND SCI_START + 314
+#define SCI_LINEENDEXTEND SCI_START + 315
+#define SCI_DOCUMENTSTART SCI_START + 316
+#define SCI_DOCUMENTSTARTEXTEND SCI_START + 317
+#define SCI_DOCUMENTEND SCI_START + 318
+#define SCI_DOCUMENTENDEXTEND SCI_START + 319
+#define SCI_PAGEUP SCI_START + 320
+#define SCI_PAGEUPEXTEND SCI_START + 321
+#define SCI_PAGEDOWN SCI_START + 322
+#define SCI_PAGEDOWNEXTEND SCI_START + 323
+#define SCI_EDITTOGGLEOVERTYPE SCI_START + 324
+#define SCI_CANCEL SCI_START + 325
+#define SCI_DELETEBACK SCI_START + 326
+#define SCI_TAB SCI_START + 327
+#define SCI_BACKTAB SCI_START + 328
+#define SCI_NEWLINE SCI_START + 329
+#define SCI_FORMFEED SCI_START + 330
+#define SCI_VCHOME SCI_START + 331
+#define SCI_VCHOMEEXTEND SCI_START + 332
+#define SCI_ZOOMIN SCI_START + 333
+#define SCI_ZOOMOUT SCI_START + 334
+#define SCI_DELWORDLEFT SCI_START + 335
+#define SCI_DELWORDRIGHT SCI_START + 336
+
+#define SCI_LINELENGTH SCI_START + 350
+#define SCI_BRACEHIGHLIGHT SCI_START + 351
+#define SCI_BRACEBADLIGHT SCI_START + 352
+#define SCI_BRACEMATCH SCI_START + 353
+#define SCI_GETVIEWEOL SCI_START + 355
+#define SCI_SETVIEWEOL SCI_START + 356
+#define SCI_GETDOCPOINTER SCI_START + 357
+#define SCI_SETDOCPOINTER SCI_START + 358
+#define SCI_SETMODEVENTMASK SCI_START + 359
+
+#define EDGE_NONE 0
+#define EDGE_LINE 1
+#define EDGE_BACKGROUND 2
+
+#define SCI_GETEDGECOLUMN SCI_START + 360
+#define SCI_SETEDGECOLUMN SCI_START + 361
+#define SCI_GETEDGEMODE SCI_START + 362
+#define SCI_SETEDGEMODE SCI_START + 363
+#define SCI_GETEDGECOLOUR SCI_START + 364
+#define SCI_SETEDGECOLOUR SCI_START + 365
+
+#define SCI_SEARCHANCHOR SCI_START + 366
+#define SCI_SEARCHNEXT SCI_START + 367
+#define SCI_SEARCHPREV SCI_START + 368
+
+#define CARET_SLOP 0x01    // Show caret within N lines of edge when it's scrolled to view
+#define CARET_CENTER 0x02  // Center caret on screen when it's scrolled to view
+#define CARET_STRICT 0x04  // OR this with CARET_CENTER to reposition even when visible, or
+                           // OR this with CARET_SLOP to reposition whenever outside slop border
+
+#define SCI_SETCARETPOLICY SCI_START + 369
+
+// GTK+ Specific
+#define SCI_GRABFOCUS SCI_START + 400
+
+// Optional module for macro recording
+#ifdef MACRO_SUPPORT
+typedef void (tMacroRecorder)(UINT iMessage, WPARAM wParam, LPARAM lParam, 
+                              void *userData);
+#define SCI_STARTRECORD SCI_OPTIONAL_START + 1
+#define SCI_STOPRECORD SCI_OPTIONAL_START + 2
+#endif
+
+#define SCI_SETLEXER SCI_LEXER_START + 1
+#define SCI_GETLEXER SCI_LEXER_START + 2
+#define SCI_COLOURISE SCI_LEXER_START + 3
+#define SCI_SETPROPERTY SCI_LEXER_START + 4
+#define SCI_SETKEYWORDS SCI_LEXER_START + 5
+
+// Notifications
+
+// Type of modification and the action which caused the modification
+// These are defined as a bit mask to make it easy to specify which notifications are wanted.
+// One bit is set from each of SC_MOD_* and SC_PERFORMED_*.
+#define SC_MOD_INSERTTEXT 0x1
+#define SC_MOD_DELETETEXT 0x2
+#define SC_MOD_CHANGESTYLE 0x4
+#define SC_MOD_CHANGEFOLD 0x8
+#define SC_PERFORMED_USER 0x10
+#define SC_PERFORMED_UNDO 0x20
+#define SC_PERFORMED_REDO 0x40
+#define SC_LASTSTEPINUNDOREDO 0x100
+
+#define SC_MODEVENTMASKALL 0x377
+
+struct SCNotification {
+       NMHDR nmhdr;
+       int position;                   // SCN_STYLENEEDED, SCN_MODIFIED
+       int ch;                                 // SCN_CHARADDED, SCN_KEY
+       int modifiers;                  // SCN_KEY
+       int modificationType;   // SCN_MODIFIED
+       const char *text;               // SCN_MODIFIED
+       int length;                             // SCN_MODIFIED
+       int linesAdded; // SCN_MODIFIED
+#ifdef MACRO_SUPPORT
+       int message;    // SCN_MACRORECORD
+       int wParam;     // SCN_MACRORECORD
+       int lParam;     // SCN_MACRORECORD
+#endif
+       int line;                       // SCN_MODIFIED
+       int foldLevelNow;       // SCN_MODIFIED
+       int foldLevelPrev;      // SCN_MODIFIED
+       int margin;     // SCN_MARGINCLICK
+};
+
+#define SCN_STYLENEEDED 2000
+#define SCN_CHARADDED 2001
+#define SCN_SAVEPOINTREACHED 2002
+#define SCN_SAVEPOINTLEFT 2003
+#define SCN_MODIFYATTEMPTRO 2004
+// GTK+ Specific to work around focus and accelerator problems:
+#define SCN_KEY 2005
+#define SCN_DOUBLECLICK 2006
+#define SCN_UPDATEUI 2007
+// The old name for SCN_UPDATEUI:
+#define SCN_CHECKBRACE 2007
+#define SCN_MODIFIED 2008
+// Optional module for macro recording
+#ifdef MACRO_SUPPORT
+#define SCN_MACRORECORD 2009
+#endif
+#define SCN_MARGINCLICK 2010
+#define SCN_NEEDSHOWN 2011
+
+#ifdef STATIC_BUILD
+void Scintilla_RegisterClasses(HINSTANCE hInstance);
+#endif
+
+// Deprecation section listing all API features that are deprecated and will
+// will be removed completely in a future version.
+// To enable these features define INCLUDE_DEPRECATED_FEATURES
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+
+// Default style settings. These are deprecated and will be removed in a future version.
+#define SCI_SETFORE SCI_START + 60
+#define SCI_SETBACK SCI_START + 61
+#define SCI_SETBOLD SCI_START + 62
+#define SCI_SETITALIC SCI_START + 63
+#define SCI_SETSIZE SCI_START + 64
+#define SCI_SETFONT SCI_START + 65
+
+#define SCI_APPENDUNDOSTARTACTION SCI_START + 74
+
+#define SC_UNDOCOLLECT_MANUALSTART 2
+
+// Deprecated in release 1.22
+#define SCI_SETMARGINWIDTH SCI_START + 34
+#define SCI_SETLINENUMBERWIDTH SCI_START + 38
+
+#endif
+
+#endif
diff --git a/contrib/src/stc/scintilla/include/WinDefs.h b/contrib/src/stc/scintilla/include/WinDefs.h
new file mode 100644 (file)
index 0000000..0b125e7
--- /dev/null
@@ -0,0 +1,218 @@
+// Scintilla source code edit control
+// WinDefs.h - the subset of definitions from Windows needed by Scintilla for GTK+
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef WINDEFS_H
+#define WINDEFS_H
+
+#define WORD short
+#define WPARAM unsigned long
+#define LPARAM long
+#define LRESULT long
+#define DWORD long
+
+#define UINT unsigned int
+#define LPSTR char *
+#define LONG long
+
+/* RTF control */
+#define EM_CANPASTE    (1074)
+#define EM_CANUNDO     (198)
+#define EM_CHARFROMPOS (215)
+#define EM_DISPLAYBAND (1075)
+#define EM_EMPTYUNDOBUFFER     (205)
+#define EM_EXGETSEL    (1076)
+#define EM_EXLIMITTEXT (1077)
+#define EM_EXLINEFROMCHAR      (1078)
+#define EM_EXSETSEL    (1079)
+#define EM_FINDTEXT    (1080)
+#define EM_FINDTEXTEX  (1103)
+#define EM_FINDWORDBREAK       (1100)
+#define EM_FMTLINES    (200)
+#define EM_FORMATRANGE (1081)
+#define EM_GETCHARFORMAT       (1082)
+#define EM_GETEVENTMASK        (1083)
+#define EM_GETFIRSTVISIBLELINE (206)
+#define EM_GETHANDLE   (189)
+#define EM_GETLIMITTEXT        (213)
+#define EM_GETLINE     (196)
+#define EM_GETLINECOUNT        (186)
+#define EM_GETMARGINS  (212)
+#define EM_GETMODIFY   (184)
+#define EM_GETIMECOLOR (1129)
+#define EM_GETIMEOPTIONS       (1131)
+#define EM_GETOPTIONS  (1102)
+#define EM_GETOLEINTERFACE     (1084)
+#define EM_GETPARAFORMAT       (1085)
+#define EM_GETPASSWORDCHAR     (210)
+#define EM_GETPUNCTUATION      (1125)
+#define EM_GETRECT     (178)
+#define EM_GETSEL      (176)
+#define EM_GETSELTEXT  (1086)
+#define EM_GETTEXTRANGE        (1099)
+#define EM_GETTHUMB    (190)
+#define EM_GETWORDBREAKPROC    (209)
+#define EM_GETWORDBREAKPROCEX  (1104)
+#define EM_GETWORDWRAPMODE     (1127)
+#define EM_HIDESELECTION       (1087)
+#define EM_LIMITTEXT   (197)
+#define EM_LINEFROMCHAR        (201)
+#define EM_LINEINDEX   (187)
+#define EM_LINELENGTH  (193)
+#define EM_LINESCROLL  (182)
+#define EM_PASTESPECIAL        (1088)
+#define EM_POSFROMCHAR (214)
+#define EM_REPLACESEL  (194)
+#define EM_REQUESTRESIZE       (1089)
+#define EM_SCROLL      (181)
+#define EM_SCROLLCARET (183)
+#define EM_SELECTIONTYPE       (1090)
+#define EM_SETBKGNDCOLOR       (1091)
+#define EM_SETCHARFORMAT       (1092)
+#define EM_SETEVENTMASK        (1093)
+#define EM_SETHANDLE   (188)
+#define EM_SETIMECOLOR (1128)
+#define EM_SETIMEOPTIONS       (1130)
+#define EM_SETLIMITTEXT        (197)
+#define EM_SETMARGINS  (211)
+#define EM_SETMODIFY   (185)
+#define EM_SETOLECALLBACK      (1094)
+#define EM_SETOPTIONS  (1101)
+#define EM_SETPARAFORMAT       (1095)
+#define EM_SETPASSWORDCHAR     (204)
+#define EM_SETPUNCTUATION      (1124)
+#define EM_SETREADONLY (207)
+#define EM_SETRECT     (179)
+#define EM_SETRECTNP   (180)
+#define EM_SETSEL      (177)
+#define EM_SETTABSTOPS (203)
+#define EM_SETTARGETDEVICE     (1096)
+#define EM_SETWORDBREAKPROC    (208)
+#define EM_SETWORDBREAKPROCEX  (1105)
+#define EM_SETWORDWRAPMODE     (1126)
+#define EM_STREAMIN    (1097)
+#define EM_STREAMOUT   (1098)
+#define EM_UNDO        (199)
+
+#define WM_NULL                (0)
+#define WM_CLEAR       (771)
+#define WM_COMMAND     (273)
+#define WM_COPY        (769)
+#define WM_CUT (768)
+#define WM_GETTEXT     (13)
+#define WM_GETTEXTLENGTH       (14)
+#define WM_NOTIFY      (78)
+#define WM_PASTE       (770)
+#define WM_SETTEXT     (12)
+#define WM_UNDO        (772)
+
+#define EN_CHANGE      (768)
+#define EN_KILLFOCUS (512)
+#define EN_SETFOCUS (256)
+
+#define EC_LEFTMARGIN 1
+#define EC_RIGHTMARGIN 2
+#define EC_USEFONTINFO 0xffff
+
+#if PLAT_GTK
+#define VK_DOWN GDK_Down
+#define VK_UP GDK_Up
+#define VK_LEFT GDK_Left
+#define VK_RIGHT GDK_Right
+#define VK_HOME GDK_Home
+#define VK_END GDK_End
+#define VK_PRIOR GDK_Page_Up
+#define VK_NEXT GDK_Page_Down
+#define VK_DELETE GDK_Delete
+#define VK_INSERT GDK_Insert
+#define VK_ESCAPE GDK_Escape
+#define VK_BACK GDK_BackSpace
+#define VK_TAB GDK_Tab
+#define VK_RETURN GDK_Return
+#define VK_ADD GDK_KP_Add
+#define VK_SUBTRACT GDK_KP_Subtract
+#endif
+
+#if PLAT_WX
+#define VK_DOWN         WXK_DOWN
+#define VK_UP           WXK_UP
+#define VK_LEFT         WXK_LEFT
+#define VK_RIGHT        WXK_RIGHT
+#define VK_HOME         WXK_HOME
+#define VK_END          WXK_END
+#define VK_PRIOR        WXK_PRIOR
+#define VK_NEXT         WXK_NEXT
+#define VK_DELETE       WXK_DELETE
+#define VK_INSERT       WXK_INSERT
+#define VK_ESCAPE       WXK_ESCAPE
+#define VK_BACK         WXK_BACK
+#define VK_TAB          WXK_TAB
+#define VK_RETURN       WXK_RETURN
+#define VK_ADD          WXK_ADD
+#define VK_SUBTRACT     WXK_SUBTRACT
+
+// Are these needed any more
+#define LPSTR char *
+#define LONG long
+#define LPDWORD (long *)
+#endif
+
+/* SELCHANGE structure */
+#define SEL_EMPTY      (0)
+#define SEL_TEXT       (1)
+#define SEL_OBJECT     (2)
+#define SEL_MULTICHAR  (4)
+#define SEL_MULTIOBJECT        (8)
+
+/* FINDREPLACE structure */
+#define FR_MATCHCASE   (0x4)
+#define FR_WHOLEWORD   (0x2)
+#define FR_DOWN                (0x1)
+
+#define SHIFT_PRESSED 1
+#define LEFT_CTRL_PRESSED 2
+#define LEFT_ALT_PRESSED 4
+
+struct RECT {
+       LONG left;
+       LONG top;
+       LONG right;
+       LONG bottom;
+};
+
+struct CHARRANGE {
+       LONG cpMin;
+       LONG cpMax;
+};
+
+struct TEXTRANGE {
+       CHARRANGE chrg;
+       LPSTR lpstrText;
+};
+
+struct FINDTEXTEX {
+       CHARRANGE chrg;
+       LPSTR lpstrText;
+       CHARRANGE chrgText;
+};
+
+struct NMHDR {
+       WindowID hwndFrom;
+       UINT idFrom;
+       UINT code;
+};
+
+struct FORMATRANGE {
+       SurfaceID hdc;
+       SurfaceID hdcTarget;
+       RECT rc;
+       RECT rcPage;
+       CHARRANGE chrg;
+};
+
+#define MAKELONG(a, b) ((a) | ((b) << 16))
+#define LOWORD(x) (x & 0xffff)
+#define HIWORD(x) (x >> 16)
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/Accessor.cxx b/contrib/src/stc/scintilla/src/Accessor.cxx
new file mode 100644 (file)
index 0000000..57b7e4d
--- /dev/null
@@ -0,0 +1,112 @@
+// SciTE - Scintilla based Text Editor
+// Accessor.cxx - rapid easy access to contents of a Scintilla
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "Scintilla.h"
+
+void Accessor::Fill(int position) {
+       if (lenDoc == -1)
+               lenDoc = Platform::SendScintilla(id, WM_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::SendScintilla(id, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr));
+}
+
+char Accessor::StyleAt(int position) {
+       return static_cast<char>(Platform::SendScintilla(
+               id, SCI_GETSTYLEAT, position, 0));
+}
+
+int Accessor::GetLine(int position) {
+       return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0);
+}
+
+int Accessor::LineStart(int line) {
+       return Platform::SendScintilla(id, EM_LINEINDEX, line, 0);
+}
+
+int Accessor::LevelAt(int line) {
+       return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0);
+}
+
+int Accessor::Length() { 
+       if (lenDoc == -1) 
+               lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0);
+       return lenDoc; 
+}
+
+int Accessor::GetLineState(int line) {
+       return Platform::SendScintilla(id, SCI_GETLINESTATE, line);
+}
+
+int Accessor::SetLineState(int line, int state) {
+       return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state);
+}
+
+void StylingContext::StartAt(unsigned int start, char chMask) {
+       Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask);
+}
+
+void StylingContext::ColourSegment(unsigned int start, unsigned int end, int chAttr) {
+       // Only perform styling if non empty range
+       if (end != start - 1) {
+               if (end < start) {
+                       Platform::DebugPrintf("Bad colour positions %d - %d\n", start, end);
+               }
+
+               if (validLen + (end - start + 1) >= bufferSize)
+                       Flush();
+               if (validLen + (end - start + 1) >= bufferSize) {
+                       // Too big for buffer so send directly
+                       Platform::SendScintilla(id, SCI_SETSTYLING, end - start + 1, chAttr);
+               } else {
+                       if (chAttr != chWhile)
+                               chFlags = 0;
+                       chAttr |= chFlags;
+                       for (unsigned int i = start; i <= end; i++) {
+                               styleBuf[validLen++] = chAttr;
+                       }
+               }
+       }
+}
+
+void StylingContext::StartSegment(unsigned int pos) {
+       startSeg = pos;
+}
+
+void StylingContext::ColourTo(unsigned int pos, int chAttr) {
+       ColourSegment(startSeg, pos, chAttr);
+       startSeg = pos+1;
+}
+
+int StylingContext::GetLine(int position) {
+       return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0);
+}
+
+void StylingContext::SetLevel(int line, int level) {
+       Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level);
+}
+
+void StylingContext::Flush() {
+       if (validLen > 0) {
+               Platform::SendScintilla(id, SCI_SETSTYLINGEX, validLen, 
+                       reinterpret_cast<LPARAM>(styleBuf));
+               validLen = 0;
+       }
+}
diff --git a/contrib/src/stc/scintilla/src/AutoComplete.cxx b/contrib/src/stc/scintilla/src/AutoComplete.cxx
new file mode 100644 (file)
index 0000000..c3ec29c
--- /dev/null
@@ -0,0 +1,104 @@
+// Scintilla source code edit control
+// AutoComplete.cxx - defines the auto completion list box
+// Copyright 1998-2000 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 "AutoComplete.h"
+
+AutoComplete::AutoComplete() {
+       lb = 0;
+       active = false;
+       posStart = 0;
+       strcpy(stopChars, "");
+}
+
+AutoComplete::~AutoComplete() {
+       lb.Destroy();
+}
+
+bool AutoComplete::Active() {
+       return active;
+}
+
+void AutoComplete::Start(Window &parent, int ctrlID, int position, int startLen_) {
+       if (!lb.Created()) {
+               lb.Create(parent, ctrlID);
+       }
+       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);
+}
+
+int AutoComplete::SetList(const char *list) {
+       int maxStrLen = 12;
+       lb.Clear();
+       char *words = new char[strlen(list) + 1];
+       if (words) {
+               strcpy(words, list);
+               char *startword = words;
+               int i = 0;
+               for (; words && words[i]; i++) {
+                       if (words[i] == ' ') {
+                               words[i] = '\0';
+                               lb.Append(startword);
+                               maxStrLen = Platform::Maximum(maxStrLen, strlen(startword));
+                               startword = words + i + 1;
+                       }
+               }
+               if (startword) {
+                       lb.Append(startword);
+                       maxStrLen = Platform::Maximum(maxStrLen, strlen(startword));
+               }
+               delete []words;
+       }
+       lb.Sort();
+       return maxStrLen;
+}
+
+void AutoComplete::Show() {
+       lb.Show();
+       lb.Select(0);
+}
+
+void AutoComplete::Cancel() {
+       if (lb.Created()) {
+               lb.Destroy();
+               lb = 0;
+               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) {
+       int pos = lb.Find(word);
+       //Platform::DebugPrintf("Autocompleting at <%s> %d\n", wordCurrent, pos);
+       if (pos != -1)
+               lb.Select(pos);
+}
+
diff --git a/contrib/src/stc/scintilla/src/AutoComplete.h b/contrib/src/stc/scintilla/src/AutoComplete.h
new file mode 100644 (file)
index 0000000..1021602
--- /dev/null
@@ -0,0 +1,43 @@
+// Scintilla source code edit control
+// AutoComplete.h - defines the auto completion list box
+// Copyright 1998-2000 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
+
+class AutoComplete {
+       bool active;
+       char stopChars[256];
+public:
+       ListBox lb;
+       int posStart;
+       int startLen;
+       
+       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, int startLen_);
+       
+       // 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 list string contains a sequence of words separated by spaces
+       int SetList(const char *list);
+       
+       void 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);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/CallTip.cxx b/contrib/src/stc/scintilla/src/CallTip.cxx
new file mode 100644 (file)
index 0000000..ad67402
--- /dev/null
@@ -0,0 +1,168 @@
+// Scintilla source code edit control
+// CallTip.cxx - code for displaying call tips
+// Copyright 1998-2000 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 "CallTip.h"
+
+CallTip::CallTip() {
+       wCallTip = 0;
+       inCallTipMode = false;
+       posStartCallTip = 0;
+       val = 0;
+       startHighlight = 0;
+       endHighlight = 0;
+
+       colourBG.desired = Colour(0xff, 0xff, 0xff);
+       colourUnSel.desired = Colour(0x80, 0x80, 0x80);
+       colourSel.desired = Colour(0, 0, 0x80);
+       colourShade.desired = Colour(0, 0, 0);
+       colourLight.desired = Colour(0xc0, 0xc0, 0xc0);
+}
+
+CallTip::~CallTip() {
+       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);
+}
+
+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);
+       // To make a nice small call tip window, it is only sized to fit most normal characters without accents
+       int lineHeight = surfaceWindow->Height(font);
+       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;
+       char *chunkVal = val;
+       bool moreChunks = true;
+       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;
+               int x = 5;
+               int xEnd = x + surfaceWindow->WidthText(font, chunkVal, thisStartHighlight);
+               rcClient.left = x;
+               rcClient.top = ytext - ascent - 1;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal, thisStartHighlight,
+                                       colourUnSel.allocated, colourBG.allocated);
+               x = xEnd;
+
+               xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisStartHighlight,
+                                                   thisEndHighlight - thisStartHighlight);
+               rcClient.top = ytext;
+               rcClient.left = x;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal + thisStartHighlight, thisEndHighlight - thisStartHighlight,
+                                       colourSel.allocated, colourBG.allocated);
+               x = xEnd;
+
+               xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisEndHighlight,
+                                                   chunkLength - thisEndHighlight);
+               rcClient.left = x;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal + thisEndHighlight, chunkLength - thisEndHighlight,
+                                       colourUnSel.allocated, colourBG.allocated);
+               chunkVal = chunkEnd + 1;
+               ytext += lineHeight;
+       }
+       // 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);
+}
+
+PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
+                                 const char *faceName, int size) {
+       Surface surfaceMeasure;
+       surfaceMeasure.Init();
+       int deviceHeight = (size * surfaceMeasure.LogPixelsY()) / 72;
+       font.Create(faceName, deviceHeight);
+       if (val)
+               delete []val;
+       val = new char[strlen(defn) + 1];
+       if (!val)
+               return PRectangle();
+       strcpy(val, defn);
+       startHighlight = 0;
+       endHighlight = 0;
+       inCallTipMode = true;
+       posStartCallTip = pos;
+       // Look for multiple lines in the text
+       // Only support \n here - simply means container must avoid \r!
+       int width = 0;
+       int numLines = 1;
+       const char *newline;
+       const char *look = val;
+       while ((newline = strchr(look, '\n')) != NULL) {
+               int thisWidth = surfaceMeasure.WidthText(font, look, newline - look);
+               width = Platform::Maximum(width, thisWidth);
+               look = newline + 1;
+               numLines++;
+       }
+       int lastWidth = surfaceMeasure.WidthText(font, look, strlen(look));
+       width = Platform::Maximum(width, lastWidth) + 10;
+       int lineHeight = surfaceMeasure.Height(font);
+       // Extra line for border and an empty line at top and bottom
+       int height = lineHeight * numLines - surfaceMeasure.InternalLeading(font) + 2 + 2;
+       return PRectangle(pt.x -5, pt.y + lineHeight + 1, pt.x + width - 5, pt.y + lineHeight + 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();
+               }
+       }
+}
diff --git a/contrib/src/stc/scintilla/src/CallTip.h b/contrib/src/stc/scintilla/src/CallTip.h
new file mode 100644 (file)
index 0000000..cd5b093
--- /dev/null
@@ -0,0 +1,46 @@
+// Scintilla source code edit control
+// CallTip.h - interface to the call tip control
+// Copyright 1998-2000 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
+
+const char callClassName[] = "CallTip";
+
+class CallTip {
+       int startHighlight;
+       int endHighlight;
+       char *val;
+       Font font;
+public:
+       Window wCallTip;
+       Window wDraw;
+       bool inCallTipMode;
+       int posStartCallTip;
+       ColourPair colourBG;
+       ColourPair colourUnSel;
+       ColourPair colourSel;
+       ColourPair colourShade;
+       ColourPair colourLight;
+       
+       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);
+       
+       // 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);
+               
+       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);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/CellBuffer.cxx b/contrib/src/stc/scintilla/src/CellBuffer.cxx
new file mode 100644 (file)
index 0000000..7776885
--- /dev/null
@@ -0,0 +1,950 @@
+// Scintilla source code edit control
+// CellBuffer.cxx - manages a buffer of cells
+// Copyright 1998-2000 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 "SVector.h"
+#include "CellBuffer.h"
+
+MarkerHandleSet::MarkerHandleSet() {
+       root = 0;
+}
+
+MarkerHandleSet::~MarkerHandleSet() {
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               MarkerHandleNumber *mhnToFree = mhn;
+               mhn = mhn->next;
+               delete mhnToFree;
+       }
+       root = 0;
+}
+
+int MarkerHandleSet::Length() {
+       int c = 0;
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               c++;
+               mhn = mhn->next;
+       }
+       return c;
+}
+
+int MarkerHandleSet::NumberFromHandle(int handle) {
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               if (mhn->handle == handle) {
+                       return mhn->number;
+               }
+               mhn = mhn->next;
+       }
+       return - 1;
+}
+
+int MarkerHandleSet::MarkValue() {
+       unsigned int m = 0;
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               m |= (1 << mhn->number);
+               mhn = mhn->next;
+       }
+       return m;
+}
+
+bool MarkerHandleSet::Contains(int handle) {
+       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);
+       }
+}
+
+void MarkerHandleSet::RemoveNumber(int markerNum) {
+       MarkerHandleNumber **pmhn = &root;
+       while (*pmhn) {
+               MarkerHandleNumber *mhn = *pmhn;
+               if (mhn->number == markerNum) {
+                       *pmhn = mhn->next;
+                       delete mhn;
+                       return;
+               }
+               pmhn = &((*pmhn)->next);
+       }
+}
+
+void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
+       MarkerHandleNumber **pmhn = &root;
+       while (*pmhn) {
+               pmhn = &((*pmhn)->next);
+       }
+       *pmhn = other->root;
+       other->root = 0;
+}
+
+LineVector::LineVector() {
+       linesData = 0;
+       lines = 0;
+       levels = 0;
+       Init();
+}
+
+LineVector::~LineVector() {
+       for (int line = 0; line < lines; line++) {
+               delete linesData[line].handleSet;
+               linesData[line].handleSet = 0;
+       }
+       delete []linesData;
+       linesData = 0;
+       delete []levels;
+       levels = 0;
+}
+
+void LineVector::Init() {
+       for (int line = 0; line < lines; line++) {
+               delete linesData[line].handleSet;
+               linesData[line].handleSet = 0;
+       }
+       delete []linesData;
+       linesData = new LineData[static_cast<int>(growSize)];
+       size = growSize;
+       lines = 1;
+       delete []levels;
+       levels = 0;
+       sizeLevels = 0;
+}
+
+void LineVector::Expand(int sizeNew) {
+       LineData *linesDataNew = new LineData[sizeNew];
+       if (linesDataNew) {
+               for (int i = 0; i < size; i++)
+                       linesDataNew[i] = linesData[i];
+               // Do not delete handleSets here as they are transferred to new linesData
+               delete []linesData;
+               linesData = linesDataNew;
+               size = sizeNew;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void LineVector::ExpandLevels(int sizeNew) {
+       if (sizeNew == -1)
+               sizeNew = size;
+       int *levelsNew = new int[sizeNew];
+       if (levelsNew) {
+               int i = 0;
+               for (; i < sizeLevels; i++)
+                       levelsNew[i] = levels[i];
+               for (; i < sizeNew; i++)
+                       levelsNew[i] = SC_FOLDLEVELBASE;
+               delete []levels;
+               levels = levelsNew;
+               sizeLevels = sizeNew;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void LineVector::InsertValue(int pos, int value) {
+       //Platform::DebugPrintf("InsertValue[%d] = %d\n", pos, value);
+       if ((lines + 2) >= size) {
+               Expand(size + growSize);
+               if (levels) {
+                       ExpandLevels(size + growSize);
+               }
+       }
+       lines++;
+       for (int i = lines + 1; i > pos; i--) {
+               linesData[i] = linesData[i - 1];
+       }
+       linesData[pos].startPosition = value;
+       linesData[pos].handleSet = 0;
+}
+
+void LineVector::SetValue(int pos, int value) {
+       //Platform::DebugPrintf("SetValue[%d] = %d\n", pos, value);
+       if ((pos + 2) >= size) {
+               //Platform::DebugPrintf("Resize %d %d\n", size,pos);
+               Expand(pos + growSize);
+               //Platform::DebugPrintf("end Resize %d %d\n", size,pos);
+               lines = pos;
+               if (levels) {
+                       ExpandLevels(pos + growSize);
+               }
+       }
+       linesData[pos].startPosition = value;
+}
+
+void LineVector::Remove(int pos) {
+       //Platform::DebugPrintf("Remove %d\n", pos);
+       // Retain the markers from the deleted line by oring them into the previous line
+       if (pos > 0) {
+               MergeMarkers(pos - 1);
+       }
+       for (int i = pos; i < lines; i++) {
+               linesData[i] = linesData[i + 1];
+       }
+       lines--;
+}
+
+int LineVector::LineFromPosition(int pos) {
+       //Platform::DebugPrintf("LineFromPostion %d lines=%d end = %d\n", pos, lines, linesData[lines].startPosition);
+       if (lines == 0)
+               return 0;
+       //Platform::DebugPrintf("LineFromPosition %d\n", pos);
+       if (pos >= linesData[lines].startPosition)
+               return lines - 1;
+       int lower = 0;
+       int upper = lines;
+       int middle = 0;
+       do {
+               middle = (upper + lower + 1) / 2;       // Round high
+               if (pos < linesData[middle].startPosition) {
+                       upper = middle - 1;
+               } else {
+                       lower = middle;
+               }
+       } while (lower < upper);
+       //Platform::DebugPrintf("LineFromPostion %d %d %d\n", pos, lower, linesData[lower].startPosition, linesData[lower > 1 ? lower - 1 : 0].startPosition);
+       return lower;
+}
+
+int LineVector::AddMark(int line, int markerNum) {
+       handleCurrent++;
+       if (!linesData[line].handleSet) {
+               // Need new structure to hold marker handle
+               linesData[line].handleSet = new MarkerHandleSet;
+               if (!linesData[line].handleSet)
+                       return - 1;
+       }
+       linesData[line].handleSet->InsertHandle(handleCurrent, markerNum);
+
+       return handleCurrent;
+}
+
+void LineVector::MergeMarkers(int pos) {
+       if (linesData[pos].handleSet || linesData[pos + 1].handleSet) {
+               if (linesData[pos].handleSet && linesData[pos + 1].handleSet) {
+                       linesData[pos].handleSet->CombineWith(linesData[pos].handleSet);
+                       linesData[pos].handleSet = 0;
+               }
+       }
+}
+
+void LineVector::DeleteMark(int line, int markerNum) {
+       if (linesData[line].handleSet) {
+               if (markerNum == -1) {
+                       delete linesData[line].handleSet;
+                       linesData[line].handleSet = 0;
+               } else {
+                       linesData[line].handleSet->RemoveNumber(markerNum);
+                       if (linesData[line].handleSet->Length() == 0) {
+                               delete linesData[line].handleSet;
+                               linesData[line].handleSet = 0;
+                       }
+               }
+       }
+}
+
+void LineVector::DeleteMarkFromHandle(int markerHandle) {
+       int line = LineFromHandle(markerHandle);
+       if (line >= 0) {
+               linesData[line].handleSet->RemoveHandle(markerHandle);
+               if (linesData[line].handleSet->Length() == 0) {
+                       delete linesData[line].handleSet;
+                       linesData[line].handleSet = 0;
+               }
+       }
+}
+
+int LineVector::LineFromHandle(int markerHandle) {
+       for (int line = 0; line < lines; line++) {
+               if (linesData[line].handleSet) {
+                       if (linesData[line].handleSet->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_) {
+       delete []data;
+       position = position_;
+       at = at_;
+       data = data_;
+       lenData = lenData_;
+}
+
+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;
+
+       // Ownership of source data transferred to this
+       source->position = 0;
+       source->at = startAction;
+       source->data = 0;
+       source->lenData = 0;
+}
+
+CellBuffer::CellBuffer(int initialLength) {
+       body = new char[initialLength];
+       size = initialLength;
+       length = 0;
+       part1len = 0;
+       gaplen = initialLength;
+       part2body = body + gaplen;
+       readOnly = false;
+
+       lenActions = 100;
+       actions = new Action[lenActions];
+       maxAction = 0;
+       currentAction = 0;
+       collectingUndo = undoCollectAutoStart;
+       undoSequenceDepth = 0;
+       savePoint = 0;
+
+       actions[currentAction].Create(startAction);
+}
+
+CellBuffer::~CellBuffer() {
+       delete []body;
+       body = 0;
+       delete []actions;
+       actions = 0;
+}
+
+void CellBuffer::GapTo(int position) {
+       if (position == part1len)
+               return;
+       if (position < part1len) {
+               int diff = part1len - position;
+               //Platform::DebugPrintf("Move gap backwards to %d diff = %d part1len=%d length=%d \n", position,diff, part1len, length);
+               for (int i = 0; i < diff; i++)
+                       body[part1len + gaplen - i - 1] = body[part1len - i - 1];
+       } else {        // position > part1len
+               int diff = position - part1len;
+               //Platform::DebugPrintf("Move gap forwards to %d diff =%d\n", position,diff);
+               for (int i = 0; i < diff; i++)
+                       body[part1len + i] = body[part1len + gaplen + i];
+       }
+       part1len = position;
+       part2body = body + gaplen;
+}
+
+void CellBuffer::RoomFor(int insertionLength) {
+       //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
+       if (gaplen <= insertionLength) {
+               //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
+               GapTo(length);
+               int newSize = size + insertionLength + 4000;
+               //Platform::DebugPrintf("moved gap %d\n", newSize);
+               char *newBody = new char[newSize];
+               memcpy(newBody, body, size);
+               delete []body;
+               body = newBody;
+               gaplen += newSize - size;
+               part2body = body + gaplen;
+               size = newSize;
+               //Platform::DebugPrintf("end need room %d %d - size=%d length=%d\n", gaplen, insertionLength,size,length);
+       }
+}
+
+// To make it easier to write code that uses ByteAt, a position outside the range of the buffer
+// can be retrieved. All characters outside the range have the value '\0'.
+char CellBuffer::ByteAt(int position) {
+       if (position < part1len) {
+               if (position < 0) {
+                       return '\0';
+               } else {
+                       return body[position];
+               }
+       } else {
+               if (position >= length) {
+                       return '\0';
+               } else {
+                       return part2body[position];
+               }
+       }
+}
+
+void CellBuffer::SetByteAt(int position, char ch) {
+
+       if (position < 0) {
+               //Platform::DebugPrintf("Bad position %d\n",position);
+               return;
+       }
+       if (position >= length + 11) {
+               Platform::DebugPrintf("Very Bad position %d of %d\n", position, length);
+               //exit(2);
+               return;
+       }
+       if (position >= length) {
+               //Platform::DebugPrintf("Bad position %d of %d\n",position,length);
+               return;
+       }
+
+       if (position < part1len) {
+               body[position] = ch;
+       } else {
+               part2body[position] = ch;
+       }
+}
+
+char CellBuffer::CharAt(int position) {
+       return ByteAt(position*2);
+}
+
+void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) {
+       if (lengthRetrieve < 0)
+               return;
+       if (position < 0)
+               return;
+       int bytePos = position * 2;
+       if ((bytePos + lengthRetrieve * 2) > length) {
+               Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n",bytePos,
+                       lengthRetrieve, length);
+               return;
+       }
+       GapTo(0);       // Move the buffer so its easy to subscript into it
+       char *pb = part2body + bytePos;
+       while (lengthRetrieve--) {
+               *buffer++ = *pb;
+               pb +=2;
+       }
+}
+
+char CellBuffer::StyleAt(int position) {
+       return ByteAt(position*2 + 1);
+}
+
+const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
+       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 / 2];
+                       for (int i = 0; i < insertLength / 2; i++) {
+                               data[i] = s[i * 2];
+                       }
+                       AppendAction(insertAction, position, data, insertLength / 2);
+               }
+
+               BasicInsertString(position, s, insertLength);
+       }
+       return data;
+}
+
+void CellBuffer::InsertCharStyle(int position, char ch, char style) {
+       char s[2];
+       s[0] = ch;
+       s[1] = style;
+       InsertString(position*2, s, 2);
+}
+
+bool CellBuffer::SetStyleAt(int position, char style, char mask) {
+       char curVal = ByteAt(position*2 + 1);
+       if ((curVal & mask) != style) {
+               SetByteAt(position*2 + 1, (curVal & ~mask) | style);
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mask) {
+       int bytePos = position * 2 + 1;
+       bool changed = false;
+       while (lengthStyle--) {
+               char curVal = ByteAt(bytePos);
+               if ((curVal & mask) != style) {
+                       SetByteAt(bytePos, (curVal & ~mask) | style);
+                       changed = true;
+               }
+               bytePos += 2;
+       }
+       return changed;
+}
+
+void CellBuffer::EnsureUndoRoom() {
+       //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, length, currentAction);
+       if (currentAction >= 2) {
+               // Have to test that there is room for 2 more actions in the array
+               // as two actions may be created by this 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 CellBuffer::AppendAction(actionType at, int position, char *data, int lengthData) {
+       EnsureUndoRoom();
+       //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
+       if (currentAction >= 2) {
+               // See if current action can be coalesced into previous action
+               // Will work if both are inserts or deletes and position is same or two different
+               if ((at != actions[currentAction - 1].at) || (abs(position - actions[currentAction - 1].position) > 2)) {
+                       currentAction++;
+               } else if (currentAction == savePoint) {
+                       currentAction++;
+               }
+       } else {
+               currentAction++;
+       }
+       actions[currentAction].Create(at, position, data, lengthData);
+       if ((collectingUndo == undoCollectAutoStart) && (0 == undoSequenceDepth)) {
+               currentAction++;
+               actions[currentAction].Create(startAction);
+       }
+       maxAction = currentAction;
+}
+
+const char *CellBuffer::DeleteChars(int position, int deleteLength) {
+       // InsertString and DeleteChars are the bottleneck though which all changes occur
+       char *data = 0;
+       if (!readOnly) {
+               if (collectingUndo) {
+                       // Save into the undo/redo stack, but only the characters - not the formatting
+                       data = new char[deleteLength / 2];
+                       for (int i = 0; i < deleteLength / 2; i++) {
+                               data[i] = ByteAt(position + i * 2);
+                       }
+                       AppendAction(removeAction, position, data, deleteLength / 2);
+               }
+
+               BasicDeleteChars(position, deleteLength);
+       }
+       return data;
+}
+
+int CellBuffer::ByteLength() {
+       return length;
+}
+
+int CellBuffer::Length() {
+       return ByteLength() / 2;
+}
+
+int CellBuffer::Lines() {
+       //Platform::DebugPrintf("Lines = %d\n", lv.lines);
+       return lv.lines;
+}
+
+int CellBuffer::LineStart(int line) {
+       if (line < 0)
+               return 0;
+       else if (line > lv.lines)
+               return length;
+       else
+               return lv.linesData[line].startPosition;
+}
+
+bool CellBuffer::IsReadOnly() {
+       return readOnly;
+}
+
+void CellBuffer::SetReadOnly(bool set) {
+       readOnly = set;
+}
+
+void CellBuffer::SetSavePoint() {
+       savePoint = currentAction;
+}
+
+bool CellBuffer::IsSavePoint() {
+       return savePoint == currentAction;
+}
+
+int CellBuffer::AddMark(int line, int markerNum) {
+       if ((line >= 0) && (line < lv.lines)) {
+               return lv.AddMark(line, markerNum);
+       }
+       return - 1;
+}
+
+void CellBuffer::DeleteMark(int line, int markerNum) {
+       if ((line >= 0) && (line < lv.lines)) {
+               lv.DeleteMark(line, markerNum);
+       }
+}
+
+void CellBuffer::DeleteMarkFromHandle(int markerHandle) {
+       lv.DeleteMarkFromHandle(markerHandle);
+}
+
+int CellBuffer::GetMark(int line) {
+       if ((line >= 0) && (line < lv.lines) && (lv.linesData[line].handleSet))
+               return lv.linesData[line].handleSet->MarkValue();
+       return 0;
+}
+
+void CellBuffer::DeleteAllMarks(int markerNum) {
+       for (int line = 0; line < lv.lines; line++) {
+               lv.DeleteMark(line, markerNum);
+       }
+}
+
+int CellBuffer::LineFromHandle(int markerHandle) {
+       return lv.LineFromHandle(markerHandle);
+}
+
+// Without undo
+
+void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
+       //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
+       if (insertLength == 0)
+               return;
+       RoomFor(insertLength);
+       GapTo(position);
+
+       memcpy(body + part1len, s, insertLength);
+       length += insertLength;
+       part1len += insertLength;
+       gaplen -= insertLength;
+       part2body = body + gaplen;
+
+       int lineInsert = lv.LineFromPosition(position / 2) + 1;
+       // Point all the lines after the insertion point further along in the buffer
+       for (int lineAfter = lineInsert; lineAfter <= lv.lines; lineAfter++) {
+               lv.linesData[lineAfter].startPosition += insertLength / 2;
+       }
+       char chPrev = ' ';
+       if ((position - 2) >= 0)
+               chPrev = ByteAt(position - 2);
+       char chAfter = ' ';
+       if ((position + insertLength) < length)
+               chAfter = ByteAt(position + insertLength);
+       if (chPrev == '\r' && chAfter == '\n') {
+               //Platform::DebugPrintf("Splitting a crlf pair at %d\n", lineInsert);
+               // Splitting up a crlf pair at position
+               lv.InsertValue(lineInsert, position / 2);
+               lineInsert++;
+       }
+       char ch = ' ';
+       for (int i = 0; i < insertLength; i += 2) {
+               ch = s[i];
+               if (ch == '\r') {
+                       //Platform::DebugPrintf("Inserting cr at %d\n", lineInsert);
+                       lv.InsertValue(lineInsert, (position + i) / 2 + 1);
+                       lineInsert++;
+               } else if (ch == '\n') {
+                       if (chPrev == '\r') {
+                               //Platform::DebugPrintf("Patching cr before lf at %d\n", lineInsert-1);
+                               // Patch up what was end of line
+                               lv.SetValue(lineInsert - 1, (position + i) / 2 + 1);
+                       } else {
+                               //Platform::DebugPrintf("Inserting lf at %d\n", lineInsert);
+                               lv.InsertValue(lineInsert, (position + i) / 2 + 1);
+                               lineInsert++;
+                       }
+               }
+               chPrev = ch;
+       }
+       // Joining two lines where last insertion is cr and following text starts with lf
+       if (chAfter == '\n') {
+               if (ch == '\r') {
+                       //Platform::DebugPrintf("Joining cr before lf at %d\n", lineInsert-1);
+                       // End of line already in buffer so drop the newly created one
+                       lv.Remove(lineInsert - 1);
+               }
+       }
+}
+
+void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
+       //Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength);
+       if (deleteLength == 0)
+               return;
+
+       if ((position == 0) && (deleteLength == length)) {
+               // If whole buffer is being deleted, faster to reinitialise lines data
+               // than to delete each line.
+               //printf("Whole buffer being deleted\n");
+               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 / 2) + 1;
+               // Point all the lines after the insertion point further along in the buffer
+               for (int lineAfter = lineRemove; lineAfter <= lv.lines; lineAfter++) {
+                       lv.linesData[lineAfter].startPosition -= deleteLength / 2;
+               }
+               char chPrev = ' ';
+               if (position >= 2)
+                       chPrev = ByteAt(position - 2);
+               char chBefore = chPrev;
+               char chNext = ' ';
+               if (position < length)
+                       chNext = ByteAt(position);
+               bool ignoreNL = false;
+               if (chPrev == '\r' && chNext == '\n') {
+                       //Platform::DebugPrintf("Deleting lf after cr, move line end to cr at %d\n", lineRemove);
+                       // Move back one
+                       lv.SetValue(lineRemove, position / 2);
+                       lineRemove++;
+                       ignoreNL = true;        // First \n is not real deletion
+               }
+
+               char ch = chNext;
+               for (int i = 0; i < deleteLength; i += 2) {
+                       chNext = ' ';
+                       if ((position + i + 2) < length)
+                               chNext = ByteAt(position + i + 2);
+                       //Platform::DebugPrintf("Deleting %d %x\n", i, ch);
+                       if (ch == '\r') {
+                               if (chNext != '\n') {
+                                       //Platform::DebugPrintf("Removing cr end of line\n");
+                                       lv.Remove(lineRemove);
+                               }
+                       } else if ((ch == '\n') && !ignoreNL) {
+                               //Platform::DebugPrintf("Removing lf end of line\n");
+                               lv.Remove(lineRemove);
+                               ignoreNL = false;       // Further \n are not real deletions
+                       }
+
+                       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 = ' ';
+               if ((position + deleteLength) < length)
+                       chAfter = ByteAt(position + deleteLength);
+               if (chBefore == '\r' && chAfter == '\n') {
+                       //d.printf("Joining cr before lf at %d\n", lineRemove);
+                       // Using lineRemove-1 as cr ended line before start of deletion
+                       lv.Remove(lineRemove - 1);
+                       lv.SetValue(lineRemove - 1, position / 2 + 1);
+               }
+       }
+       GapTo(position);
+       length -= deleteLength;
+       gaplen += deleteLength;
+       part2body = body + gaplen;
+}
+
+undoCollectionType CellBuffer::SetUndoCollection(undoCollectionType collectUndo) {
+       collectingUndo = collectUndo;
+       undoSequenceDepth = 0;
+       return collectingUndo;
+}
+
+bool CellBuffer::IsCollectingUndo() {
+       return collectingUndo;
+}
+
+void CellBuffer::AppendUndoStartAction() {
+       EnsureUndoRoom();
+       // Finish any currently active undo sequence
+       undoSequenceDepth = 0;
+       if (actions[currentAction].at != startAction) {
+               undoSequenceDepth++;
+               currentAction++;
+               actions[currentAction].Create(startAction);
+               maxAction = currentAction;
+       }
+}
+
+void CellBuffer::BeginUndoAction() {
+       EnsureUndoRoom();
+       if (undoSequenceDepth == 0) {
+               if (actions[currentAction].at != startAction) {
+                       currentAction++;
+                       actions[currentAction].Create(startAction);
+                       maxAction = currentAction;
+               }
+       }
+       undoSequenceDepth++;
+}
+
+void CellBuffer::EndUndoAction() {
+       EnsureUndoRoom();
+       undoSequenceDepth--;
+       if (0 == undoSequenceDepth) {
+               if (actions[currentAction].at != startAction) {
+                       currentAction++;
+                       actions[currentAction].Create(startAction);
+                       maxAction = currentAction;
+               }
+       }
+}
+
+void CellBuffer::DeleteUndoHistory() {
+       for (int i = 1; i < maxAction; i++)
+               actions[i].Destroy();
+       maxAction = 0;
+       currentAction = 0;
+       savePoint = 0;
+}
+
+bool CellBuffer::CanUndo() {
+       return (!readOnly) && ((currentAction > 0) && (maxAction > 0));
+}
+
+int CellBuffer::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 &CellBuffer::UndoStep() {
+       const Action &actionStep = actions[currentAction];
+       if (actionStep.at == insertAction) {
+               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+       } else if (actionStep.at == removeAction) {
+               char *styledData = new char[actionStep.lenData * 2];
+               for (int i = 0; i < actionStep.lenData; i++) {
+                       styledData[i*2] = actionStep.data[i];
+                       styledData[i*2+1] = 0;
+               }
+               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               delete []styledData;
+       }
+       currentAction--;
+       return actionStep;
+}
+
+bool CellBuffer::CanRedo() {
+       return (!readOnly) && (maxAction > currentAction);
+}
+
+int CellBuffer::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 &CellBuffer::RedoStep() {
+       const Action &actionStep = actions[currentAction];
+       if (actionStep.at == insertAction) {
+               char *styledData = new char[actionStep.lenData * 2];
+               for (int i = 0; i < actionStep.lenData; i++) {
+                       styledData[i*2] = actionStep.data[i];
+                       styledData[i*2+1] = 0;
+               }
+               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               delete []styledData;
+       } else if (actionStep.at == removeAction) {
+               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+       }
+       currentAction++;
+       return actionStep;
+}
+
+int CellBuffer::SetLineState(int line, int state) {
+       int stateOld = lineStates[line];
+       lineStates[line] = state;
+       return stateOld;
+}
+
+int CellBuffer::GetLineState(int line) {
+       return lineStates[line];
+}
+
+int CellBuffer::GetMaxLineState() {
+       return lineStates.Length();
+}
+               
+int CellBuffer::SetLevel(int line, int level) {
+       int prev = 0;
+       if ((line >= 0) && (line < lv.lines)) {
+               if (!lv.levels) {
+                       lv.ExpandLevels();
+               }
+               prev = lv.levels[line];
+               if (lv.levels[line] != level) {
+                       lv.levels[line] = level;
+               }
+       }
+       return prev;
+}
+
+int CellBuffer::GetLevel(int line) {
+       if (lv.levels && (line >= 0) && (line < lv.lines)) {
+               return lv.levels[line];
+       } else {
+               return SC_FOLDLEVELBASE;
+       }
+}
+
diff --git a/contrib/src/stc/scintilla/src/CellBuffer.h b/contrib/src/stc/scintilla/src/CellBuffer.h
new file mode 100644 (file)
index 0000000..5fbe2ea
--- /dev/null
@@ -0,0 +1,197 @@
+// Scintilla source code edit control
+// CellBuffer.h - manages the text of the document
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CELLBUFFER_H
+#define CELLBUFFER_H
+
+// This holds the marker identifier and the marker type to display.
+// MarkerHandleNumbers are members of lists.
+struct MarkerHandleNumber {
+       int handle;
+       int number;
+       MarkerHandleNumber *next;
+};
+
+// A marker handle set contains any number of MarkerHandleNumbers
+class MarkerHandleSet {
+       MarkerHandleNumber *root;
+public:
+       MarkerHandleSet();
+       ~MarkerHandleSet();
+       int Length();
+       int NumberFromHandle(int handle);
+       int MarkValue();        // Bit set of marker numbers
+       bool Contains(int handle);
+       bool InsertHandle(int handle, int markerNum);
+       void RemoveHandle(int handle);
+       void RemoveNumber(int markerNum);
+       void CombineWith(MarkerHandleSet *other);
+};
+
+// Each line stores the starting position of the first character of the line in the cell buffer
+// and potentially a marker handle set. Often a line will not have any attached markers.
+struct LineData {
+       int startPosition;
+       MarkerHandleSet *handleSet;
+       LineData() : startPosition(0), handleSet(0) {
+       }
+};
+
+// The line vector contains information about each of the lines in a cell buffer.
+class LineVector {
+public:
+       enum { growSize = 4000 };
+       int lines;
+       LineData *linesData;
+       int size;
+       int *levels;
+       int sizeLevels;
+       
+       // Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
+       int handleCurrent;
+       
+       LineVector();
+       ~LineVector();
+       void Init();
+
+       void Expand(int sizeNew);
+       void ExpandLevels(int sizeNew=-1);
+       void InsertValue(int pos, int value);
+       void SetValue(int pos, int value);
+       void Remove(int pos);
+       int LineFromPosition(int pos);
+       
+       int AddMark(int line, int marker);
+       void MergeMarkers(int pos);
+       void DeleteMark(int line, int markerNum);
+       void DeleteMarkFromHandle(int markerHandle);
+       int LineFromHandle(int markerHandle);
+};
+
+// Actions are used to store all the information required to perform one undo/redo step.
+enum actionType { insertAction, removeAction, startAction };
+
+class Action {
+public:
+       actionType at;
+       int position;
+       char *data;
+       int lenData;
+
+       Action();
+       ~Action();
+       void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0);
+       void Destroy();
+       void Grab(Action *source);
+};
+
+enum undoCollectionType { undoCollectNone, undoCollectAutoStart, undoCollectManualStart };
+
+// Holder for an expandable array of characters that supports undo and line markers
+// Based on article "Data Structures in a Bit-Mapped Text Editor"
+// by Wilfred J. Hansen, Byte January 1987, page 183
+class CellBuffer {
+private:
+       char *body;
+       int size;
+       int length;
+       int part1len;
+       int gaplen;
+       char *part2body;
+       bool readOnly;
+
+       Action *actions;
+       int lenActions;
+       int maxAction;
+       int currentAction;
+       undoCollectionType collectingUndo;
+       int undoSequenceDepth;
+       int savePoint;
+
+       LineVector lv;
+
+       SVector<int, 4000> lineStates;
+
+       void GapTo(int position);
+       void RoomFor(int insertionLength);
+
+       void EnsureUndoRoom();
+       void AppendAction(actionType at, int position, char *data, int length);
+
+       inline char ByteAt(int position);
+       void SetByteAt(int position, char ch);
+
+public:
+
+       CellBuffer(int initialLength = 4000);
+       ~CellBuffer();
+       
+       // Retrieving positions outside the range of the buffer works and returns 0
+       char CharAt(int position);
+       void GetCharRange(char *buffer, int position, int lengthRetrieve);
+       char StyleAt(int position);
+       
+       int ByteLength();
+       int Length();
+       int Lines();
+       int LineStart(int line);
+       int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
+       const char *InsertString(int position, char *s, int insertLength);
+       void InsertCharStyle(int position, char ch, char style);
+       
+       // Setting styles for positions outside the range of the buffer is safe and has no effect.
+       // True is returned if the style of a character changed.
+       bool SetStyleAt(int position, char style, char mask=(char)0xff);
+       bool SetStyleFor(int position, int length, char style, char mask);
+       
+       const char *DeleteChars(int position, int deleteLength);
+
+       bool IsReadOnly();
+       void SetReadOnly(bool set);
+
+       // The save point is a marker in the undo stack where the container has stated that 
+       // the buffer was saved. Undo and redo can move over the save point.
+       void SetSavePoint();
+       bool IsSavePoint();
+
+       // Line marker functions
+       int AddMark(int line, int markerNum);
+       void DeleteMark(int line, int markerNum);
+       void DeleteMarkFromHandle(int markerHandle);
+       int GetMark(int line);
+       void DeleteAllMarks(int markerNum);
+       int LineFromHandle(int markerHandle);
+       // Without undo
+       void BasicInsertString(int position, char *s, int insertLength);
+       void BasicDeleteChars(int position, int deleteLength);
+
+       undoCollectionType SetUndoCollection(undoCollectionType collectUndo);
+       bool IsCollectingUndo();
+       void AppendUndoStartAction();
+       void BeginUndoAction();
+       void EndUndoAction();
+       void DeleteUndoHistory();
+       
+       // To perform an undo, StartUndo is called to retreive the number of steps, then UndoStep is 
+       // called that many times. Similarly for redo.
+       bool CanUndo();
+       int StartUndo();
+       const Action &UndoStep();
+       bool CanRedo();
+       int StartRedo();
+       const Action &RedoStep();
+       
+       int SetLineState(int line, int state);
+       int GetLineState(int line);
+       int GetMaxLineState();
+               
+       int SetLevel(int line, int level);
+       int GetLevel(int line);
+};
+
+#define CELL_SIZE      2
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/ContractionState.cxx b/contrib/src/stc/scintilla/src/ContractionState.cxx
new file mode 100644 (file)
index 0000000..6f41461
--- /dev/null
@@ -0,0 +1,203 @@
+// Scintilla source code edit control
+// ContractionState.cxx - manages visibility of lines for folding
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "ContractionState.h"
+
+OneLine::OneLine() {
+       displayLine = 0;
+       docLine = 0;
+       visible = true;
+       expanded = true;
+}
+
+ContractionState::ContractionState() {
+       lines = 0;
+       size = 0;
+       linesInDoc = 1;
+       linesInDisplay = 1;
+       valid = false;
+}
+
+ContractionState::~ContractionState() {
+       Clear();
+}
+
+void ContractionState::MakeValid() const {
+       if (!valid) {
+               // Could be cleverer by keeping the index of the last still valid entry 
+               // rather than invalidating all.
+               int linePrev = -1;
+               int lineDisplay = 0;
+               for (int line=0; line<linesInDoc; line++) {
+                       lines[line].displayLine = lineDisplay;
+                       if (lines[line].visible) {
+                               lines[lineDisplay].docLine = line;
+                               lineDisplay++;
+                       }
+               }
+               valid = true;
+       }
+}
+
+void ContractionState::Clear() {
+       delete []lines;
+       lines = 0;
+       size = 0;
+       linesInDoc = 1;
+       linesInDisplay = 1;
+}
+
+int ContractionState::LinesInDoc() const {
+       return linesInDoc;
+}
+
+int ContractionState::LinesDisplayed() const {
+       return linesInDisplay;
+}
+
+int ContractionState::DisplayFromDoc(int lineDoc) const {
+       if (size == 0) {
+               return lineDoc;
+       }
+       MakeValid();
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].displayLine;
+       }
+       return -1;
+}
+
+int ContractionState::DocFromDisplay(int lineDisplay) const {
+       if (lineDisplay <= 0)
+               return 0;
+       if (lineDisplay >= linesInDisplay)
+               return linesInDoc-1;
+       if (size == 0)
+               return lineDisplay;
+       MakeValid();
+       return lines[lineDisplay].docLine;
+}
+
+void ContractionState::Grow(int sizeNew) {
+       OneLine *linesNew = new OneLine[sizeNew];
+       if (linesNew) {
+               int i = 0;
+               for (; i < size; i++) {
+                       linesNew[i] = lines[i];
+               }
+               for (; i < sizeNew; i++) {
+                       linesNew[i].displayLine = i;
+               }
+               delete []lines;
+               lines = linesNew;
+               size = sizeNew;
+               valid = false;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void ContractionState::InsertLines(int lineDoc, int lineCount) {
+       if (size == 0) {
+               linesInDoc += lineCount;
+               linesInDisplay += lineCount;
+               return;
+       }
+       //Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
+       if ((linesInDoc + 2) >= size) {
+               Grow(size + growSize);
+       }
+       linesInDoc += lineCount;
+       linesInDisplay += lineCount;
+       for (int i = linesInDoc + 1; i >= lineDoc + lineCount; i--) {
+               lines[i].visible = lines[i - lineCount].visible;
+               lines[i].expanded = lines[i - lineCount].expanded;
+       }
+       for (int d=0;d<lineCount;d++) {
+               lines[lineDoc+d].visible = true;        // Should inherit visibility from context ?
+               lines[lineDoc+d].expanded = true;
+       }
+       valid = false;
+}
+
+void ContractionState::DeleteLines(int lineDoc, int lineCount) {
+       if (size == 0) {
+               linesInDoc -= lineCount;
+               linesInDisplay -= lineCount;
+               return;
+       }
+       int delta = 0;
+       for (int d=0;d<lineCount;d++)
+               if (lines[lineDoc+d].visible)
+                       delta--;
+       for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
+               lines[i].visible = lines[i + lineCount].visible;
+               lines[i].expanded = lines[i + lineCount].expanded;
+       }
+       linesInDoc -= lineCount;
+       linesInDisplay += delta;
+       valid = false;
+}
+
+bool ContractionState::GetVisible(int lineDoc) const {
+       if (size == 0)
+               return true;
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].visible;
+       } else {
+               return false;
+       }
+}
+
+bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
+       if (size == 0) {
+               Grow(lineDocEnd + growSize);
+       }
+       // TODO: modify docLine members to mirror displayLine
+       int delta = 0;
+       // Change lineDocs
+       if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
+               for (int line=lineDocStart; line <= lineDocEnd; line++) {
+                       if (lines[line].visible != visible) {
+                               delta += visible ? 1 : -1;              
+                               lines[line].visible = visible;
+                       }
+                       lines[line].displayLine += delta;
+               }
+               if (delta != 0) {
+                       for (int line=lineDocEnd+1; line <= linesInDoc; line++) {
+                               lines[line].displayLine += delta;
+                       }
+               }
+       }
+       linesInDisplay += delta;
+       valid = false;
+       return delta != 0;
+}
+
+bool ContractionState::GetExpanded(int lineDoc) const {
+       if (size == 0) 
+               return true;
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].expanded;
+       } else {
+               return false;
+       }
+}
+
+bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
+       if (size == 0) {
+               Grow(lineDoc + growSize);
+       }
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               if (lines[lineDoc].expanded != expanded) {
+                       lines[lineDoc].expanded = expanded;
+                       return true;
+               }
+       }
+       return false;
+}
diff --git a/contrib/src/stc/scintilla/src/ContractionState.h b/contrib/src/stc/scintilla/src/ContractionState.h
new file mode 100644 (file)
index 0000000..9e17a76
--- /dev/null
@@ -0,0 +1,50 @@
+// Scintilla source code edit control
+// ContractionState.h - manages visibility of lines for folding
+// Copyright 1998-2000 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
+
+class OneLine {
+public:
+       int displayLine;        // position within set of visible lines
+       int docLine;            // inverse of displayLine
+       bool visible;
+       bool expanded;
+       
+       OneLine();
+       virtual ~OneLine() {}
+};
+
+class ContractionState {
+       void Grow(int sizeNew);
+       enum { growSize = 4000 };
+       int linesInDoc;
+       int linesInDisplay;
+       mutable OneLine *lines;
+       int size;
+       mutable bool valid;
+       void MakeValid() const;
+public:
+       ContractionState();
+       virtual ~ContractionState();
+       
+       void Clear();
+       
+       int LinesInDoc() const; 
+       int LinesDisplayed() const;     
+       int DisplayFromDoc(int lineDoc) const;
+       int DocFromDisplay(int lineDisplay) const;
+       
+       void InsertLines(int lineDoc, int lineCount);
+       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);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/Document.cxx b/contrib/src/stc/scintilla/src/Document.cxx
new file mode 100644 (file)
index 0000000..7d83224
--- /dev/null
@@ -0,0 +1,734 @@
+// Scintilla source code edit control
+// Document.cxx - text document that handles notifications, DBCS, styling, words and end of line
+// Copyright 1998-2000 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 "SVector.h"
+#include "CellBuffer.h"
+#include "Document.h"
+
+Document::Document() {
+       refCount = 0;
+#ifdef unix
+       eolMode = SC_EOL_LF;
+#else
+       eolMode = SC_EOL_CRLF;
+#endif
+       dbcsCodePage = 0;
+       stylingBits = 5;
+       stylingBitsMask = 0x1F;
+       stylingPos = 0;
+       stylingMask = 0;
+       for (int ch = 0; ch < 256; ch++) {
+               wordchars[ch] = isalnum(ch) || ch == '_';
+       }
+       endStyled = 0;
+       enteredCount = 0;
+       tabInChars = 8;
+       watchers = 0;
+       lenWatchers = 0;
+}
+
+Document::~Document() {
+       for (int i = 0; i < lenWatchers; i++) {
+               watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
+       }
+       delete []watchers;
+       watchers = 0;
+       lenWatchers = 0;
+}
+
+// Increase reference count and return its previous value.
+int Document::AddRef() {
+       return refCount++;
+}
+
+// Decrease reference count and return its provius 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::LineStart(int line) {
+       return cb.LineStart(line);
+}
+
+int Document::LineFromPosition(int pos) {
+       return cb.LineFromPosition(pos);
+}
+
+int Document::LineEndPosition(int position) {
+       int line = LineFromPosition(position);
+       if (line == LinesTotal() - 1) {
+               position = LineStart(line + 1);
+       } else {
+               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::VCHomePosition(int position) {
+       int line = LineFromPosition(position);
+       int startPosition = LineStart(line);
+       int endLine = LineStart(line + 1) - 1;
+       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, LineStart(line), 0, 0, 0);
+               mh.line = 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) && IsSubordinate(level, GetLevel(lineMaxSubord+1))) {
+               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 ((lineMaxSubord > lineParent) && (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG)) {
+                               lineMaxSubord--;
+                       }
+               }
+       }
+       return lineMaxSubord;
+}
+
+int Document::GetFoldParent(int line) {
+       int level = GetLevel(line);
+       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');
+}
+
+bool Document::IsDBCS(int pos) {
+#if PLAT_WIN
+       if (dbcsCodePage) {
+               // Anchor DBCS calculations at start of line because start of line can
+               // not be a DBCS trail byte.
+               int startLine = pos;
+               while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
+                       startLine--;
+               while (startLine <= pos) {
+                       if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) {
+                               startLine++;
+                               if (startLine >= pos)
+                                       return true;
+                       }
+                       startLine++;
+               }
+       }
+       return false;
+#else
+       return false;
+#endif
+}
+
+// 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 value - should be fixed up after
+       if (pos < 0)
+               return pos;
+       if (pos > Length())
+               return pos;
+
+       // Position 0 and Length() can not be between any two characters
+       if (pos == 0)
+               return pos;
+       if (pos == Length())
+               return pos;
+
+       // 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 PLAT_WIN
+       if (dbcsCodePage) {
+               // Anchor DBCS calculations at start of line because start of line can
+               // not be a DBCS trail byte.
+               int startLine = pos;
+               while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
+                       startLine--;
+               bool atLeadByte = false;
+               while (startLine < pos) {
+                       if (atLeadByte)
+                               atLeadByte = false;
+                       else if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine)))
+                               atLeadByte = true;
+                       else
+                               atLeadByte = false;
+                       startLine++;
+                       //Platform::DebugPrintf("DBCS %s\n", atlead ? "D" : "-");
+               }
+
+               if (atLeadByte) {
+                       // Position is between a lead byte and a trail byte
+                       if (moveDir > 0)
+                               return pos + 1;
+                       else
+                               return pos - 1;
+               }
+       }
+#endif
+
+       return pos;
+}
+
+void Document::ModifiedAt(int pos) {
+       if (endStyled > pos)
+               endStyled = pos;
+}
+
+// Document only modified by gateways DeleteChars, InsertStyledString, Undo, Redo, and SetStyleAt.
+// SetStyleAt does not change the persistent state of a document
+
+// Unlike Undo, Redo, and InsertStyledString, the pos argument is a cell number not a char number
+void Document::DeleteChars(int pos, int len) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               if (cb.IsReadOnly())
+                       NotifyModifyAttempt();
+               if (!cb.IsReadOnly()) {
+                       int prevLinesTotal = LinesTotal();
+                       bool startSavePoint = cb.IsSavePoint();
+                       const char *text = cb.DeleteChars(pos*2, len * 2);
+                       if (startSavePoint && cb.IsCollectingUndo())
+                               NotifySavePoint(!startSavePoint);
+                       ModifiedAt(pos);
+                       int modFlags = SC_MOD_DELETETEXT | SC_PERFORMED_USER;
+                       DocModification mh(modFlags, pos, len, LinesTotal() - prevLinesTotal, text);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+void Document::InsertStyledString(int position, char *s, int insertLength) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               if (cb.IsReadOnly())
+                       NotifyModifyAttempt();
+               if (!cb.IsReadOnly()) {
+                       int prevLinesTotal = LinesTotal();
+                       bool startSavePoint = cb.IsSavePoint();
+                       const char *text = cb.InsertString(position, s, insertLength);
+                       if (startSavePoint && cb.IsCollectingUndo())
+                               NotifySavePoint(!startSavePoint);
+                       ModifiedAt(position / 2);
+       
+                       int modFlags = SC_MOD_INSERTTEXT | SC_PERFORMED_USER;
+                       DocModification mh(modFlags, position / 2, insertLength / 2, LinesTotal() - prevLinesTotal, text);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+int Document::Undo() {
+       int newPos = 0;
+       if (enteredCount == 0) {
+               enteredCount++;
+               bool startSavePoint = cb.IsSavePoint();
+               int steps = cb.StartUndo();
+               for (int step=0; step<steps; step++) {
+                       int prevLinesTotal = LinesTotal();
+                       const Action &action = cb.UndoStep();
+                       int cellPosition = action.position / 2;
+                       ModifiedAt(cellPosition);
+                       newPos = cellPosition;
+                       
+                       int modFlags = SC_PERFORMED_UNDO;
+                       // With undo, an insertion action becomes a deletion notification
+                       if (action.at == removeAction) {
+                               newPos += action.lenData;
+                               modFlags |= SC_MOD_INSERTTEXT;
+                       } else {
+                               modFlags |= SC_MOD_DELETETEXT;
+                       }
+                       if (step == steps-1)
+                               modFlags |= SC_LASTSTEPINUNDOREDO;
+                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData, 
+                               LinesTotal() - prevLinesTotal, action.data));
+               }
+       
+               bool endSavePoint = cb.IsSavePoint();
+               if (startSavePoint != endSavePoint)
+                       NotifySavePoint(endSavePoint);
+               enteredCount--;
+       }
+       return newPos;
+}
+
+int Document::Redo() {
+       int newPos = 0;
+       if (enteredCount == 0) {
+               enteredCount++;
+               bool startSavePoint = cb.IsSavePoint();
+               int steps = cb.StartRedo();
+               for (int step=0; step<steps; step++) {
+                       int prevLinesTotal = LinesTotal();
+                       const Action &action = cb.RedoStep();
+                       int cellPosition = action.position / 2;
+                       ModifiedAt(cellPosition);
+                       newPos = cellPosition;
+                       
+                       int modFlags = SC_PERFORMED_REDO;
+                       if (action.at == insertAction) {
+                               newPos += action.lenData;
+                               modFlags |= SC_MOD_INSERTTEXT;
+                       } else {
+                               modFlags |= SC_MOD_DELETETEXT;
+                       }
+                       if (step == steps-1)
+                               modFlags |= SC_LASTSTEPINUNDOREDO;
+                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData, 
+                               LinesTotal() - prevLinesTotal, action.data));
+               }
+       
+               bool endSavePoint = cb.IsSavePoint();
+               if (startSavePoint != endSavePoint)
+                       NotifySavePoint(endSavePoint);
+               enteredCount--;
+       }
+       return newPos;
+}
+
+void Document::InsertChar(int pos, char ch) {
+       char chs[2];
+       chs[0] = ch;
+       chs[1] = 0;
+       InsertStyledString(pos*2, chs, 2);
+}
+
+// Insert a null terminated string
+void Document::InsertString(int position, const char *s) {
+       InsertString(position, s, strlen(s));
+}
+
+// Insert a string with a length
+void Document::InsertString(int position, const char *s, int insertLength) {
+       char *sWithStyle = new char[insertLength * 2];
+       if (sWithStyle) {
+               for (int i = 0; i < insertLength; i++) {
+                       sWithStyle[i*2] = s[i];
+                       sWithStyle[i*2 + 1] = 0;
+               }
+               InsertStyledString(position*2, sWithStyle, insertLength*2);
+               delete []sWithStyle;
+       }
+}
+
+void Document::DelChar(int pos) {
+       if (IsCrLf(pos)) {
+               DeleteChars(pos, 2);
+       } else if (IsDBCS(pos)) {
+               DeleteChars(pos, 2);
+       } else if (pos < Length()) {
+               DeleteChars(pos, 1);
+       }
+}
+
+int Document::DelCharBack(int pos) {
+       if (pos <= 0) {
+               return pos;
+       } else if (IsCrLf(pos - 2)) {
+               DeleteChars(pos - 2, 2);
+               return pos - 2;
+       } else if (IsDBCS(pos - 1)) {
+               DeleteChars(pos - 2, 2);
+               return pos - 2;
+       } else {
+               DeleteChars(pos - 1, 1);
+               return pos - 1;
+       }
+}
+
+void Document::Indent(bool forwards, int lineBottom, int lineTop) {
+       if (forwards) {
+               // Indent by a tab
+               for (int line = lineBottom; line >= lineTop; line--) {
+                       InsertChar(LineStart(line), '\t');
+               }
+       } else {
+               // 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 ispc = 0;
+                       while (ispc < tabInChars && cb.CharAt(LineStart(line) + ispc) == ' ')
+                               ispc++;
+                       int posStartLine = LineStart(line);
+                       if (ispc == tabInChars) {
+                               DeleteChars(posStartLine, ispc);
+                       } else if (cb.CharAt(posStartLine + ispc) == '\t') {
+                               DeleteChars(posStartLine, ispc + 1);
+                       } else {        // Hit a non-white
+                               DeleteChars(posStartLine, ispc);
+                       }
+               }
+       }
+}
+
+void Document::ConvertLineEnds(int eolModeSet) {
+       BeginUndoAction();
+       for (int pos = 0; pos < Length(); pos++) {
+               if (cb.CharAt(pos) == '\r') {
+                       if (cb.CharAt(pos+1) == '\n') {
+                               if (eolModeSet != SC_EOL_CRLF) {
+                                       DeleteChars(pos, 2);
+                                       if (eolModeSet == SC_EOL_CR)
+                                               InsertString(pos, "\r", 1);
+                                       else
+                                               InsertString(pos, "\n", 1);
+                               } else {
+                                       pos++;
+                               }
+                       } else {
+                               if (eolModeSet != SC_EOL_CR) {
+                                       DeleteChars(pos, 1);
+                                       if (eolModeSet == SC_EOL_CRLF) {
+                                               InsertString(pos, "\r\n", 2);
+                                               pos++;
+                                       } else {
+                                               InsertString(pos, "\n", 1);
+                                       }
+                               }
+                       }
+               } else if (cb.CharAt(pos) == '\n') {
+                       if (eolModeSet != SC_EOL_LF) {
+                               DeleteChars(pos, 1);
+                               if (eolModeSet == SC_EOL_CRLF) {
+                                       InsertString(pos, "\r\n", 2);
+                                       pos++;
+                               } else {
+                                       InsertString(pos, "\r", 1);
+                               }
+                       }
+               }
+       }
+       EndUndoAction();
+}
+
+bool Document::IsWordChar(unsigned char ch) {
+       return wordchars[ch];
+}
+
+int Document::ExtendWordSelect(int pos, int delta) {
+       if (delta < 0) {
+               while (pos > 0 && IsWordChar(cb.CharAt(pos - 1)))
+                       pos--;
+       } else {
+               while (pos < (Length()) && IsWordChar(cb.CharAt(pos)))
+                       pos++;
+       }
+       return pos;
+}
+
+int Document::NextWordStart(int pos, int delta) {
+       if (delta < 0) {
+               while (pos > 0 && (cb.CharAt(pos - 1) == ' ' || cb.CharAt(pos - 1) == '\t'))
+                       pos--;
+               if (isspace(cb.CharAt(pos - 1))) {      // Back up to previous line
+                       while (pos > 0 && isspace(cb.CharAt(pos - 1)))
+                               pos--;
+               } else {
+                       bool startAtWordChar = IsWordChar(cb.CharAt(pos - 1));
+                       while (pos > 0 && !isspace(cb.CharAt(pos - 1)) && (startAtWordChar == IsWordChar(cb.CharAt(pos - 1))))
+                               pos--;
+               }
+       } else {
+               bool startAtWordChar = IsWordChar(cb.CharAt(pos));
+               while (pos < (Length()) && isspace(cb.CharAt(pos)))
+                       pos++;
+               while (pos < (Length()) && !isspace(cb.CharAt(pos)) && (startAtWordChar == IsWordChar(cb.CharAt(pos))))
+                       pos++;
+               while (pos < (Length()) && (cb.CharAt(pos) == ' ' || cb.CharAt(pos) == '\t'))
+                       pos++;
+       }
+       return pos;
+}
+
+bool Document::IsWordAt(int start, int end) {
+       int lengthDoc = Length();
+       if (start > 0) {
+               char ch = CharAt(start - 1);
+               if (IsWordChar(ch))
+                       return false;
+       }
+       if (end < lengthDoc - 1) {
+               char ch = CharAt(end);
+               if (IsWordChar(ch))
+                       return false;
+       }
+       return true;
+}
+
+// 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 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 = strlen(s);
+       int endSearch = 0;
+       if (startPos <= endPos) {
+               endSearch = endPos - lengthFind + 1;
+       } else {
+               endSearch = endPos;
+       }
+       //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
+       char firstChar = s[0];
+       if (!caseSensitive)
+               firstChar = toupper(firstChar);
+       int pos = startPos;
+       while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+               char ch = CharAt(pos);
+               if (caseSensitive) {
+                       if (ch == firstChar) {
+                               bool found = true;
+                               for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+                                       ch = CharAt(pos + posMatch);
+                                       if (ch != s[posMatch])
+                                               found = false;
+                               }
+                               if (found) {
+                                       if ((!word) || IsWordAt(pos, pos + lengthFind))
+                                               return pos;
+                               }
+                       }
+               } else {
+                       if (toupper(ch) == firstChar) {
+                               bool found = true;
+                               for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+                                       ch = CharAt(pos + posMatch);
+                                       if (toupper(ch) != toupper(s[posMatch]))
+                                               found = false;
+                               }
+                               if (found) {
+                                       if ((!word) || IsWordAt(pos, pos + lengthFind))
+                                               return pos;
+                               }
+                       }
+               }
+               pos += increment;
+               if (dbcsCodePage) {
+                       // Ensure trying to match from start of character
+                       pos = MovePositionOutsideChar(pos, increment, false);
+               }
+       }
+       //Platform::DebugPrintf("Not found\n");
+       return - 1;
+}
+
+int Document::LinesTotal() {
+       return cb.Lines();
+}
+
+void Document::SetWordChars(unsigned char *chars) {
+       int ch;
+       for (ch = 0; ch < 256; ch++) {
+               wordchars[ch] = false;
+       }
+       if (chars) {
+               while (*chars) {
+                       wordchars[*chars] = true;
+                       chars++;
+               }
+       } else {
+               for (ch = 0; ch < 256; ch++) {
+                       wordchars[ch] = isalnum(ch) || ch == '_';
+               }
+       }
+}
+
+void Document::SetStylingBits(int bits) {
+       stylingBits = bits;
+       stylingBitsMask = 0;
+       for (int bit=0; bit<stylingBits; bit++) {
+               stylingBitsMask <<= 1;
+               stylingBitsMask |= 1;
+       }
+}
+
+void Document::StartStyling(int position, char mask) {
+       stylingPos = position;
+       stylingMask = mask;
+}
+
+void Document::SetStyleFor(int length, char style) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               int prevEndStyled = endStyled;
+               if (cb.SetStyleFor(stylingPos, length, style, stylingMask)) {
+                       DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, 
+                               prevEndStyled, length);
+                       NotifyModified(mh);
+               }
+               stylingPos += length;
+               endStyled = stylingPos;
+               enteredCount--;
+       }
+}
+
+void Document::SetStyles(int length, char *styles) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               int prevEndStyled = endStyled;
+               bool didChange = false;
+               for (int iPos = 0; iPos < length; iPos++, stylingPos++) {
+                       if (cb.SetStyleAt(stylingPos, styles[iPos], stylingMask)) {
+                               didChange = true;
+                       }
+               }
+               endStyled = stylingPos;
+               if (didChange) {
+                       DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, 
+                               prevEndStyled, endStyled - prevEndStyled);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+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) {
+       for (int i = 0; i < lenWatchers; i++) {
+               watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
+       }
+}
diff --git a/contrib/src/stc/scintilla/src/Document.h b/contrib/src/stc/scintilla/src/Document.h
new file mode 100644 (file)
index 0000000..fba611c
--- /dev/null
@@ -0,0 +1,222 @@
+// Scintilla source code edit control
+// Document.h - text document that handles notifications, DBCS, styling, words and end of line
+// Copyright 1998-2000 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
+
+// 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);
+       }
+       
+       bool Contains(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 {
+
+public:
+       // Used to pair watcher pointer with user data
+       class WatcherWithUserData {
+       public:
+               DocWatcher *watcher;
+               void *userData;
+               WatcherWithUserData() {
+                       watcher = 0;
+                       userData = 0;
+               }
+       };
+       
+private:       
+       int refCount;
+       CellBuffer cb;
+       bool wordchars[256];
+       int stylingPos;
+       int stylingMask;
+       int endStyled;
+       int enteredCount;
+       
+       WatcherWithUserData *watchers;
+       int lenWatchers;
+       
+public:
+       int stylingBits;
+       int stylingBitsMask;
+       
+       int eolMode;
+       int dbcsCodePage;
+       int tabInChars;
+       
+       Document();
+       virtual ~Document();
+       
+       int AddRef();
+       int Release();
+       
+       int LineFromPosition(int pos);
+       int ClampPositionIntoDocument(int pos);
+       bool IsCrLf(int pos);
+       int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
+
+       // Gateways to modifying document
+       void DeleteChars(int pos, int len);
+       void InsertStyledString(int position, char *s, int insertLength);
+       int Undo();
+       int Redo();
+       bool CanUndo() { return cb.CanUndo(); }
+       bool CanRedo() { return cb.CanRedo(); }
+       void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
+       undoCollectionType SetUndoCollection(undoCollectionType collectUndo) {
+               return cb.SetUndoCollection(collectUndo);
+       }
+       void AppendUndoStartAction() { cb.AppendUndoStartAction(); }
+       void BeginUndoAction() { cb.BeginUndoAction(); }
+       void EndUndoAction() { cb.EndUndoAction(); }
+       void SetSavePoint();
+       bool IsSavePoint() { return cb.IsSavePoint(); }
+       void Indent(bool forwards, int lineBottom, int lineTop);
+       void ConvertLineEnds(int eolModeSet);
+       void SetReadOnly(bool set) { cb.SetReadOnly(set); }
+
+       void InsertChar(int pos, char ch);
+       void InsertString(int position, const char *s);
+       void InsertString(int position, const char *s, int insertLength);
+       void DelChar(int pos);
+       int 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) { return cb.AddMark(line, markerNum); }
+       void DeleteMark(int line, int markerNum) { cb.DeleteMark(line, markerNum); }
+       void DeleteMarkFromHandle(int markerHandle) { cb.DeleteMarkFromHandle(markerHandle); }
+       void DeleteAllMarks(int markerNum) { cb.DeleteAllMarks(markerNum); }
+       int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
+       int LineStart(int line);
+       int LineEndPosition(int position);
+       int VCHomePosition(int position);
+
+       int SetLevel(int line, int level);
+       int GetLevel(int line) { return cb.GetLevel(line); }
+       int GetLastChild(int lineParent, int level=-1);
+       int GetFoldParent(int line);
+
+       void Indent(bool forwards);
+       int ExtendWordSelect(int pos, int delta);
+       int NextWordStart(int pos, int delta);
+       int Length() { return cb.Length(); }
+       long FindText(int minPos, int maxPos, const char *s, bool caseSensitive, bool word);
+       long FindText(WORD iMessage,WPARAM wParam,LPARAM lParam);
+       int LinesTotal();
+       
+       void SetWordChars(unsigned char *chars);
+       void SetStylingBits(int bits);
+       void StartStyling(int position, char mask);
+       void SetStyleFor(int length, char style);
+       void SetStyles(int length, char *styles);
+       int GetEndStyled() { return endStyled; }
+
+       int SetLineState(int line, int state) { return cb.SetLineState(line, 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; }
+       
+private:
+       bool IsDBCS(int pos);
+       bool IsWordChar(unsigned char ch);
+       bool IsWordAt(int start, int end);
+       void ModifiedAt(int pos);
+               
+       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) :
+               modificationType(modificationType_),
+               position(position_),
+               length(length_),
+               linesAdded(linesAdded_),
+               text(text_),
+               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;
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/Editor.cxx b/contrib/src/stc/scintilla/src/Editor.cxx
new file mode 100644 (file)
index 0000000..6508c95
--- /dev/null
@@ -0,0 +1,3693 @@
+// Scintilla source code edit control
+// Editor.cxx - main code for the edit control
+// Copyright 1998-2000 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 "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "Document.h"
+#include "Editor.h"
+
+Caret::Caret() :
+active(true), on(true), period(500) {}
+
+Timer::Timer() :
+ticking(false), ticksToWait(0), tickerID(0) {}
+
+Editor::Editor() {
+       ctrlID = 0;
+
+       stylesValid = false;
+
+       hideSelection = false;
+       inOverstrike = false;
+
+       bufferedDraw = true;
+
+       lastClickTime = 0;
+       ptMouseLast.x = 0;
+       ptMouseLast.y = 0;
+       firstExpose = true;
+       inDragDrop = false;
+       dropWentOutside = false;
+       posDrag = invalidPosition;
+       posDrop = invalidPosition;
+       selectionType = selChar;
+
+       lastXChosen = 0;
+       lineAnchor = 0;
+       originalAnchorPos = 0;
+
+       dragChars = 0;
+       lenDrag = 0;
+       dragIsRectangle = false;
+       selType = selStream;
+       xStartSelect = 0;
+       xEndSelect = 0;
+
+       caretPolicy = CARET_SLOP;
+       caretSlop = 0;
+
+       searchAnchor = 0;
+       
+       ucWheelScrollLines = 0;
+       cWheelDelta = 0;   //wheel delta from roll
+
+       xOffset = 0;
+       xCaretMargin = 50;
+       
+       currentPos = 0;
+       anchor = 0;
+
+       topLine = 0;
+       posTopLine = 0;
+       
+       needUpdateUI = true;
+       braces[0]=invalidPosition;
+       braces[1]=invalidPosition;
+       bracesMatchStyle = STYLE_BRACEBAD;
+       
+       edgeState = EDGE_NONE;
+       theEdge = 0;
+       
+       paintState = notPainting;
+       
+       modEventMask = SC_MODEVENTMASKALL;
+
+       pdoc = new Document();
+       pdoc ->AddRef();
+       pdoc->AddWatcher(this, 0);
+
+#ifdef MACRO_SUPPORT
+       recordingMacro = 0;
+#endif
+       foldFlags = 0;
+}
+
+Editor::~Editor() {
+       pdoc->RemoveWatcher(this, 0);
+       pdoc->Release();
+       pdoc = 0;
+       DropGraphics();
+
+       delete []dragChars;
+       dragChars = 0;
+       lenDrag = 0;
+}
+
+void Editor::Finalise() {
+}
+
+void Editor::DropGraphics() {
+       pixmapLine.Release();
+       pixmapSelMargin.Release();
+       pixmapSelPattern.Release();
+}
+
+void Editor::InvalidateStyleData() {
+       stylesValid = false;
+       palette.Release();
+       DropGraphics();
+}
+
+void Editor::InvalidateStyleRedraw() {
+       InvalidateStyleData();
+       Redraw();
+}
+
+void Editor::RefreshColourPalette(Palette &pal, bool want) {
+       vs.RefreshColourPalette(pal, want);
+}
+
+void Editor::RefreshStyleData() {
+       if (!stylesValid) {
+               stylesValid = true;
+               Surface surface;
+               surface.Init();
+               vs.Refresh(surface);
+               RefreshColourPalette(palette, true);
+               palette.Allocate(wMain);
+               RefreshColourPalette(palette, false);
+               SetScrollBars();
+       }
+}
+
+PRectangle Editor::GetClientRectangle() {
+       return wDraw.GetClientPosition();
+}
+
+PRectangle Editor::GetTextRectangle() {
+       PRectangle rc = GetClientRectangle();
+       rc.left += vs.fixedColumnWidth;
+       rc.right -= vs.rightMarginWidth;
+       return rc;
+}
+
+int Editor::LinesOnScreen() {
+       PRectangle rcClient = GetClientRectangle();
+       int htClient = rcClient.bottom - rcClient.top;
+       //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
+       return htClient / vs.lineHeight;
+}
+
+int Editor::LinesToScroll() {
+       int retVal = LinesOnScreen() - 1;
+       if (retVal < 1)
+               return 1;
+       else
+               return retVal;
+}
+
+int Editor::MaxScrollPos() {
+       //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
+       //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
+       int retVal = cs.LinesDisplayed() - LinesOnScreen();
+       if (retVal < 0)
+               return 0;
+       else
+               return retVal;
+}
+
+bool IsControlCharacter(char ch) {
+       // iscntrl returns true for lots of chars > 127 which are displayable
+       return ch >= 0 && ch < ' ';
+}
+
+const char *ControlCharacterString(char ch) {
+       const char *reps[] = {
+           "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+           "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+           "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+           "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+       };
+       if (ch < (sizeof(reps) / sizeof(reps[0]))) {
+               return reps[ch];
+       } else {
+               return "BAD";
+       }
+}
+
+Point Editor::LocationFromPosition(unsigned int pos) {
+       RefreshStyleData();
+       int line = pdoc->LineFromPosition(pos);
+       int lineVisible = cs.DisplayFromDoc(line);
+       //Platform::DebugPrintf("line=%d\n", line);
+       Surface surface;
+       surface.Init();
+       Point pt;
+       pt.y = (lineVisible - topLine) * vs.lineHeight;         // + half a lineheight?
+       unsigned int posLineStart = pdoc->LineStart(line);
+       if ((pos - posLineStart) > LineLayout::maxLineLength) {
+               // very long line so put x at arbitrary large position
+               pt.x = 30000 + vs.fixedColumnWidth - xOffset;
+       } else {
+               LineLayout ll;
+               LayoutLine(line, &surface, vs, ll);
+               pt.x = ll.positions[pos - posLineStart] + vs.fixedColumnWidth - xOffset;
+       }
+       return pt;
+}
+
+int Editor::XFromPosition(unsigned int pos) {
+       Point pt = LocationFromPosition(pos);
+       return pt.x - vs.fixedColumnWidth + xOffset;
+}
+       
+int Editor::LineFromLocation(Point pt) {
+       return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+}
+
+void Editor::SetTopLine(int topLineNew) {
+       topLine = topLineNew;
+       posTopLine = pdoc->LineStart(topLine);
+}
+
+int Editor::PositionFromLocation(Point pt) {
+       RefreshStyleData();
+       pt.x = pt.x - vs.fixedColumnWidth + xOffset;
+       int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+       if (pt.y < 0) { // Division rounds towards 0
+               line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine);
+       }
+       if (line < 0)
+               return 0;
+       if (line >= pdoc->LinesTotal())
+               return pdoc->Length();
+//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+       Surface surface;
+       surface.Init();
+       unsigned int posLineStart = pdoc->LineStart(line);
+
+       LineLayout ll;
+       LayoutLine(line, &surface, vs, ll);
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+               if (pt.x < ((ll.positions[i] + ll.positions[i + 1]) / 2) || 
+                       ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+                       return i + posLineStart;
+               }
+       }
+
+       return ll.numCharsInLine + posLineStart;
+}
+
+int Editor::PositionFromLineX(int line, int x) {
+       RefreshStyleData();
+       if (line >= pdoc->LinesTotal())
+               return pdoc->Length();
+       //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+       Surface surface;
+       surface.Init();
+       unsigned int posLineStart = pdoc->LineStart(line);
+
+       LineLayout ll;
+       LayoutLine(line, &surface, vs, ll);
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+               if (x < ((ll.positions[i] + ll.positions[i + 1]) / 2) || 
+                       ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+                       return i + posLineStart;
+               }
+       }
+
+       return ll.numCharsInLine + posLineStart;
+}
+
+void Editor::RedrawRect(PRectangle rc) {
+       //Platform::DebugPrintf("Redraw %d %d - %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
+       wDraw.InvalidateRectangle(rc);
+}
+
+void Editor::Redraw() {
+       //Platform::DebugPrintf("Redraw all\n");
+       wDraw.InvalidateAll();
+}
+
+void Editor::RedrawSelMargin() {
+       if (vs.maskInLine) {
+               Redraw();
+       } else {
+               PRectangle rcSelMargin = GetClientRectangle();
+               rcSelMargin.right = vs.fixedColumnWidth;
+               wDraw.InvalidateRectangle(rcSelMargin);
+       }
+}
+
+PRectangle Editor::RectangleFromRange(int start, int end) {
+       int minPos = start;
+       if (minPos > end)
+               minPos = end;
+       int maxPos = start;
+       if (maxPos < end)
+               maxPos = end;
+       int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
+       int maxLine = cs.DisplayFromDoc(pdoc->LineFromPosition(maxPos));
+       PRectangle rcClient = GetTextRectangle();
+       PRectangle rc;
+       rc.left = vs.fixedColumnWidth;
+       rc.top = (minLine - topLine) * vs.lineHeight;
+       if (rc.top < 0)
+               rc.top = 0;
+       rc.right = rcClient.right;
+       rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
+       // Ensure PRectangle is within 16 bit space
+       rc.top = Platform::Clamp(rc.top, -32000, 32000);
+       rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
+
+       return rc;
+}
+
+void Editor::InvalidateRange(int start, int end) {
+       RedrawRect(RectangleFromRange(start, end));
+}
+
+int Editor::CurrentPosition() {
+       return currentPos;
+}
+
+bool Editor::SelectionEmpty() {
+       return anchor == currentPos;
+}
+
+int Editor::SelectionStart(int line) {
+       if ((line == -1) || (selType == selStream)) {
+               return Platform::Minimum(currentPos, anchor);
+       } else { // selType == selRectangle
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               int lineStart = pdoc->LineFromPosition(selStart);
+               int lineEnd = pdoc->LineFromPosition(selEnd);
+               if (line < lineStart || line > lineEnd) {
+                       return -1;
+               } else {
+                       int minX = Platform::Minimum(xStartSelect, xEndSelect);
+                       //return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);
+                       return PositionFromLineX(line, minX);
+               }
+       } 
+}
+
+int Editor::SelectionEnd(int line) {
+       if ((line == -1) || (selType == selStream)) {
+               return Platform::Maximum(currentPos, anchor);
+       } else { // selType == selRectangle
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               int lineStart = pdoc->LineFromPosition(selStart);
+               int lineEnd = pdoc->LineFromPosition(selEnd);
+               if (line < lineStart || line > lineEnd) {
+                       return -1;
+               } else {
+                       int maxX = Platform::Maximum(xStartSelect, xEndSelect);
+                       // measure line and return character closest to minx
+                       return PositionFromLineX(line, maxX);
+               }
+       }
+}
+
+void Editor::SetSelection(int currentPos_, int anchor_) {
+       currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+       anchor_ = pdoc->ClampPositionIntoDocument(anchor_);
+       if ((currentPos != currentPos_) || (anchor != anchor_)) {
+               int firstAffected = anchor;
+               if (firstAffected > currentPos)
+                       firstAffected = currentPos;
+               if (firstAffected > anchor_)
+                       firstAffected = anchor_;
+               if (firstAffected > currentPos_)
+                       firstAffected = currentPos_;
+               int lastAffected = anchor;
+               if (lastAffected < currentPos)
+                       lastAffected = currentPos;
+               if (lastAffected < anchor_)
+                       lastAffected = anchor_;
+               if (lastAffected < (currentPos_ + 1))   // +1 ensures caret repainted
+                       lastAffected = (currentPos_ + 1);
+               currentPos = currentPos_;
+               anchor = anchor_;
+               needUpdateUI = true;
+               InvalidateRange(firstAffected, lastAffected);
+       }
+       ClaimSelection();
+}
+
+void Editor::SetSelection(int currentPos_) {
+       currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+       if (currentPos != currentPos_) {
+               int firstAffected = anchor;
+               if (firstAffected > currentPos)
+                       firstAffected = currentPos;
+               if (firstAffected > currentPos_)
+                       firstAffected = currentPos_;
+               int lastAffected = anchor;
+               if (lastAffected < currentPos)
+                       lastAffected = currentPos;
+               if (lastAffected < (currentPos_ + 1))   // +1 ensures caret repainted
+                       lastAffected = (currentPos_ + 1);
+               currentPos = currentPos_;
+               needUpdateUI = true;
+               InvalidateRange(firstAffected, lastAffected);
+       }
+       ClaimSelection();
+}
+
+void Editor::SetEmptySelection(int currentPos_) {
+       SetSelection(currentPos_, currentPos_);
+}
+
+int Editor::MovePositionTo(int newPos, bool extend) {
+       int delta = newPos - currentPos;
+       newPos = pdoc->ClampPositionIntoDocument(newPos);
+       newPos = pdoc->MovePositionOutsideChar(newPos, delta);
+       if (extend) {
+               SetSelection(newPos);
+       } else {
+               SetEmptySelection(newPos);
+       }
+       EnsureCaretVisible();
+       ShowCaretAtCurrentPosition();
+       return 0;
+}
+
+int Editor::MovePositionSoVisible(int pos, int moveDir) {
+       pos = pdoc->ClampPositionIntoDocument(pos);
+       pos = pdoc->MovePositionOutsideChar(pos, moveDir);
+       int lineDoc = pdoc->LineFromPosition(pos);
+       if (cs.GetVisible(lineDoc)) {
+               return pos;
+       } else {
+               int lineDisplay = cs.DisplayFromDoc(lineDoc);
+               if (moveDir > 0) {
+                       lineDisplay = Platform::Clamp(lineDisplay + 1, 0, cs.LinesDisplayed());
+                       return pdoc->LineStart(cs.DocFromDisplay(lineDisplay));
+               } else {
+                       // lineDisplay is already line before fold as lines in fold use display line of line before fold
+                       lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
+                       return pdoc->LineEndPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
+               }
+       }
+}
+
+// Choose the x position that the caret will try to stick to as it is moves up and down
+void Editor::SetLastXChosen() {
+       Point pt = LocationFromPosition(currentPos);
+       lastXChosen = pt.x;
+}
+
+void Editor::ScrollTo(int line) {
+       int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
+       if (topLineNew != topLine) {
+               // Try to optimise small scrolls
+               int linesToMove = topLine - topLineNew;
+               SetTopLine(topLineNew);
+               ShowCaretAtCurrentPosition();
+               // Perform redraw rather than scroll if many lines would be redrawn anyway.
+               if (abs(linesToMove) <= 10) {
+                       ScrollText(linesToMove);
+               } else {
+                       Redraw();
+               }
+               SetVerticalScrollPos();
+       }
+}
+
+void Editor::ScrollText(int linesToMove) {
+       //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
+       Redraw();
+}
+
+void Editor::HorizontalScrollTo(int xPos) {
+       //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
+       xOffset = xPos;
+       if (xOffset < 0)
+               xOffset = 0;
+       SetHorizontalScrollPos();
+       Redraw();
+}
+
+void Editor::EnsureCaretVisible(bool useMargin) {
+       //Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
+       PRectangle rcClient = GetTextRectangle();
+       int posCaret = currentPos;
+       if (posDrag >= 0)
+               posCaret = posDrag;
+       Point pt = LocationFromPosition(posCaret);
+       Point ptEOL = LocationFromPosition(pdoc->LineEndPosition(posCaret));
+       Point ptBottomCaret = pt;
+       int lineCaret = cs.DisplayFromDoc(pdoc->LineFromPosition(posCaret));
+       ptBottomCaret.y += vs.lineHeight - 1;
+
+       // Ensure the caret is reasonably visible in context.
+       int xMargin = Platform::Clamp(xCaretMargin, 2, Platform::Maximum(rcClient.Width() - 10, 4) / 2);
+       if (!useMargin)
+               xMargin = 2;
+       
+       // Ensure certain amount of text visible on both sides of caretSo move if caret just on edge
+       rcClient.left = rcClient.left + xMargin;
+       rcClient.right = rcClient.right - xMargin;
+       
+       if (!rcClient.Contains(pt) || !rcClient.Contains(ptBottomCaret) || (caretPolicy & CARET_STRICT)) {
+               //Platform::DebugPrintf("EnsureCaretVisible move, (%d,%d) (%d,%d)\n", pt.x, pt.y, rcClient.left, rcClient.right);
+               // It should be possible to scroll the window to show the caret,
+               // but this fails to remove the caret on GTK+
+               if (caretPolicy & CARET_SLOP) {
+                       if ((topLine > lineCaret) || ((caretPolicy & CARET_STRICT) && (topLine + caretSlop > lineCaret))) {
+                               SetTopLine(Platform::Clamp(lineCaret - caretSlop, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       } else if ((lineCaret > topLine + LinesOnScreen() - 1) || 
+                               ((caretPolicy & CARET_STRICT) && (lineCaret > topLine + LinesOnScreen() - 1 - caretSlop))) {
+                               SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() + 1 + caretSlop, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       }
+               } else {
+                       if ((topLine > lineCaret) || (lineCaret > topLine + LinesOnScreen() - 1) || (caretPolicy & CARET_STRICT)) {
+                               SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       }
+               }
+               int xOffsetNew = xOffset;
+               if (pt.x < rcClient.left) {
+                       xOffsetNew = xOffset - (rcClient.left - pt.x);
+               } else if (pt.x >= rcClient.right) {
+                       xOffsetNew = xOffset + (pt.x - rcClient.right);
+                       int xOffsetEOL = xOffset + (ptEOL.x - rcClient.right) - xMargin + 2;
+                       //Platform::DebugPrintf("Margin %d %d\n", xOffsetNew, xOffsetEOL);
+                       // Ensure don't scroll out into empty space
+                       if (xOffsetNew > xOffsetEOL)
+                               xOffsetNew = xOffsetEOL;
+               }
+               if (xOffsetNew < 0)
+                       xOffsetNew = 0;
+               if (xOffset != xOffsetNew) {
+                       xOffset = xOffsetNew;
+                       SetHorizontalScrollPos();
+                       Redraw();
+               }
+       }
+}
+
+void Editor::ShowCaretAtCurrentPosition() {
+       if (!wMain.HasFocus()) {
+               caret.active = false;
+               caret.on = false;
+               return;
+       }
+       caret.active = true;
+       caret.on = true;
+       SetTicking(true);
+}
+
+void Editor::DropCaret() {
+       caret.active = false;
+       InvalidateCaret();
+}
+
+void Editor::InvalidateCaret() {
+       if (posDrag >= 0)
+               InvalidateRange(posDrag, posDrag + 1);
+       else
+               InvalidateRange(currentPos, currentPos + 1);
+}
+
+void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
+       if (vs.fixedColumnWidth == 0)
+               return;
+
+       PRectangle rcMargin = GetClientRectangle();
+       rcMargin.right = vs.fixedColumnWidth;
+
+       if (!rc.Intersects(rcMargin))
+               return;
+
+       Surface *surface;
+       if (bufferedDraw) {
+               surface = &pixmapSelMargin;
+       } else {
+               surface = surfWindow;
+       }
+
+       PRectangle rcSelMargin = rcMargin;
+       rcSelMargin.right = rcMargin.left;
+
+       for (int margin=0; margin < vs.margins; margin++) {
+               if (vs.ms[margin].width > 0) {
+       
+                       rcSelMargin.left = rcSelMargin.right;
+                       rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+                       if (vs.ms[margin].symbol) {
+                               /* alternate scheme:
+                               if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+                                       surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+                               else
+                                       // Required because of special way brush is created for selection margin
+                                       surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
+                               */
+                               if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+                                       // Required because of special way brush is created for selection margin
+                                       surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
+                               else
+                                       surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated); 
+                       } else {
+                               surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated);
+                       }
+                       
+                       int visibleLine = topLine;
+                       int line = cs.DocFromDisplay(visibleLine);
+                       int yposScreen = 0;
+
+                       while (line < pdoc->LinesTotal() && yposScreen < rcMargin.bottom) {
+                               int marks = pdoc->GetMark(line);
+                               if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+                                       if (cs.GetExpanded(line)) {
+                                               marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+                                       } else {
+                                               marks |= 1 << SC_MARKNUM_FOLDER;
+                                       }
+                               }
+                               marks &= vs.ms[margin].mask;
+                               PRectangle rcMarker = rcSelMargin;
+                               rcMarker.top = yposScreen;
+                               rcMarker.bottom = yposScreen + vs.lineHeight;
+                               if (!vs.ms[margin].symbol) {
+                                       char number[100];
+                                       number[0] = '\0';
+                                       sprintf(number, "%d", line + 1);
+                                       if (foldFlags & 8)
+                                               sprintf(number, "%X", pdoc->GetLevel(line));
+                                       int xpos = 0;
+                                       PRectangle rcNumber=rcMarker;
+                                       // Right justify
+                                       int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, strlen(number));
+                                       xpos = rcNumber.right - width - 3;
+                                       rcNumber.left = xpos;
+                                       if ((visibleLine < cs.LinesDisplayed()) && cs.GetVisible(line)) {
+                                               surface->DrawText(rcNumber, vs.styles[STYLE_LINENUMBER].font,
+                                                                 rcNumber.top + vs.maxAscent, number, strlen(number),
+                                                                 vs.styles[STYLE_LINENUMBER].fore.allocated, 
+                                                                 vs.styles[STYLE_LINENUMBER].back.allocated);
+                                       }
+                               }
+                               
+                               if (marks) {
+                                       for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+                                               if (marks & 1) {
+                                                       rcMarker.top++;
+                                                       rcMarker.bottom--;
+                                                       vs.markers[markBit].Draw(surface, rcMarker);
+                                               }
+                                               marks >>= 1;
+                                       }
+                               }
+                               
+                               visibleLine++;
+                               line = cs.DocFromDisplay(visibleLine);
+                               yposScreen += vs.lineHeight;
+                       }
+               }
+       }
+
+       PRectangle rcBlankMargin = rcMargin;
+       rcBlankMargin.left = rcSelMargin.right;
+       surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+       
+       if (bufferedDraw) {
+               surfWindow->Copy(rcMargin, Point(), pixmapSelMargin);
+       }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+       int ydiff = (rcTab.bottom - rcTab.top) / 2;
+       int xhead = rcTab.right - 1 - ydiff;
+       if ((rcTab.left + 2) < (rcTab.right - 1))
+               surface->MoveTo(rcTab.left + 2, ymid);
+       else
+               surface->MoveTo(rcTab.right - 1, ymid);
+       surface->LineTo(rcTab.right - 1, ymid);
+       surface->LineTo(xhead, ymid - ydiff);
+       surface->MoveTo(rcTab.right - 1, ymid);
+       surface->LineTo(xhead, ymid + ydiff);
+}
+
+void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll) {
+       int numCharsInLine = 0;
+       int posLineStart = pdoc->LineStart(line);
+       int posLineEnd = pdoc->LineStart(line + 1);
+       Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
+       char styleByte = 0;
+       int styleMask = pdoc->stylingBitsMask;
+       for (int charInDoc = posLineStart; 
+               charInDoc < posLineEnd && numCharsInLine < LineLayout::maxLineLength - 1; 
+               charInDoc++) {
+               char chDoc = pdoc->CharAt(charInDoc);
+               styleByte = pdoc->StyleAt(charInDoc);
+               if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) {
+                       ll.chars[numCharsInLine] = chDoc;
+                       ll.styles[numCharsInLine] = styleByte & styleMask;
+                       ll.indicators[numCharsInLine] = styleByte & ~styleMask;
+                       numCharsInLine++;
+               }
+       }
+       ll.chars[numCharsInLine] = 0;
+       ll.styles[numCharsInLine] = styleByte;  // For eolFilled
+       ll.indicators[numCharsInLine] = 0;
+
+       // Layout the line, determining the position of each character
+       int startseg = 0;
+       int startsegx = 0;
+       ll.positions[0] = 0;
+       unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
+       
+       for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
+               if ((ll.styles[charInLine] != ll.styles[charInLine + 1]) ||
+                       IsControlCharacter(ll.chars[charInLine]) || IsControlCharacter(ll.chars[charInLine + 1])) {
+                       ll.positions[startseg] = 0;
+                       if (IsControlCharacter(ll.chars[charInLine])) {
+                               if (ll.chars[charInLine] == '\t') {
+                                       ll.positions[charInLine + 1] = ((((startsegx + 2) /
+                                                                          tabWidth) + 1) * tabWidth) - startsegx;
+                               } else {
+                                       const char *ctrlChar = ControlCharacterString(ll.chars[charInLine]);
+                                       // +3 For a blank on front and rounded edge each side:
+                                       ll.positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, strlen(ctrlChar)) + 3;
+                               }
+                       } else {
+                               surface->MeasureWidths(vstyle.styles[ll.styles[charInLine]].font, ll.chars + startseg, 
+                                       charInLine - startseg + 1, ll.positions + startseg + 1);
+                       }
+                       for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) {
+                               ll.positions[posToIncrease] += startsegx;
+                       }
+                       startsegx = ll.positions[charInLine + 1];
+                       startseg = charInLine + 1;
+               }
+       }
+       ll.numCharsInLine = numCharsInLine;
+}
+
+void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout &ll) {
+       
+       PRectangle rcSegment = rcLine;
+       
+       // Using one font for all control characters so it can be controlled independently to ensure
+       // the box goes around the characters tightly. Seems to be no way to work out what height
+       // is taken by an individual character - internal leading gives varying results.
+       Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+       int marks = 0;
+       Colour markBack = Colour(0, 0, 0);
+       if (vsDraw.maskInLine) {
+               marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+               if (marks) {
+                       for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+                               if (marks & 1) {
+                                       markBack = vsDraw.markers[markBit].back.allocated;
+                               }
+                               marks >>= 1;
+                       }
+               }
+               marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+       }
+
+       int posLineStart = pdoc->LineStart(line);
+       int posLineEnd = pdoc->LineStart(line + 1);
+
+       int selStart = SelectionStart(line);
+       int selEnd = SelectionEnd(line);
+
+       int styleMask = pdoc->stylingBitsMask;
+       int startseg = 0;
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+
+               int iDoc = i + posLineStart;
+               // If there is the end of a style run for any reason
+               if ((ll.styles[i] != ll.styles[i + 1]) ||
+                       IsControlCharacter(ll.chars[i]) || IsControlCharacter(ll.chars[i + 1]) ||
+                       ((selStart != selEnd) && ((iDoc + 1 == selStart) || (iDoc + 1 == selEnd))) ||
+                               (i == (theEdge-1))) {
+                       int styleMain = ll.styles[i];
+                       Colour textBack = vsDraw.styles[styleMain].back.allocated;
+                       Colour textFore = vsDraw.styles[styleMain].fore.allocated;
+                       Font &textFont = vsDraw.styles[styleMain].font;
+                       bool inSelection = (iDoc >= selStart) && (iDoc < selEnd) && (selStart != selEnd);
+                       if (inSelection && !hideSelection) {
+                               if (vsDraw.selbackset)
+                                       textBack = vsDraw.selbackground.allocated;
+                               if (vsDraw.selforeset)
+                                       textFore = vsDraw.selforeground.allocated;
+                       } else {
+                               if (marks)
+                                       textBack = markBack;
+                               if ((edgeState == EDGE_BACKGROUND) && (i >= theEdge) && (ll.chars[i] != '\n') && (ll.chars[i] != '\r'))
+                                       textBack = vs.edgecolour.allocated;
+                       }
+                       // Manage tab display
+                       if (ll.chars[i] == '\t') {
+                               rcSegment.left = ll.positions[i] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               surface->FillRectangle(rcSegment, textBack);
+                               if (vsDraw.viewWhitespace) {
+                                       surface->PenColour(textFore);
+                                       PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+                                                        rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+                                       DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
+                               }
+                       // Manage control character display
+                       } else if (IsControlCharacter(ll.chars[i])) {
+                               const char *ctrlChar = ControlCharacterString(ll.chars[i]);
+                               rcSegment.left = ll.positions[i] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               surface->FillRectangle(rcSegment, textBack);
+                               int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+                                                      surface->InternalLeading(ctrlCharsFont);
+                               PRectangle rcCChar = rcSegment;
+                               rcCChar.left = rcCChar.left + 1;
+                               rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+                               rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+                               PRectangle rcCentral = rcCChar;
+                               rcCentral.top++;
+                               rcCentral.bottom--;
+                               surface->FillRectangle(rcCentral, textFore);
+                               PRectangle rcChar = rcCChar;
+                               rcChar.left++;
+                               rcChar.right--;
+                               surface->DrawTextClipped(rcChar, ctrlCharsFont,
+                                                       rcSegment.top + vsDraw.maxAscent, ctrlChar, strlen(ctrlChar), 
+                                                       textBack, textFore);
+                       // Manage normal display
+                       } else {
+                               rcSegment.left = ll.positions[startseg] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               // Only try do draw if really visible - enhances performance by not calling environment to 
+                               // draw strings that are completely past the right side of the window.
+                               if (rcSegment.left <= rcLine.right) {
+                                       surface->DrawText(rcSegment, textFont,
+                                                         rcSegment.top + vsDraw.maxAscent, ll.chars + startseg,
+                                                         i - startseg + 1, textFore, textBack);
+                                       if (vsDraw.viewWhitespace) {
+                                               for (int cpos = 0; cpos <= i - startseg; cpos++) {
+                                                       if (ll.chars[cpos + startseg] == ' ') {
+                                                               int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2;
+                                                               PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+                                                               rcDot.right = rcDot.left + 1;
+                                                               rcDot.bottom = rcDot.top + 1;
+                                                               surface->FillRectangle(rcDot, textFore);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       startseg = i + 1;
+               }
+       }
+
+       // Draw indicators
+       int indStart[INDIC_MAX + 1] = {0};
+       for (int indica = 0; indica <= INDIC_MAX; indica++)
+               indStart[indica] = 0;
+
+       for (int indicPos = 0; indicPos <= ll.numCharsInLine; indicPos++) {
+               if (ll.indicators[indicPos] != ll.indicators[indicPos + 1]) {
+                       int mask = 1 << pdoc->stylingBits;
+                       for (int indicnum = 0; mask <= 0x100; indicnum++) {
+                               if ((ll.indicators[indicPos + 1] & mask) && !(ll.indicators[indicPos] & mask)) {
+                                       indStart[indicnum] = ll.positions[indicPos + 1];
+                               }
+                               if (!(ll.indicators[indicPos + 1] & mask) && (ll.indicators[indicPos] & mask)) {
+                                       PRectangle rcIndic(
+                                           indStart[indicnum] + xStart,
+                                           rcLine.top + vsDraw.maxAscent,
+                                           ll.positions[indicPos + 1] + xStart,
+                                           rcLine.top + vsDraw.maxAscent + 3);
+                                       vsDraw.indicators[indicnum].Draw(surface, rcIndic);
+                               }
+                               mask = mask << 1;
+                       }
+               }
+       }
+       // End of the drawing of the current line
+
+       // Fill in a PRectangle representing the end of line characters
+       int xEol = ll.positions[ll.numCharsInLine];
+       rcSegment.left = xEol + xStart;
+       rcSegment.right = xEol + vsDraw.aveCharWidth + xStart;
+       bool eolInSelection = (posLineEnd > selStart) && (posLineEnd <= selEnd) && (selStart != selEnd);
+       if (eolInSelection && !hideSelection && vsDraw.selbackset && (line < pdoc->LinesTotal()-1)) {
+               surface->FillRectangle(rcSegment, vsDraw.selbackground.allocated);
+       } else if (marks) {
+               surface->FillRectangle(rcSegment, markBack);
+       } else {
+               surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+       }
+
+       rcSegment.left = xEol + vsDraw.aveCharWidth + xStart;
+       rcSegment.right = rcLine.right;
+       if (marks) {
+               surface->FillRectangle(rcSegment, markBack);
+       } else if (vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].eolFilled) {
+               surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+       } else {
+               surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);
+       }
+       
+       if (edgeState == EDGE_LINE) {
+               int edgeX = theEdge * vsDraw.spaceWidth;
+               rcSegment.left = edgeX + xStart;
+               rcSegment.right = rcSegment.left + 1;
+               surface->FillRectangle(rcSegment, vs.edgecolour.allocated);
+       }
+}
+
+void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+       //Platform::DebugPrintf("Paint %d %d - %d %d\n", rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+       RefreshStyleData();
+
+       PRectangle rcClient = GetClientRectangle();
+       //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n",
+       //      rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+       if (!pixmapSelPattern.Initialised()) {
+               pixmapSelPattern.InitPixMap(8, 8, surfaceWindow);
+               // This complex procedure is to reproduce the checker board dithered pattern used by windows
+               // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+               // way between the chrome colour and the chrome highlight colour making a nice transition
+               // between the window chrome and the content area. And it works in low colour depths.
+               PRectangle rcPattern(0, 0, 8, 8);
+               if (vs.selbarlight.desired == Colour(0xff, 0xff, 0xff)) {
+                       pixmapSelPattern.FillRectangle(rcPattern, vs.selbar.allocated);
+                       pixmapSelPattern.PenColour(vs.selbarlight.allocated);
+                       for (int stripe = 0; stripe < 8; stripe++) {
+                               pixmapSelPattern.MoveTo(0, stripe * 2);
+                               pixmapSelPattern.LineTo(8, stripe * 2 - 8);
+                       }
+               } else {
+                       // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+                       pixmapSelPattern.FillRectangle(rcPattern, vs.selbarlight.allocated);
+               }
+       }
+
+       if (bufferedDraw) {
+               if (!pixmapLine.Initialised()) {
+                       pixmapLine.InitPixMap(rcClient.Width(), rcClient.Height(),
+                                             surfaceWindow);
+                       pixmapSelMargin.InitPixMap(vs.fixedColumnWidth,
+                                                  rcClient.Height(), surfaceWindow);
+               }
+       }
+
+       surfaceWindow->SetPalette(&palette, true);
+       pixmapLine.SetPalette(&palette, !wMain.HasFocus());
+
+       //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n",
+       //      rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+
+       int screenLinePaintFirst = rcArea.top / vs.lineHeight;
+       // The area to be painted plus one extra line is styled.
+       // The extra line is to determine when a style change, such as statrting a comment flows on to other lines.
+       int lineStyleLast = topLine + (rcArea.bottom-1) / vs.lineHeight + 1;
+       //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);
+       int endPosPaint = pdoc->Length();
+       if (lineStyleLast < cs.LinesDisplayed())
+               endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast + 1));
+
+       int xStart = vs.fixedColumnWidth - xOffset;
+       int ypos = 0;
+       if (!bufferedDraw)
+               ypos += screenLinePaintFirst * vs.lineHeight;
+       int yposScreen = screenLinePaintFirst * vs.lineHeight;
+
+       if (endPosPaint > pdoc->GetEndStyled()) {
+               // Notify container to do some more styling
+               NotifyStyleNeeded(endPosPaint);
+       }
+       if (needUpdateUI) {
+               NotifyUpdateUI();
+               needUpdateUI = false;
+       }
+       
+       PaintSelMargin(surfaceWindow, rcArea);
+
+       PRectangle rcRightMargin = rcClient;
+       rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+       if (rcArea.Intersects(rcRightMargin)) {
+               surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+       }
+
+       if (paintState == paintAbandoned) {
+               // Either NotifyStyleNeeded or NotifyUpdateUI noticed that painting is needed
+               // outside the current painting rectangle
+               //Platform::DebugPrintf("Abandoning paint\n");
+               return;
+       }
+       //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+       Surface *surface = 0;
+       if (rcArea.right > vs.fixedColumnWidth) {
+
+               if (bufferedDraw) {
+                       surface = &pixmapLine;
+               } else {
+                       surface = surfaceWindow;
+               }
+
+               int visibleLine = topLine + screenLinePaintFirst;
+               int line = cs.DocFromDisplay(visibleLine);
+
+               int posCaret = currentPos;
+               if (posDrag >= 0)
+                       posCaret = posDrag;
+               int lineCaret = pdoc->LineFromPosition(posCaret);
+
+               // Remove selection margin from drawing area so text will not be drawn
+               // on it in unbuffered mode.
+               PRectangle rcTextArea = rcClient;
+               rcTextArea.left = vs.fixedColumnWidth;
+               rcTextArea.right -= vs.rightMarginWidth;
+               surfaceWindow->SetClip(rcTextArea);
+               //GTimer *tim=g_timer_new();
+               while (visibleLine <= cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+                       //g_timer_start(tim);
+                       //Platform::DebugPrintf("Painting line %d\n", line);
+
+                       int posLineStart = pdoc->LineStart(line);
+                       int posLineEnd = pdoc->LineStart(line + 1);
+                       //Platform::DebugPrintf("line %d %d - %d\n", line, posLineStart, posLineEnd);
+
+                       PRectangle rcLine = rcClient;
+                       rcLine.top = ypos;
+                       rcLine.bottom = ypos + vs.lineHeight;
+
+                       // Copy this line and its styles from the document into local arrays
+                       // and determine the x position at which each character starts.
+                       LineLayout ll;
+                       LayoutLine(line, surface, vs, ll);
+                                                       
+                       // Highlight the current braces if any
+                       if ((braces[0] >= posLineStart) && (braces[0] < posLineEnd))
+                               ll.styles[braces[0] - posLineStart] = bracesMatchStyle;
+                       if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd))
+                               ll.styles[braces[1] - posLineStart] = bracesMatchStyle;
+                               
+                       // Draw the line
+                       if (cs.GetVisible(line))
+                               DrawLine(surface, vs, line, xStart, rcLine, ll);
+
+                       if (foldFlags & 2) {
+                               if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+                                       PRectangle rcFoldLine = rcLine;
+                                       rcFoldLine.bottom = rcFoldLine.top + 1;
+                                       surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+                               }
+                       }
+                       
+                       // Draw the Caret
+                       if (line == lineCaret) {
+                               int xposCaret = ll.positions[posCaret - posLineStart] + xStart;
+                               int widthOverstrikeCaret =
+                                   ll.positions[posCaret - posLineStart + 1] - ll.positions[posCaret - posLineStart];
+                               if (posCaret == pdoc->Length()) // At end of document
+                                       widthOverstrikeCaret = vs.aveCharWidth;
+                               if ((posCaret - posLineStart) >= ll.numCharsInLine)     // At end of line
+                                       widthOverstrikeCaret = vs.aveCharWidth;
+                               if (widthOverstrikeCaret < 3)   // Make sure its visible
+                                       widthOverstrikeCaret = 3;
+                               if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) {
+                                       PRectangle rcCaret = rcLine;
+                                       if (posDrag >= 0) {
+                                               rcCaret.left = xposCaret;
+                                               rcCaret.right = xposCaret + 1;
+                                       } else {
+                                               if (inOverstrike) {
+                                                       rcCaret.top = rcCaret.bottom - 2;
+                                                       rcCaret.left = xposCaret + 1;
+                                                       rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+                                               } else {
+                                                       rcCaret.left = xposCaret;
+                                                       rcCaret.right = xposCaret + 1;
+                                               }
+                                       }
+                                       surface->FillRectangle(rcCaret, vs.caretcolour.allocated);
+                               }
+                       }
+                       
+                       if (cs.GetVisible(line)) {
+                               if (bufferedDraw) {
+                                       Point from(vs.fixedColumnWidth, 0);
+                                       PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen,
+                                                         rcClient.right, yposScreen + vs.lineHeight);
+                                       surfaceWindow->Copy(rcCopyArea, from, pixmapLine);
+                               }
+                       }
+
+                       if (!bufferedDraw) {
+                               ypos += vs.lineHeight;
+                       }
+
+                       yposScreen += vs.lineHeight;
+                       visibleLine++;
+                       line = cs.DocFromDisplay(visibleLine);
+                       //gdk_flush();
+                       //g_timer_stop(tim);
+                       //Platform::DebugPrintf("Paint [%0d] took %g\n", line, g_timer_elapsed(tim, 0));
+               }
+               //g_timer_destroy(tim);
+               PRectangle rcBeyondEOF = rcClient;
+               rcBeyondEOF.left = vs.fixedColumnWidth;
+               rcBeyondEOF.right = rcBeyondEOF.right;
+               rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
+               if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+                       surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back.allocated);
+                       if (edgeState == EDGE_LINE) {
+                               int edgeX = theEdge * vs.spaceWidth;
+                               rcBeyondEOF.left = edgeX + xStart;
+                               rcBeyondEOF.right = rcBeyondEOF.left + 1;
+                               surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated);
+                       }
+               }
+       }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace "   "
+
+// This is mostly copied from the Paint method but with some things omitted
+// such as the margin markers, line numbers, selection and caret
+// Should be merged back into a combined Draw method.
+long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
+       if (!pfr)
+               return 0;
+
+       Surface *surface = new Surface();
+       surface->Init(pfr->hdc);
+       Surface *surfaceMeasure = new Surface();
+       surfaceMeasure->Init(pfr->hdcTarget);
+       
+       ViewStyle vsPrint(vs);
+       
+       // Modify the view style for printing as do not normally want any of the transient features to be printed
+       // Printing supports only the line number margin.
+       int lineNumberIndex = -1;
+       for (int margin=0; margin < ViewStyle::margins; margin++) {
+               if ((!vsPrint.ms[margin].symbol) && (vsPrint.ms[margin].width > 0)) {
+                       lineNumberIndex = margin;
+               } else {
+                       vsPrint.ms[margin].width = 0;
+               }
+       }
+       vsPrint.showMarkedLines = false;
+       vsPrint.fixedColumnWidth = 0;
+       vsPrint.zoomLevel = 0;
+       // Don't show the selection when printing
+       vsPrint.selbackset = false;
+       vsPrint.selforeset = false;
+       // White background for the line numbers
+       vsPrint.styles[STYLE_LINENUMBER].back.desired = Colour(0xff,0xff,0xff); 
+       
+       vsPrint.Refresh(*surfaceMeasure);
+       // Ensure colours are set up
+       vsPrint.RefreshColourPalette(palette, true);
+       vsPrint.RefreshColourPalette(palette, false);
+       // Determining width must hapen after fonts have been realised in Refresh
+       int lineNumberWidth = 0;
+       if (lineNumberIndex >= 0) {
+               lineNumberWidth = surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, 
+                       "9999" lineNumberPrintSpace, 4 + strlen(lineNumberPrintSpace));
+               vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+       }
+
+       int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
+       int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+       if (linePrintLast < linePrintStart)
+               linePrintLast = linePrintStart;
+       int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax - 1);
+       if (linePrintLast > linePrintMax)
+               linePrintLast = linePrintMax;
+       //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+       //      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+       //      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+       int endPosPrint = pdoc->Length();
+       if (linePrintLast < pdoc->LinesTotal())
+               endPosPrint = pdoc->LineStart(linePrintLast + 1);
+
+       if (endPosPrint > pdoc->GetEndStyled()) {
+               // Notify container to do some more styling
+               NotifyStyleNeeded(endPosPrint);
+       }
+       int xStart = vsPrint.fixedColumnWidth + pfr->rc.left + lineNumberWidth;
+       int ypos = pfr->rc.top;
+       int line = linePrintStart;
+
+       if (draw) {     // Otherwise just measuring
+
+               while (line <= linePrintLast && ypos < pfr->rc.bottom) {
+
+                       PRectangle rcLine;
+                       rcLine.left = pfr->rc.left + lineNumberWidth;
+                       rcLine.top = ypos;
+                       rcLine.right = pfr->rc.right;
+                       rcLine.bottom = ypos + vsPrint.lineHeight;
+                       
+                       if (lineNumberWidth) {
+                               char number[100];
+                               sprintf(number, "%d" lineNumberPrintSpace, line + 1);
+                               PRectangle rcNumber = rcLine;
+                               rcNumber.right = rcNumber.left + lineNumberWidth;
+                               // Right justify
+                               rcNumber.left += lineNumberWidth - 
+                                       surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, number, strlen(number));
+                               surface->DrawText(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+                                                 ypos + vsPrint.maxAscent, number, strlen(number),
+                                                 vsPrint.styles[STYLE_LINENUMBER].fore.allocated, 
+                                                 vsPrint.styles[STYLE_LINENUMBER].back.allocated);
+                       }
+                       
+                       // Copy this line and its styles from the document into local arrays
+                       // and determine the x position at which each character starts.
+                       LineLayout ll;
+                       LayoutLine(line, surfaceMeasure, vsPrint, ll);
+                                                       
+                       // Draw the line
+                       DrawLine(surface, vsPrint, line, xStart, rcLine, ll);
+
+                       ypos += vsPrint.lineHeight;
+                       line++;
+               }
+       }
+
+       delete surface;
+       delete surfaceMeasure;
+
+       return endPosPrint;
+}
+
+void Editor::SetScrollBarsTo(PRectangle) {
+       RefreshStyleData();
+
+       int nMax = cs.LinesDisplayed();
+       int nPage = cs.LinesDisplayed() - MaxScrollPos() + 1;
+       bool modified = ModifyScrollBars(nMax, nPage);
+
+       // TODO: ensure always showing as many lines as possible
+       // May not be, if, for example, window made larger
+       if (topLine > MaxScrollPos()) {
+               SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
+               SetVerticalScrollPos();
+               Redraw();
+       }
+       if (modified)
+               Redraw();
+       //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
+}
+
+void Editor::SetScrollBars() {
+       PRectangle rsClient = GetClientRectangle();
+       SetScrollBarsTo(rsClient);
+}
+
+void Editor::AddChar(char ch) {
+       bool wasSelection = currentPos != anchor;
+       ClearSelection();
+       if (inOverstrike && !wasSelection) {
+               if (currentPos < (pdoc->Length() - 1)) {
+                       if ((pdoc->CharAt(currentPos) != '\r') && (pdoc->CharAt(currentPos) != '\n')) {
+                               pdoc->DelChar(currentPos);
+                       }
+               }
+       }
+       pdoc->InsertChar(currentPos, ch);
+       SetEmptySelection(currentPos + 1);
+       EnsureCaretVisible();
+       SetLastXChosen();
+       NotifyChar(ch);
+}
+
+void Editor::ClearSelection() {
+       if (selType == selRectangle) {
+               pdoc->BeginUndoAction();
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int startPos = SelectionStart();
+               int line;
+               for (line=lineStart; line <= lineEnd; line++) {
+                       startPos = SelectionStart(line);
+                       unsigned int chars = SelectionEnd(line) - startPos;
+                       if (0 != chars) {
+                               pdoc->DeleteChars(startPos, chars);
+                       }
+               }
+               SetEmptySelection(startPos);
+               selType = selStream;
+               pdoc->EndUndoAction();
+       } else {
+               int startPos = SelectionStart();
+               unsigned int chars = SelectionEnd() - startPos;
+               SetEmptySelection(startPos);
+               if (0 != chars) {
+                       pdoc->DeleteChars(startPos, chars);
+               }
+       }
+}
+
+void Editor::ClearAll() {
+       if (0 != pdoc->Length()) {
+               pdoc->DeleteChars(0, pdoc->Length());
+       }
+       cs.Clear();
+       anchor = 0;
+       currentPos = 0;
+       SetTopLine(0);
+       SetVerticalScrollPos();
+}
+
+void Editor::Cut() {
+       Copy();
+       ClearSelection();
+}
+
+void Editor::PasteRectangular(int pos, const char *ptr, int len) {
+       currentPos = pos;
+       int insertPos = currentPos;
+       int xInsert = XFromPosition(currentPos);
+       int line = pdoc->LineFromPosition(currentPos);
+       bool prevCr = false;
+       for (int i=0; i<len; i++) {
+               if ((ptr[i] == '\r') || (ptr[i] == '\n')) {
+                       if ((ptr[i] == '\r') || (!prevCr)) 
+                               line++;
+                       if (line >= pdoc->LinesTotal()) {
+                               if (pdoc->eolMode != SC_EOL_LF)
+                                       pdoc->InsertChar(pdoc->Length(), '\r');
+                               if (pdoc->eolMode != SC_EOL_CR)
+                                       pdoc->InsertChar(pdoc->Length(), '\n');
+                       }
+                       currentPos = PositionFromLineX(line, xInsert);
+                       prevCr = ptr[i] == '\r';
+               } else {
+                       pdoc->InsertString(currentPos, ptr+i, 1);
+                       currentPos++;
+                       insertPos = currentPos;
+                       prevCr = false;
+               }
+       }
+       SetEmptySelection(insertPos);
+}
+
+void Editor::Clear() {
+       if (currentPos == anchor) {
+               DelChar();
+       } else {
+               ClearSelection();
+       }
+       SetEmptySelection(currentPos);
+}
+
+void Editor::SelectAll() {
+       SetSelection(0, pdoc->Length());
+       Redraw();
+}
+
+void Editor::Undo() {
+       if (pdoc->CanUndo()) {
+               int newPos = pdoc->Undo();
+               SetEmptySelection(newPos);
+               EnsureCaretVisible();
+       }
+}
+
+void Editor::Redo() {
+       if (pdoc->CanRedo()) {
+               int newPos = pdoc->Redo();
+               SetEmptySelection(newPos);
+               EnsureCaretVisible();
+       }
+}
+
+void Editor::DelChar() {
+       pdoc->DelChar(currentPos);
+}
+
+void Editor::DelCharBack() {
+       if (currentPos == anchor) {
+               int newPos = pdoc->DelCharBack(currentPos);
+               SetEmptySelection(newPos);
+       } else {
+               ClearSelection();
+               SetEmptySelection(currentPos);
+       }
+}
+
+void Editor::NotifyFocus(bool) {
+}
+
+void Editor::NotifyStyleNeeded(int endStyleNeeded) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_STYLENEEDED;
+       scn.position = endStyleNeeded;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyChar(char ch) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_CHARADDED;
+       scn.ch = ch;
+       NotifyParent(scn);
+#ifdef MACRO_SUPPORT
+       if (recordingMacro) {
+               char txt[2];
+               txt[0] = ch;
+               txt[1] = '\0';
+               NotifyMacroRecord(EM_REPLACESEL, 0, (LPARAM) txt);
+       }
+#endif
+}
+
+void Editor::NotifySavePoint(bool isSavePoint) {
+       SCNotification scn;
+       if (isSavePoint) {
+               scn.nmhdr.code = SCN_SAVEPOINTREACHED;
+       } else {
+               scn.nmhdr.code = SCN_SAVEPOINTLEFT;
+       }
+       NotifyParent(scn);
+}
+
+void Editor::NotifyModifyAttempt() {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyDoubleClick(Point, bool) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_DOUBLECLICK;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyUpdateUI() {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_UPDATEUI;
+       NotifyParent(scn);
+}
+
+bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
+       int marginClicked = -1;
+       int x = 0;
+       for (int margin=0; margin < ViewStyle::margins; margin++) {
+               if ((pt.x > x) && (pt.x < x + vs.ms[margin].width))
+                       marginClicked = margin;
+               x += vs.ms[margin].width;
+       }
+       if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
+               SCNotification scn;
+               scn.nmhdr.code = SCN_MARGINCLICK;
+               scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+                               (alt ? SCI_ALT : 0);
+               scn.position = pdoc->LineStart(LineFromLocation(pt));
+               scn.margin = marginClicked;
+               NotifyParent(scn);
+               return true;
+       } else {
+               return false;
+       }
+}
+
+void Editor::NotifyNeedShown(int pos, int len) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_NEEDSHOWN;
+       scn.position = pos;
+       scn.length = len;
+       NotifyParent(scn);
+}
+
+// Notifications from document
+void Editor::NotifyModifyAttempt(Document*, void *) {
+       //Platform::DebugPrintf("** Modify Attempt\n");
+       NotifyModifyAttempt();
+}
+
+void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
+       //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
+       NotifySavePoint(atSavePoint);
+}
+
+void Editor::NotifyModified(Document*, DocModification mh, void *) {
+       needUpdateUI = true;
+       if (paintState == painting) {
+               CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
+       } else if (paintState == notPainting) {
+               if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+                       if (mh.position < pdoc->LineStart(topLine)) {
+                               // Styling performed before this view
+                               Redraw();
+                       } else {
+                               InvalidateRange(mh.position, mh.position + mh.length);
+                       }
+               } else {
+                       // Move selection and brace highlights
+                       if (mh.modificationType & SC_MOD_INSERTTEXT) {
+                               if (currentPos > mh.position) {
+                                       currentPos += mh.length;
+                               }
+                               if (anchor > mh.position) {
+                                       anchor += mh.length;
+                               }
+                               if (braces[0] > mh.position) {
+                                       braces[0] += mh.length;
+                               }
+                               if (braces[1] > mh.position) {
+                                       braces[1] += mh.length;
+                               }
+                       } else {        // SC_MOD_DELETETEXT
+                               int endPos = mh.position + mh.length;
+                               if (currentPos > mh.position) {
+                                       if (currentPos > endPos) {
+                                               currentPos -= mh.length;
+                                       } else {
+                                               currentPos = endPos;
+                                       }
+                               }
+                               if (anchor > mh.position) {
+                                       if (anchor > endPos) {
+                                               anchor -= mh.length;
+                                       } else {
+                                               anchor = endPos;
+                                       }
+                               }
+                               if (braces[0] > mh.position) {
+                                       if (braces[0] > endPos) {
+                                               braces[0] -= mh.length;
+                                       } else {
+                                               braces[0] = endPos;
+                                       }
+                               }
+                               if (braces[1] > mh.position) {
+                                       if (braces[1] > endPos) {
+                                               braces[1] -= mh.length;
+                                       } else {
+                                               braces[1] = endPos;
+                                       }
+                               }
+                       }
+                       if (mh.linesAdded != 0) {
+
+                               // Update contraction state for inserted and removed lines
+                               // lineOfPos should be calculated in context of state before modification, shouldn't it
+                               int lineOfPos = pdoc->LineFromPosition(mh.position);
+                               if (mh.linesAdded > 0) {
+                                       NotifyNeedShown(mh.position, mh.length);
+                                       cs.InsertLines(lineOfPos, mh.linesAdded);
+                               } else {
+                                       cs.DeleteLines(lineOfPos, -mh.linesAdded);
+                               }
+                               // Avoid scrolling of display if change before current display
+                               if (mh.position < posTopLine) {
+                                       int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
+                                       if (newTop != topLine) {
+                                               SetTopLine(newTop);
+                                               SetVerticalScrollPos();
+                                       }
+                               }
+                               
+                               //Platform::DebugPrintf("** %x Doc Changed\n", this);
+                               // TODO: could invalidate from mh.startModification to end of screen
+                               //InvalidateRange(mh.position, mh.position + mh.length);
+                               Redraw();
+                       } else {
+                               //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
+                               //      mh.position, mh.position + mh.length);
+                               InvalidateRange(mh.position, mh.position + mh.length);
+                       }
+               }
+       } // else paintState == paintAbandoned so no need to do anything
+
+       if (mh.linesAdded != 0) {
+               SetScrollBars();
+       }
+
+       // If client wants to see this modification
+       if (mh.modificationType & modEventMask) {
+               if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
+                       // Real modification made to text of document.
+                       NotifyChange(); // Send EN_CHANGE
+               }
+               SCNotification scn;
+               scn.nmhdr.code = SCN_MODIFIED;
+               scn.position = mh.position;
+               scn.modificationType = mh.modificationType;
+               scn.text = mh.text;
+               scn.length = mh.length;
+               scn.linesAdded = mh.linesAdded;
+               scn.line = mh.line;
+               scn.foldLevelNow = mh.foldLevelNow;
+               scn.foldLevelPrev = mh.foldLevelPrev;
+               NotifyParent(scn);
+       }
+}
+
+void Editor::NotifyDeleted(Document *document, void *userData) {
+       /* Do nothing */
+}
+
+#ifdef MACRO_SUPPORT
+void Editor::NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+
+       // Enumerates all macroable messages
+       switch (iMessage) {
+       case WM_CUT:
+       case WM_COPY:
+       case WM_PASTE:
+       case WM_CLEAR:
+       case EM_REPLACESEL:
+       case SCI_ADDTEXT:
+       case SCI_INSERTTEXT:
+       case SCI_CLEARALL:
+       case SCI_SELECTALL:
+       case SCI_GOTOLINE:
+       case SCI_GOTOPOS:
+       case SCI_SEARCHANCHOR:
+       case SCI_SEARCHNEXT:
+       case SCI_SEARCHPREV:
+       case SCI_LINEDOWN:
+       case SCI_LINEDOWNEXTEND:
+       case SCI_LINEUP:
+       case SCI_LINEUPEXTEND:
+       case SCI_CHARLEFT:
+       case SCI_CHARLEFTEXTEND:
+       case SCI_CHARRIGHT:
+       case SCI_CHARRIGHTEXTEND:
+       case SCI_WORDLEFT:
+       case SCI_WORDLEFTEXTEND:
+       case SCI_WORDRIGHT:
+       case SCI_WORDRIGHTEXTEND:
+       case SCI_HOME:
+       case SCI_HOMEEXTEND:
+       case SCI_LINEEND:
+       case SCI_LINEENDEXTEND:
+       case SCI_DOCUMENTSTART:
+       case SCI_DOCUMENTSTARTEXTEND:
+       case SCI_DOCUMENTEND:
+       case SCI_DOCUMENTENDEXTEND:
+       case SCI_PAGEUP:
+       case SCI_PAGEUPEXTEND:
+       case SCI_PAGEDOWN:
+       case SCI_PAGEDOWNEXTEND:
+       case SCI_EDITTOGGLEOVERTYPE:
+       case SCI_CANCEL:
+       case SCI_DELETEBACK:
+       case SCI_TAB:
+       case SCI_BACKTAB:
+       case SCI_NEWLINE:
+       case SCI_FORMFEED:
+       case SCI_VCHOME:
+       case SCI_VCHOMEEXTEND:
+       case SCI_DELWORDLEFT:
+       case SCI_DELWORDRIGHT:
+               break;
+
+       // Filter out all others (display changes, etc)
+       default:
+//             printf("Filtered out %ld of macro recording\n", iMessage);
+               return;
+       }
+
+       // Send notification
+       SCNotification scn;
+       scn.nmhdr.code = SCN_MACRORECORD;
+       scn.message = iMessage;
+       scn.wParam = wParam;
+       scn.lParam = lParam;
+       NotifyParent(scn);
+}
+#endif
+
+// Force scroll and keep position relative to top of window
+void Editor::PageMove(int direction, bool extend) {
+       Point pt = LocationFromPosition(currentPos);
+       int topLineNew = Platform::Clamp(
+                        topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+       int newPos = PositionFromLocation(
+                        Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll())));
+       if (topLineNew != topLine) {
+               SetTopLine(topLineNew);
+               MovePositionTo(newPos, extend);
+               Redraw();
+               SetVerticalScrollPos();
+       } else {
+               MovePositionTo(newPos, extend);
+       }
+}
+
+int Editor::KeyCommand(UINT iMessage) {
+       Point pt = LocationFromPosition(currentPos);
+
+       switch (iMessage) {
+       case SCI_LINEDOWN:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y + vs.lineHeight)));
+               break;
+       case SCI_LINEDOWNEXTEND:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y + vs.lineHeight)), true);
+               break;
+       case SCI_LINEUP:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y - vs.lineHeight)));
+               break;
+       case SCI_LINEUPEXTEND:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y - vs.lineHeight)), true);
+               break;
+       case SCI_CHARLEFT:
+               if (SelectionEmpty()) {
+                       MovePositionTo(MovePositionSoVisible(currentPos - 1, -1));
+               } else {
+                       MovePositionTo(SelectionStart());
+               }
+               SetLastXChosen();
+               break;
+       case SCI_CHARLEFTEXTEND:
+               MovePositionTo(MovePositionSoVisible(currentPos - 1, -1), true);
+               SetLastXChosen();
+               break;
+       case SCI_CHARRIGHT:
+               if (SelectionEmpty()) {
+                       MovePositionTo(MovePositionSoVisible(currentPos + 1, 1));
+               } else {
+                       MovePositionTo(SelectionEnd());
+               }
+               SetLastXChosen();
+               break;
+       case SCI_CHARRIGHTEXTEND:
+               MovePositionTo(MovePositionSoVisible(currentPos + 1, 1), true);
+               SetLastXChosen();
+               break;
+       case SCI_WORDLEFT:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1));
+               SetLastXChosen();
+               break;
+       case SCI_WORDLEFTEXTEND:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1), true);
+               SetLastXChosen();
+               break;
+       case SCI_WORDRIGHT:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1));
+               SetLastXChosen();
+               break;
+       case SCI_WORDRIGHTEXTEND:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1), true);
+               SetLastXChosen();
+               break;
+       case SCI_HOME:
+               MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)));
+               SetLastXChosen();
+               break;
+       case SCI_HOMEEXTEND:
+               MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)), true);
+               SetLastXChosen();
+               break;
+       case SCI_LINEEND:
+               MovePositionTo(pdoc->LineEndPosition(currentPos));
+               SetLastXChosen();
+               break;
+       case SCI_LINEENDEXTEND:
+               MovePositionTo(pdoc->LineEndPosition(currentPos), true);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTSTART:
+               MovePositionTo(0);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTSTARTEXTEND:
+               MovePositionTo(0, true);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTEND:
+               MovePositionTo(pdoc->Length());
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTENDEXTEND:
+               MovePositionTo(pdoc->Length(), true);
+               SetLastXChosen();
+               break;
+       case SCI_PAGEUP:
+               PageMove( -1);
+               break;
+       case SCI_PAGEUPEXTEND:
+               PageMove( -1, true);
+               break;
+       case SCI_PAGEDOWN:
+               PageMove(1);
+               break;
+       case SCI_PAGEDOWNEXTEND:
+               PageMove(1, true);
+               break;
+       case SCI_EDITTOGGLEOVERTYPE:
+               inOverstrike = !inOverstrike;
+               DropCaret();
+               ShowCaretAtCurrentPosition();
+               break;
+       case SCI_CANCEL:        // Cancel any modes - handled in subclass
+               // Also unselect text
+               SetEmptySelection(currentPos);
+               break;
+       case SCI_DELETEBACK:
+               DelCharBack();
+               EnsureCaretVisible();
+               break;
+       case SCI_TAB:
+               Indent(true);
+               break;
+       case SCI_BACKTAB:
+               Indent(false);
+               break;
+       case SCI_NEWLINE:
+               ClearSelection();
+               if (pdoc->eolMode == SC_EOL_CRLF) {
+                       pdoc->InsertString(currentPos, "\r\n");
+                       SetEmptySelection(currentPos + 2);
+                       NotifyChar('\r');
+                       NotifyChar('\n');
+               } else if (pdoc->eolMode == SC_EOL_CR) {
+                       pdoc->InsertChar(currentPos, '\r');
+                       SetEmptySelection(currentPos + 1);
+                       NotifyChar('\r');
+               } else if (pdoc->eolMode == SC_EOL_LF) {
+                       pdoc->InsertChar(currentPos, '\n');
+                       SetEmptySelection(currentPos + 1);
+                       NotifyChar('\n');
+               }
+               SetLastXChosen();
+               EnsureCaretVisible();
+               break;
+       case SCI_FORMFEED:
+               AddChar('\f');
+               break;
+       case SCI_VCHOME:
+               MovePositionTo(pdoc->VCHomePosition(currentPos));
+               SetLastXChosen();
+               break;
+       case SCI_VCHOMEEXTEND:
+               MovePositionTo(pdoc->VCHomePosition(currentPos), true);
+               SetLastXChosen();
+               break;
+       case SCI_ZOOMIN:
+               if (vs.zoomLevel < 20)
+                       vs.zoomLevel++;
+               InvalidateStyleRedraw();
+               break;
+       case SCI_ZOOMOUT:
+               if (vs.zoomLevel > -10)
+                       vs.zoomLevel--;
+               InvalidateStyleRedraw();
+               break;
+       case SCI_DELWORDLEFT: {
+                       int startWord = pdoc->NextWordStart(currentPos, -1);
+                       pdoc->DeleteChars(startWord, currentPos - startWord);
+                       MovePositionTo(startWord);
+               }
+               break;
+       case SCI_DELWORDRIGHT: {
+                       int endWord = pdoc->NextWordStart(currentPos, 1);
+                       pdoc->DeleteChars(currentPos, endWord - currentPos);
+               }
+               break;
+       }
+       return 0;
+}
+
+int Editor::KeyDefault(int, int) {
+       return 0;
+}
+
+int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt) {
+       int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+                       (alt ? SCI_ALT : 0);
+       int msg = kmap.Find(key, modifiers);
+       if (msg)
+               return WndProc(msg, 0, 0);
+       else
+               return KeyDefault(key, modifiers);
+}
+
+void Editor::SetWhitespaceVisible(bool view) {
+       vs.viewWhitespace = view;
+}
+
+bool Editor::GetWhitespaceVisible() {
+       return vs.viewWhitespace;
+}
+
+void Editor::Indent(bool forwards) {
+       //Platform::DebugPrintf("INdent %d\n", forwards);
+       int lineOfAnchor = pdoc->LineFromPosition(anchor);
+       int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+       if (lineOfAnchor == lineCurrentPos) {
+               ClearSelection();
+               pdoc->InsertChar(currentPos, '\t');
+               //pdoc->InsertChar(currentPos++, '\t');
+               SetEmptySelection(currentPos + 1);
+       } else {
+               int anchorPosOnLine = anchor - pdoc->LineStart(lineOfAnchor);
+               int currentPosPosOnLine = currentPos - pdoc->LineStart(lineCurrentPos);
+               // Multiple lines selected so indent / dedent
+               int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
+               int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
+               if (pdoc->LineStart(lineBottomSel) == anchor || pdoc->LineStart(lineBottomSel) == currentPos)
+                       lineBottomSel--;        // If not selecting any characters on a line, do not indent
+               pdoc->BeginUndoAction();
+               pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+               pdoc->EndUndoAction();
+               if (lineOfAnchor < lineCurrentPos) {
+                       if (currentPosPosOnLine == 0)
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+                       else
+                               SetSelection(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
+               } else {
+                       if (anchorPosOnLine == 0)
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+                       else
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
+               }
+       }
+}
+
+long Editor::FindText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       FINDTEXTEX *ft = reinterpret_cast<FINDTEXTEX *>(lParam);
+       int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+                       wParam & FR_MATCHCASE, wParam & FR_WHOLEWORD);
+       if (pos != -1) {
+               if (iMessage == EM_FINDTEXTEX) {
+                       ft->chrgText.cpMin = pos;
+                       ft->chrgText.cpMax = pos + strlen(ft->lpstrText);
+               }
+       }
+       return pos;
+}
+
+// Relocatable search support : Searches relative to current selection 
+// point and sets the selection to the found text range with 
+// each search.
+
+// Anchor following searches at current selection start:  This allows
+// multiple incremental interactive searches to be macro recorded
+// while still setting the selection to found text so the find/select
+// operation is self-contained.
+void Editor::SearchAnchor() {
+       searchAnchor = SelectionStart();
+}
+
+// Find text from current search anchor:  Must call SearchAnchor first.
+// Accepts both SCI_SEARCHNEXT and SCI_SEARCHPREV.
+// wParam contains search modes : ORed FR_MATCHCASE and FR_WHOLEWORD.
+// lParam contains the text to search for.
+long Editor::SearchText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       const char *txt = reinterpret_cast<char *>(lParam);
+       int pos;
+
+       if (iMessage == SCI_SEARCHNEXT) {
+               pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, 
+                                    wParam & FR_MATCHCASE,
+                                    wParam & FR_WHOLEWORD);
+       } else {
+               pos = pdoc->FindText(searchAnchor, 0, txt, 
+                                    wParam & FR_MATCHCASE,
+                                    wParam & FR_WHOLEWORD);
+       }
+
+       if (pos != -1) {
+               SetSelection(pos, pos + strlen(txt));
+       }
+
+       return pos;
+}
+
+void Editor::GoToLine(int lineNo) {
+       if (lineNo > pdoc->LinesTotal())
+               lineNo = pdoc->LinesTotal();
+       if (lineNo < 0)
+               lineNo = 0;
+       SetEmptySelection(pdoc->LineStart(lineNo));
+       ShowCaretAtCurrentPosition();
+       EnsureCaretVisible();
+}
+
+static bool Close(Point pt1, Point pt2) {
+       if (abs(pt1.x - pt2.x) > 3)
+               return false;
+       if (abs(pt1.y - pt2.y) > 3)
+               return false;
+       return true;
+}
+
+char *Editor::CopyRange(int start, int end) {
+       char *text = 0;
+       if (start < end) {
+               int len = end - start;
+               text = new char[len + 1];
+               if (text) {
+                       for (int i = 0; i < len; i++) {
+                               text[i] = pdoc->CharAt(start + i);
+                       }
+                       text[len] = '\0';
+               }
+       }
+       return text;
+}
+
+int Editor::SelectionRangeLength() {
+       if (selType == selRectangle) {
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int totalSize = 0;
+               for (int line=lineStart; line <= lineEnd; line++) {
+                       totalSize += SelectionEnd(line) - SelectionStart(line) + 1;
+                       if (pdoc->eolMode == SC_EOL_CRLF)
+                               totalSize++;
+               }
+               return totalSize;
+       } else {
+               return SelectionEnd() - SelectionStart();
+       }
+}
+
+char *Editor::CopySelectionRange() {
+       if (selType == selRectangle) {
+               char *text = 0;
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int totalSize = SelectionRangeLength();
+               if (totalSize > 0) {
+                       text = new char[totalSize + 1];
+                       if (text) {
+                               int j = 0;
+                               for (int line=lineStart; line <= lineEnd; line++) {
+                                       for (int i=SelectionStart(line);i<SelectionEnd(line);i++) {
+                                               text[j++] = pdoc->CharAt(i);
+                                       }
+                                       if (pdoc->eolMode != SC_EOL_LF)
+                                               text[j++] = '\r';
+                                       if (pdoc->eolMode != SC_EOL_CR)
+                                               text[j++] = '\n';
+                               }
+                               text[totalSize] = '\0';
+                       }
+               }
+               return text;
+       } else {
+               return CopyRange(SelectionStart(), SelectionEnd());
+       }
+}
+
+void Editor::CopySelectionIntoDrag() {
+       delete []dragChars;
+       dragChars = 0;
+       lenDrag = SelectionRangeLength();
+       dragChars = CopySelectionRange();
+       dragIsRectangle = selType == selRectangle;
+       if (!dragChars) {
+               lenDrag = 0;
+       }
+}
+
+void Editor::SetDragPosition(int newPos) {
+       if (newPos >= 0) {
+               newPos = pdoc->MovePositionOutsideChar(newPos, 1);
+               posDrop = newPos;
+       }
+       if (posDrag != newPos) {
+               caret.on = true;
+               SetTicking(true);
+               InvalidateCaret();
+               posDrag = newPos;
+               InvalidateCaret();
+       }
+}
+
+void Editor::StartDrag() {
+       // Always handled by subclasses
+       //SetMouseCapture(true);
+       //wDraw.SetCursor(Window::cursorArrow);
+}
+
+void Editor::DropAt(int position, const char *value, bool moving, bool rectangular) {
+       //Platform::DebugPrintf("DropAt %d\n", inDragDrop);
+       if (inDragDrop)
+               dropWentOutside = false;
+
+       int positionWasInSelection = PositionInSelection(position);
+
+       if ((!inDragDrop) || !(0 == positionWasInSelection)) {
+
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               
+               pdoc->BeginUndoAction();
+
+               int positionAfterDeletion = position;
+               if (inDragDrop && moving) {
+                       // Remove dragged out text
+                       if (rectangular) {
+                               int lineStart = pdoc->LineFromPosition(SelectionStart());
+                               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+                               for (int line=lineStart; line <= lineEnd; line++) {
+                                       int startPos = SelectionStart(line);
+                                       int endPos = SelectionEnd(line);
+                                       if (position >= startPos) {
+                                               if (position > endPos) {
+                                                       positionAfterDeletion -= endPos - startPos;
+                                               } else {
+                                                       positionAfterDeletion -= position - startPos;
+                                               }
+                                       }
+                               }
+                       } else {
+                               if (position > selStart) {
+                                       positionAfterDeletion -= selEnd - selStart;
+                               }
+                       }
+                       ClearSelection();
+               }
+               position = positionAfterDeletion;
+               
+               if (rectangular) {
+                       PasteRectangular(position, value, strlen(value));
+                       pdoc->EndUndoAction();
+                       // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
+                       SetSelection(position, position);       
+               } else {
+                       position = pdoc->MovePositionOutsideChar(position, currentPos - position);
+                       pdoc->InsertString(position, value);
+                       pdoc->EndUndoAction();
+                       SetSelection(position + strlen(value), position);
+               }
+       } else if (inDragDrop) {
+               SetSelection(position, position);
+       }
+}
+
+static int BeforeInOrAfter(int val, int minim, int maxim) {
+       if (val < minim)
+               return -1;
+       else if (val > maxim)
+               return 1;
+       else
+               return 0;
+}
+
+int Editor::PositionInSelection(int pos) {
+       pos = pdoc->MovePositionOutsideChar(pos, currentPos - pos);
+       if (selType == selRectangle) {
+               if (pos < SelectionStart())
+                       return -1;
+               if (pos > SelectionEnd())
+                       return 1;
+               int linePos = pdoc->LineFromPosition(pos);
+               return BeforeInOrAfter(pos, SelectionStart(linePos), SelectionEnd(linePos));
+       } else {
+               if (currentPos > anchor) {
+                       return BeforeInOrAfter(pos, anchor, currentPos);
+               } else if (currentPos < anchor) {
+                       return BeforeInOrAfter(pos, currentPos, anchor);
+               }
+       }
+       return 1;
+}
+
+bool Editor::PointInSelection(Point pt) {
+       // TODO: fix up for rectangular selection
+       int pos = PositionFromLocation(pt);
+       if (0 == PositionInSelection(pos)) {
+               if (pos == SelectionStart()) {
+                       // see if just before selection
+                       Point locStart = LocationFromPosition(pos);
+                       if (pt.x < locStart.x)
+                               return false;
+               }
+               if (pos == SelectionEnd()) {
+                       // see if just after selection
+                       Point locEnd = LocationFromPosition(pos);
+                       if (pt.x > locEnd.x)
+                               return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+bool Editor::PointInSelMargin(Point pt) {
+       // Really means: "Point in a margin"
+       if (vs.fixedColumnWidth > 0) {  // There is a margin
+               PRectangle rcSelMargin = GetClientRectangle();
+               rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
+               return rcSelMargin.Contains(pt);
+       } else {
+               return false;
+       }
+}
+
+void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+       //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
+       ptMouseLast = pt;
+       int newPos = PositionFromLocation(pt);
+       newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+       inDragDrop = false;
+       
+       bool processed = NotifyMarginClick(pt, shift, ctrl, alt);
+       if (processed)
+               return;
+               
+       if (shift) {
+               SetSelection(newPos);
+       }
+       if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+               //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
+               SetMouseCapture(true);
+               SetEmptySelection(newPos);
+               bool doubleClick = false;
+               // Stop mouse button bounce changing selection type
+               if (curTime != lastClickTime) {
+                       if (selectionType == selChar) {
+                               selectionType = selWord;
+                               doubleClick = true;
+                       } else if (selectionType == selWord) {
+                               selectionType = selLine;
+                       } else {
+                               selectionType = selChar;
+                               originalAnchorPos = currentPos;
+                       }
+               }
+
+               if (selectionType == selWord) {
+                       if (currentPos >= originalAnchorPos) {  // Moved forward
+                               SetSelection(pdoc->ExtendWordSelect(currentPos, 1),
+                                            pdoc->ExtendWordSelect(originalAnchorPos, -1));
+                       } else {        // Moved backward
+                               SetSelection(pdoc->ExtendWordSelect(currentPos, -1),
+                                            pdoc->ExtendWordSelect(originalAnchorPos, 1));
+                       }
+               } else if (selectionType == selLine) {
+                       lineAnchor = LineFromLocation(pt);
+                       SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+                       //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
+               }
+               else {
+                       SetEmptySelection(currentPos);
+               }
+               //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
+               if (doubleClick)
+                       NotifyDoubleClick(pt, shift);
+       } else {        // Single click
+               if (PointInSelMargin(pt)) {
+                       if (ctrl) {
+                               SelectAll();
+                               lastClickTime = curTime;
+                               return;
+                       }
+                       lineAnchor = LineFromLocation(pt);
+                       // While experimenting with folding turn off line selection
+                       if (!shift) {
+                               // Single click in margin: select whole line
+                               SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+                       } else {
+                               // Single shift+click in margin: select from anchor to beginning of clicked line
+                               SetSelection(pdoc->LineStart(lineAnchor), anchor);
+                       }
+                       SetDragPosition(invalidPosition);
+                       SetMouseCapture(true);
+                       selectionType = selLine;
+               } else {
+                       if (!shift) {
+                               inDragDrop = PointInSelection(pt);
+                       }
+                       if (inDragDrop) {
+                               SetMouseCapture(false);
+                               SetDragPosition(newPos);
+                               CopySelectionIntoDrag();
+                               StartDrag();
+                       } else {
+                               selType = alt ? selRectangle : selStream;
+                               xStartSelect = pt.x - vs.fixedColumnWidth + xOffset;
+                               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+                               SetDragPosition(invalidPosition);
+                               SetMouseCapture(true);
+                               if (!shift)
+                                       SetEmptySelection(newPos);
+                               selectionType = selChar;
+                               originalAnchorPos = currentPos;
+                       }
+               }
+       }
+       lastClickTime = curTime;
+       lastXChosen = pt.x;
+       ShowCaretAtCurrentPosition();
+}
+
+void Editor::ButtonMove(Point pt) {
+       //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+       if (HaveMouseCapture()) {
+               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+               ptMouseLast = pt;
+               int movePos = PositionFromLocation(pt);
+               movePos = pdoc->MovePositionOutsideChar(movePos, currentPos - movePos);
+               if (posDrag >= 0) {
+                       SetDragPosition(movePos);
+               } else {
+                       if (selectionType == selChar) {
+                               SetSelection(movePos);
+                       } else if (selectionType == selWord) {
+                               // Continue selecting by word
+                               if (currentPos > originalAnchorPos) {   // Moved forward
+                                       SetSelection(pdoc->ExtendWordSelect(movePos, 1),
+                                                    pdoc->ExtendWordSelect(originalAnchorPos, -1));
+                               } else {        // Moved backward
+                                       SetSelection(pdoc->ExtendWordSelect(movePos, -1),
+                                                    pdoc->ExtendWordSelect(originalAnchorPos, 1));
+                               }
+                       } else {
+                               // Continue selecting by line
+                               int lineMove = LineFromLocation(pt);
+                               if (lineAnchor < lineMove) {
+                                       SetSelection(pdoc->LineStart(lineMove + 1),
+                                                               pdoc->LineStart(lineAnchor));
+                               } else {
+                                       SetSelection(pdoc->LineStart(lineMove),
+                                                               pdoc->LineStart(lineAnchor + 1));
+                               }
+                       }
+               }
+               EnsureCaretVisible(false);
+       } else {
+               if (vs.fixedColumnWidth > 0) {  // There is a margin
+                       if (PointInSelMargin(pt)) {
+                               wDraw.SetCursor(Window::cursorReverseArrow);
+                               return;         // No need to test for selection
+                       }
+               }
+               // Display regular (drag) cursor over selection
+               if (PointInSelection(pt))
+                       wDraw.SetCursor(Window::cursorArrow);
+               else
+                       wDraw.SetCursor(Window::cursorText);
+       }
+
+}
+
+void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+       //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+       if (HaveMouseCapture()) {
+               if (PointInSelMargin(pt)) {
+                       wDraw.SetCursor(Window::cursorReverseArrow);
+               } else {
+                       wDraw.SetCursor(Window::cursorText);
+               }
+               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+               ptMouseLast = pt;
+               SetMouseCapture(false);
+               int newPos = PositionFromLocation(pt);
+               newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+               if (inDragDrop) {
+                       int selStart = SelectionStart();
+                       int selEnd = SelectionEnd();
+                       if (selStart < selEnd) {
+                               if (dragChars && lenDrag) {
+                                       if (ctrl) {
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else if (newPos < selStart) {
+                                               pdoc->DeleteChars(selStart, lenDrag);
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else if (newPos > selEnd) {
+                                               pdoc->DeleteChars(selStart, lenDrag);
+                                               newPos -= lenDrag;
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else {
+                                               SetEmptySelection(newPos);
+                                       }
+                                       delete []dragChars;
+                                       dragChars = 0;
+                                       lenDrag = 0;
+                               }
+                               selectionType = selChar;
+                       }
+               } else {
+                       if (selectionType == selChar) {
+                               SetSelection(newPos);
+                       }
+               }
+               lastClickTime = curTime;
+               lastClick = pt;
+               lastXChosen = pt.x;
+               inDragDrop = false;
+               EnsureCaretVisible(false);
+       }
+}
+
+// Called frequently to perform background UI including
+// caret blinking and automatic scrolling.
+void Editor::Tick() {
+       if (HaveMouseCapture()) {
+               // Auto scroll
+               ButtonMove(ptMouseLast);
+       }
+       if (caret.period > 0) {
+               timer.ticksToWait -= timer.tickSize;
+               if (timer.ticksToWait <= 0) {
+                       caret.on = !caret.on;
+                       timer.ticksToWait = caret.period;
+                       InvalidateCaret();
+               }
+       }
+}
+
+static bool IsIn(int a, int minimum, int maximum) {
+       return (a >= minimum) && (a <= maximum);
+}
+
+static bool IsOverlap(int mina, int maxa, int minb, int maxb) {
+       return 
+               IsIn(mina, minb, maxb) ||
+               IsIn(maxa, minb, maxb) ||
+               IsIn(minb, mina, maxa) ||
+               IsIn(maxb, mina, maxa);
+}
+
+void Editor::CheckForChangeOutsidePaint(Range r) {
+       if (paintState == painting && !paintingAllText) {
+               //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
+               if (!r.Valid())
+                       return;
+                       
+               PRectangle rcText = GetTextRectangle();
+               // Determine number of lines displayed including a possible partially displayed last line
+               int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1;
+               int bottomLine = topLine + linesDisplayed - 1;
+               
+               int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start));
+               int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end));
+               if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+                       //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
+                       //              lineRangeStart, lineRangeEnd, topLine, bottomLine);
+                       return;
+               }
+               
+               // Assert rcPaint contained within or equal to rcText
+               if (rcPaint.top > rcText.top) {
+                       // does range intersect rcText.top .. rcPaint.top
+                       int paintTopLine = ((rcPaint.top - rcText.top-1) / vs.lineHeight) + topLine;
+                       // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
+                       if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) {
+                               //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", 
+                               //      lineRangeStart, lineRangeEnd, topLine, paintTopLine);
+                               paintState = paintAbandoned;
+                               return;
+                       }
+               }
+               if (rcPaint.bottom < rcText.bottom) {
+                       // does range intersect rcPaint.bottom .. rcText.bottom
+                       int paintBottomLine = ((rcPaint.bottom - rcText.top-1) / vs.lineHeight + 1) + topLine;
+                       // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
+                       if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+                               //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", 
+                               //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
+                               paintState = paintAbandoned;
+                               return;
+                       }
+               }
+       }
+}
+
+char BraceOpposite(char ch) {
+       switch (ch) {
+                case '(': return ')';
+                case ')': return '(';
+                case '[': return ']';
+                case ']': return '[';
+                case '{': return '}';
+                case '}': return '{';
+                case '<': return '>';
+                case '>': return '<';
+                default: return '\0';
+       }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+// TODO: may need to make DBCS safe
+// so should be moved into Document
+int Editor::BraceMatch(int position, int maxReStyle) {
+       char chBrace = pdoc->CharAt(position);
+       char chSeek = BraceOpposite(chBrace);
+       if (!chSeek)
+               return - 1;
+       char styBrace = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+       int direction = -1;
+       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+               direction = 1;
+       int depth = 1;
+       position = position + direction;
+       while ((position >= 0) && (position < pdoc->Length())) {
+               char chAtPos = pdoc->CharAt(position);
+               char styAtPos = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+               if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
+                       if (chAtPos == chBrace)
+                               depth++;
+                       if (chAtPos == chSeek)
+                               depth--;
+                       if (depth == 0)
+                               return position;
+               }
+               position = position + direction;
+       }
+       return - 1;
+}
+
+void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
+       if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
+               if ((braces[0] != pos0)  || (matchStyle != bracesMatchStyle)) {
+                       CheckForChangeOutsidePaint(Range(braces[0]));
+                       CheckForChangeOutsidePaint(Range(pos0));
+                       braces[0] = pos0;
+               }
+               if ((braces[1] != pos1)  || (matchStyle != bracesMatchStyle)) {
+                       CheckForChangeOutsidePaint(Range(braces[1]));
+                       CheckForChangeOutsidePaint(Range(pos1));
+                       braces[1] = pos1;
+               }
+               bracesMatchStyle = matchStyle;
+               if (paintState == notPainting) {
+                       Redraw();
+               }
+       }
+}
+
+void Editor::SetDocPointer(Document *document) {
+       //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
+       pdoc->RemoveWatcher(this, 0);
+       pdoc->Release();
+       if (document == NULL) {
+               pdoc = new Document();
+       } else {
+               pdoc = document;
+       }
+       pdoc->AddRef();
+       pdoc->AddWatcher(this, 0);
+       Redraw();
+       SetScrollBars();
+}
+
+// Recursively expand a fold, making lines visible except where they have an unexpanded parent
+void Editor::Expand(int &line, bool doExpand) {
+       int lineMaxSubord = pdoc->GetLastChild(line);
+       line++;
+       while (line <= lineMaxSubord) {
+               if (doExpand)
+                       cs.SetVisible(line, line, true);
+               int level = pdoc->GetLevel(line);
+               if (level & SC_FOLDLEVELHEADERFLAG) {
+                       if (doExpand && cs.GetExpanded(line)) {
+                               Expand(line, true);
+                       } else {
+                               Expand(line, false);
+                       }
+               } else {
+                       line++;
+               }
+       }
+}
+
+void Editor::ToggleContraction(int line) {
+       if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+               if (cs.GetExpanded(line)) {
+                       int lineMaxSubord = pdoc->GetLastChild(line);
+                       cs.SetExpanded(line, 0);
+                       if (lineMaxSubord > line) {
+                               cs.SetVisible(line+1, lineMaxSubord, false);
+                               SetScrollBars();
+                               Redraw();
+                       }
+               } else {
+                       cs.SetExpanded(line, 1);
+                       Expand(line, true);
+                       SetScrollBars();
+                       Redraw();
+               }
+       }
+}
+
+// Recurse up from this line to find any folds that prevent this line from being visible
+// and unfold them all.
+void Editor::EnsureLineVisible(int line) {
+       if (!cs.GetVisible(line)) {
+               int lineParent = pdoc->GetFoldParent(line);
+               if (lineParent >= 0) {
+                       if (line != lineParent)
+                               EnsureLineVisible(lineParent);
+                       if (!cs.GetExpanded(lineParent)) {
+                               cs.SetExpanded(lineParent, 1);
+                               Expand(lineParent, true);
+                       }
+               }
+               SetScrollBars();
+               Redraw();
+       }
+}
+
+LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+
+       // Optional macro recording hook
+#ifdef MACRO_SUPPORT
+       if (recordingMacro)
+               NotifyMacroRecord(iMessage, wParam, lParam);
+#endif
+
+       switch (iMessage) {
+
+       case WM_GETTEXT:
+               {
+                       if (lParam == 0)
+                               return 0;
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       unsigned int iChar = 0;
+                       for (; iChar < wParam-1; iChar++)
+                               ptr[iChar] = pdoc->CharAt(iChar);
+                       ptr[iChar] = '\0';
+                       return iChar;
+               }
+
+       case WM_SETTEXT:
+               {
+                       if (lParam == 0)
+                               return FALSE;
+                       pdoc->DeleteChars(0, pdoc->Length());
+                       SetEmptySelection(0);
+                       pdoc->InsertString(0, reinterpret_cast<char *>(lParam));
+                       return TRUE;
+               }
+
+       case WM_GETTEXTLENGTH:
+               return pdoc->Length();
+
+       case WM_NOTIFY:
+               //Platform::DebugPrintf("S notify %d %d\n", wParam, lParam);
+               break;
+
+       case WM_CUT:
+               Cut();
+               SetLastXChosen();
+               break;
+
+       case WM_COPY:
+               Copy();
+               break;
+
+       case WM_PASTE:
+               Paste();
+               SetLastXChosen();
+               break;
+
+       case WM_CLEAR:
+               Clear();
+               SetLastXChosen();
+               break;
+
+       case WM_UNDO:
+               Undo();
+               SetLastXChosen();
+               break;
+
+               // Edit control mesages
+
+               // Not supported (no-ops):
+               //              EM_GETWORDBREAKPROC
+               //              EM_GETWORDBREAKPROCEX
+               //              EM_SETWORDBREAKPROC
+               //              EM_SETWORDBREAKPROCEX
+               //              EM_GETWORDWRAPMODE
+               //              EM_SETWORDWRAPMODE
+               //              EM_LIMITTEXT
+               //              EM_EXLIMITTEXT
+               //              EM_SETRECT
+               //              EM_SETRECTNP
+               //              EM_FMTLINES
+               //              EM_GETHANDLE
+               //              EM_SETHANDLE
+               //              EM_GETPASSWORDCHAR
+               //              EM_SETPASSWORDCHAR
+               //              EM_SETTABSTOPS
+               //              EM_FINDWORDBREAK
+               //              EM_GETCHARFORMAT
+               //              EM_SETCHARFORMAT
+               //              EM_GETOLEINTERFACE
+               //              EM_SETOLEINTERFACE
+               //              EM_SETOLECALLBACK
+               //              EM_GETPARAFORMAT
+               //              EM_SETPARAFORMAT
+               //              EM_PASTESPECIAL
+               //              EM_REQUESTRESIZE
+               //              EM_GETBKGNDCOLOR
+               //              EM_SETBKGNDCOLOR
+               //              EM_STREAMIN
+               //              EM_STREAMOUT
+               //              EM_GETIMECOLOR
+               //              EM_SETIMECOLOR
+               //              EM_GETIMEOPTIONS
+               //              EM_SETIMEOPTIONS
+               //              EM_GETOPTIONS
+               //              EM_SETOPTIONS
+               //              EM_GETPUNCTUATION
+               //              EM_SETPUNCTUATION
+               //              EM_GETTHUMB
+
+               // Not supported but should be:
+               //              EM_GETEVENTMASK
+               //              EM_SETEVENTMASK
+               //              For printing:
+               //                      EM_DISPLAYBAND
+               //                      EM_SETTARGETDEVICE
+
+       case EM_CANUNDO:
+               return pdoc->CanUndo() ? TRUE : FALSE;
+
+       case EM_UNDO:
+               Undo();
+               break;
+
+       case EM_EMPTYUNDOBUFFER:
+               pdoc->DeleteUndoHistory();
+               return 0;
+
+       case EM_GETFIRSTVISIBLELINE:
+               return topLine;
+
+       case EM_GETLINE: {
+                       if (lParam == 0)
+                               return 0;
+                       int lineStart = pdoc->LineStart(wParam);
+                       int lineEnd = pdoc->LineStart(wParam + 1);
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       WORD *pBufSize = reinterpret_cast<WORD *>(lParam);
+                       if (*pBufSize < lineEnd - lineStart) {
+                               ptr[0] = '\0';  // If no characters copied have to put a NUL into buffer
+                               return 0;
+                       }
+                       int iPlace = 0;
+                       for (int iChar = lineStart; iChar < lineEnd; iChar++)
+                               ptr[iPlace++] = pdoc->CharAt(iChar);
+                       return iPlace;
+               }
+
+       case EM_GETLINECOUNT:
+               if (pdoc->LinesTotal() == 0)
+                       return 1;
+               else
+                       return pdoc->LinesTotal();
+
+       case EM_GETMODIFY:
+               return !pdoc->IsSavePoint();
+
+       case EM_SETMODIFY:
+               // Not really supported now that there is the save point stuff
+               //pdoc->isModified = wParam;
+               //return pdoc->isModified;
+               return false;
+
+       case EM_GETRECT:
+               if (lParam == 0)
+                       return 0;
+               *(reinterpret_cast<PRectangle *>(lParam)) = GetClientRectangle();
+               break;
+
+       case EM_GETSEL:
+               if (wParam)
+                       *reinterpret_cast<int *>(wParam) = SelectionStart();
+               if (lParam)
+                       *reinterpret_cast<int *>(lParam) = SelectionEnd();
+               return MAKELONG(SelectionStart(), SelectionEnd());
+
+       case EM_EXGETSEL: {
+                       if (lParam == 0)
+                               return 0;
+                       CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+                       pCR->cpMin = SelectionStart();
+                       pCR->cpMax = SelectionEnd();
+               }
+               break;
+
+       case EM_SETSEL: {
+                       int nStart = static_cast<int>(wParam);
+                       int nEnd = static_cast<int>(lParam);
+                       if (nEnd < 0)
+                               nEnd = pdoc->Length();
+                       if (nStart < 0)
+                               nStart = nEnd;  // Remove selection
+                       SetSelection(nEnd, nStart);
+                       EnsureCaretVisible();
+               }
+               break;
+
+       case EM_EXSETSEL: {
+                       if (lParam == 0)
+                               return 0;
+                       CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+                       if (pCR->cpMax == -1) {
+                               SetSelection(pCR->cpMin, pdoc->Length());
+                       } else {
+                               SetSelection(pCR->cpMin, pCR->cpMax);
+                       }
+                       EnsureCaretVisible();
+                       return pdoc->LineFromPosition(SelectionStart());
+               }
+
+       case EM_GETSELTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       int selSize = SelectionRangeLength();
+                       char *text = CopySelectionRange();
+                       int iChar = 0;
+                       if (text) {
+                               for (; iChar < selSize; iChar++)
+                                       ptr[iChar] = text[iChar];
+                               ptr[iChar] = '\0';
+                               delete []text;
+                       }
+                       return iChar;
+               }
+
+       case EM_GETWORDBREAKPROC:
+               return 0;
+
+       case EM_SETWORDBREAKPROC:
+               break;
+
+       case EM_LIMITTEXT:
+               // wParam holds the number of characters control should be limited to
+               break;
+
+       case EM_GETLIMITTEXT:
+               return 0xffffffff;
+
+       case EM_GETOLEINTERFACE:
+               return 0;
+
+       case EM_LINEFROMCHAR:
+               if (static_cast<int>(wParam) < 0)
+                       wParam = SelectionStart();
+               return pdoc->LineFromPosition(wParam);
+
+       case EM_EXLINEFROMCHAR:
+               if (static_cast<int>(lParam) < 0)
+                       lParam = SelectionStart();      // Not specified, but probably OK
+               return pdoc->LineFromPosition(lParam);
+
+       case EM_LINEINDEX:
+               if (static_cast<int>(wParam) < 0)
+                       wParam = pdoc->LineFromPosition(SelectionStart());
+               if (wParam == 0)
+                       return 0;       // Even if there is no text, there is a first line that starts at 0
+               if (static_cast<int>(wParam) > pdoc->LinesTotal())
+                       return - 1;
+               //if (wParam > pdoc->LineFromPosition(pdoc->Length()))  // Useful test, anyway...
+               //      return -1;
+               return pdoc->LineStart(wParam);
+
+       case EM_LINELENGTH:
+               {
+                       if (static_cast<int>(wParam) < 0)       // Who use this anyway?
+                               return 0;       // Should be... Too complex to describe here, see MS specs!
+                       if (static_cast<int>(wParam) > pdoc->Length())  // Useful test, anyway...
+                               return 0;
+                       int line = pdoc->LineFromPosition(wParam);
+                       int charsOnLine = 0;
+                       for (int pos = pdoc->LineStart(line); pos < pdoc->LineStart(line + 1); pos++) {
+                               if ((pdoc->CharAt(pos) != '\r') && (pdoc->CharAt(pos) != '\n'))
+                                       charsOnLine++;
+                       }
+                       return charsOnLine;
+               }
+
+               // Replacement of the old Scintilla interpretation of EM_LINELENGTH
+       case SCI_LINELENGTH:
+               if ((static_cast<int>(wParam) < 0) ||
+                       (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
+                       return 0;
+               return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
+
+       case EM_REPLACESEL: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->BeginUndoAction();
+                       ClearSelection();
+                       char *replacement = reinterpret_cast<char *>(lParam);
+                       pdoc->InsertString(currentPos, replacement);
+                       pdoc->EndUndoAction();
+                       SetEmptySelection(currentPos + strlen(replacement));
+                       EnsureCaretVisible();
+               }
+               break;
+
+       case EM_LINESCROLL:
+               ScrollTo(topLine + lParam);
+               HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
+               return TRUE;
+
+       case EM_SCROLLCARET:
+               EnsureCaretVisible();
+               break;
+
+       case EM_SETREADONLY:
+               pdoc->SetReadOnly(wParam);
+               return TRUE;
+
+       case EM_SETRECT:
+               break;
+
+       case EM_CANPASTE:
+               return 1;
+
+       case EM_CHARFROMPOS: {
+                       if (lParam == 0)
+                               return 0;
+                       Point *ppt = reinterpret_cast<Point *>(lParam);
+                       int pos = PositionFromLocation(*ppt);
+                       int line = pdoc->LineFromPosition(pos);
+                       return MAKELONG(pos, line);
+               }
+
+       case EM_POSFROMCHAR: {
+                       // The MS specs for this have changed 3 times: using the RichEdit 3 version
+                       if (wParam == 0)
+                               return 0;
+                       Point *ppt = reinterpret_cast<Point *>(wParam);
+                       if (lParam < 0) {
+                               *ppt = Point(0, 0);
+                       } else {
+                               *ppt = LocationFromPosition(lParam);
+                       }
+                       return 0;
+               }
+
+       case EM_FINDTEXT:
+               return FindText(iMessage, wParam, lParam);
+
+       case EM_FINDTEXTEX:
+               return FindText(iMessage, wParam, lParam);
+
+       case EM_GETTEXTRANGE: {
+                       if (lParam == 0)
+                               return 0;
+                       TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+                       int cpMax = tr->chrg.cpMax;
+                       if (cpMax == -1)
+                               cpMax = pdoc->Length();
+                       int len = cpMax - tr->chrg.cpMin;       // No -1 as cpMin and cpMax are referring to inter character positions
+                       pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+                       // Spec says copied text is terminated with a NUL
+                       tr->lpstrText[len] = '\0';
+                       return len;     // Not including NUL
+               }
+
+       case EM_SELECTIONTYPE:
+               if (currentPos == anchor)
+                       return SEL_EMPTY;
+               else
+                       return SEL_TEXT;
+
+       case EM_HIDESELECTION:
+               hideSelection = wParam;
+               Redraw();
+               break;
+
+       case EM_FORMATRANGE:
+               return FormatRange(wParam, reinterpret_cast<FORMATRANGE *>(lParam));
+
+       case EM_GETMARGINS:
+               return MAKELONG(vs.leftMarginWidth, vs.rightMarginWidth);
+               
+       case EM_SETMARGINS:
+               if (wParam & EC_LEFTMARGIN) {
+                       vs.leftMarginWidth = LOWORD(lParam);
+               }
+               if (wParam & EC_RIGHTMARGIN) {
+                       vs.rightMarginWidth = HIWORD(lParam);
+               }
+               if (wParam == EC_USEFONTINFO) {
+                       vs.leftMarginWidth = vs.aveCharWidth / 2;
+                       vs.rightMarginWidth = vs.aveCharWidth / 2;
+               }
+               InvalidateStyleRedraw();
+               break;
+       
+               // Control specific mesages
+
+       case SCI_ADDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->InsertString(CurrentPosition(), reinterpret_cast<char *>(lParam), wParam);
+                       SetEmptySelection(currentPos + wParam);
+                       return 0;
+               }
+
+       case SCI_ADDSTYLEDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->InsertStyledString(CurrentPosition() * 2, reinterpret_cast<char *>(lParam), wParam);
+                       SetEmptySelection(currentPos + wParam / 2);
+                       return 0;
+               }
+
+       case SCI_INSERTTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       int insertPos = wParam;
+                       if (static_cast<short>(wParam) == -1)
+                               insertPos = CurrentPosition();
+                       int newCurrent = CurrentPosition();
+                       int newAnchor = anchor;
+                       char *sz = reinterpret_cast<char *>(lParam);
+                       pdoc->InsertString(insertPos, sz);
+                       if (newCurrent > insertPos)
+                               newCurrent += strlen(sz);
+                       if (newAnchor > insertPos)
+                               newAnchor += strlen(sz);
+                       SetEmptySelection(newCurrent);
+                       return 0;
+               }
+
+       case SCI_CLEARALL:
+               ClearAll();
+               return 0;
+
+       case SCI_SETUNDOCOLLECTION:
+               pdoc->SetUndoCollection(static_cast<enum undoCollectionType>(wParam));
+               return 0;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_APPENDUNDOSTARTACTION:
+               pdoc->AppendUndoStartAction();
+               return 0;
+#endif
+
+       case SCI_BEGINUNDOACTION:
+               pdoc->BeginUndoAction();
+               return 0;
+
+       case SCI_ENDUNDOACTION:
+               pdoc->EndUndoAction();
+               return 0;
+
+       case SCI_GETCARETPERIOD:
+               return caret.period;
+
+       case SCI_SETCARETPERIOD:
+               caret.period = wParam;
+               break;
+
+       case SCI_SETWORDCHARS: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->SetWordChars(reinterpret_cast<unsigned char *>(lParam));
+               }
+               break;
+
+       case SCI_GETLENGTH:
+               return pdoc->Length();
+
+       case SCI_GETCHARAT:
+               return pdoc->CharAt(wParam);
+
+       case SCI_GETCURRENTPOS:
+               return currentPos;
+
+       case SCI_GETANCHOR:
+               return anchor;
+
+       case SCI_GETSTYLEAT:
+               if (static_cast<short>(wParam) >= pdoc->Length())
+                       return 0;
+               else
+                       return pdoc->StyleAt(wParam);
+
+       case SCI_REDO:
+               Redo();
+               break;
+
+       case SCI_SELECTALL:
+               SelectAll();
+               break;
+
+       case SCI_SETSAVEPOINT:
+               pdoc->SetSavePoint();
+               NotifySavePoint(true);
+               break;
+
+       case SCI_GETSTYLEDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+                       int iPlace = 0;
+                       for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
+                               tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
+                               tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
+                       }
+                       tr->lpstrText[iPlace] = '\0';
+                       tr->lpstrText[iPlace + 1] = '\0';
+                       return iPlace;
+               }
+
+       case SCI_CANREDO:
+               return pdoc->CanRedo() ? TRUE : FALSE;
+
+       case SCI_MARKERLINEFROMHANDLE:
+               return pdoc->LineFromHandle(wParam);
+
+       case SCI_MARKERDELETEHANDLE:
+               pdoc->DeleteMarkFromHandle(wParam);
+               break;
+
+       case SCI_GETVIEWWS:
+               return vs.viewWhitespace;
+
+       case SCI_SETVIEWWS:
+               vs.viewWhitespace = wParam;
+               Redraw();
+               break;
+
+       case SCI_GOTOLINE:
+               GoToLine(wParam);
+               break;
+
+       case SCI_GOTOPOS:
+               SetEmptySelection(wParam);
+               EnsureCaretVisible();
+               Redraw();
+               break;
+
+       case SCI_SETANCHOR:
+               SetSelection(currentPos, wParam);
+               break;
+
+       case SCI_GETCURLINE: {
+                       if (lParam == 0)
+                               return 0;
+                       int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+                       int lineStart = pdoc->LineStart(lineCurrentPos);
+                       unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       unsigned int iPlace = 0;
+                       for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam; iChar++)
+                               ptr[iPlace++] = pdoc->CharAt(iChar);
+                       ptr[iPlace] = '\0';
+                       return currentPos - lineStart;
+               }
+
+       case SCI_GETENDSTYLED:
+               return pdoc->GetEndStyled();
+
+       case SCI_GETEOLMODE:
+               return pdoc->eolMode;
+
+       case SCI_SETEOLMODE:
+               pdoc->eolMode = wParam;
+               break;
+
+       case SCI_STARTSTYLING:
+               pdoc->StartStyling(wParam, lParam);
+               break;
+
+       case SCI_SETSTYLING:
+               pdoc->SetStyleFor(wParam, lParam);
+               break;
+
+       case SCI_SETSTYLINGEX:   // Specify a complete styling buffer
+               if (lParam == 0)
+                       return 0;
+               pdoc->SetStyles(wParam, reinterpret_cast<char *>(lParam));
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETMARGINWIDTH:
+               if (wParam < 100) {
+                       vs.ms[1].width = wParam;
+               }
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETBUFFEREDDRAW:
+               bufferedDraw = wParam;
+               break;
+
+       case SCI_SETTABWIDTH:
+               if (wParam > 0)
+                       pdoc->tabInChars = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETCODEPAGE:
+               pdoc->dbcsCodePage = wParam;
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETLINENUMBERWIDTH:
+               if (wParam < 200) {
+                       vs.ms[0].width = wParam;
+               }
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETUSEPALETTE:
+               palette.allowRealization = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+               // Marker definition and setting
+       case SCI_MARKERDEFINE:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].markType = lParam;
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERSETFORE:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].fore.desired = Colour(lParam);
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERSETBACK:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].back.desired = Colour(lParam);
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERADD: {
+                       int markerID = pdoc->AddMark(wParam, lParam);
+                       RedrawSelMargin();
+                       return markerID;
+               }
+
+       case SCI_MARKERDELETE:
+               pdoc->DeleteMark(wParam, lParam);
+               RedrawSelMargin();
+               break;
+
+       case SCI_MARKERDELETEALL:
+               pdoc->DeleteAllMarks(static_cast<int>(wParam));
+               RedrawSelMargin();
+               break;
+
+       case SCI_MARKERGET:
+               return pdoc->GetMark(wParam);
+
+       case SCI_MARKERNEXT: {
+                       int lt = pdoc->LinesTotal();
+                       for (int iLine = wParam; iLine < lt; iLine++) {
+                               if ((pdoc->GetMark(iLine) & lParam) != 0)
+                                       return iLine;
+                       }
+               }
+               return -1;
+
+       case SCI_MARKERPREVIOUS: {
+                       for (int iLine = wParam; iLine >= 0; iLine--) {
+                               if ((pdoc->GetMark(iLine) & lParam) != 0)
+                                       return iLine;
+                       }
+               }
+               return -1;
+
+       case SCI_SETMARGINTYPEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].symbol = (lParam == SC_MARGIN_SYMBOL);
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINTYPEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].symbol ? SC_MARGIN_SYMBOL : SC_MARGIN_NUMBER;
+               else
+                       return 0;
+                       
+       case SCI_SETMARGINWIDTHN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].width = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINWIDTHN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].width;
+               else
+                       return 0;
+                       
+       case SCI_SETMARGINMASKN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].mask = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINMASKN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].mask;
+               else
+                       return 0;
+               
+       case SCI_SETMARGINSENSITIVEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].sensitive = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINSENSITIVEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].sensitive ? 1 : 0;
+               else
+                       return 0;
+
+       case SCI_STYLECLEARALL:
+               vs.ClearStyles();
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_STYLESETFORE:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].fore.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETBACK:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].back.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETBOLD:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].bold = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETITALIC:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].italic = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETEOLFILLED:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].eolFilled = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETSIZE:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].size = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETFONT:
+               if (lParam == 0)
+                       return 0;
+               if (wParam <= STYLE_MAX) {
+                       strcpy(vs.styles[wParam].fontName, reinterpret_cast<char *>(lParam));
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_STYLERESETDEFAULT:
+               vs.ResetDefaultStyle();
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSTYLEBITS:
+               pdoc->SetStylingBits(wParam);
+               break;
+               
+       case SCI_GETSTYLEBITS:
+               return pdoc->stylingBits;
+               
+       case SCI_SETLINESTATE:
+               return pdoc->SetLineState(wParam, lParam);
+               
+       case SCI_GETLINESTATE:
+               return pdoc->GetLineState(wParam);
+               
+       case SCI_GETMAXLINESTATE:
+               return pdoc->GetMaxLineState();
+               
+       // Folding messages
+               
+       case SCI_VISIBLEFROMDOCLINE:
+               return cs.DisplayFromDoc(wParam);
+               
+       case SCI_DOCLINEFROMVISIBLE:
+               return cs.DocFromDisplay(wParam);
+
+       case SCI_SETFOLDLEVEL: {
+                       int prev = pdoc->SetLevel(wParam, lParam);
+                       if (prev != lParam)
+                               RedrawSelMargin();
+                       return prev;
+               }
+               
+       case SCI_GETFOLDLEVEL:
+               return pdoc->GetLevel(wParam);
+               
+       case SCI_GETLASTCHILD:
+               return pdoc->GetLastChild(wParam, lParam);
+               
+       case SCI_GETFOLDPARENT:
+               return pdoc->GetFoldParent(wParam);
+               
+       case SCI_SHOWLINES:
+               cs.SetVisible(wParam, lParam, true);
+               SetScrollBars();
+               Redraw();
+               break;
+               
+       case SCI_HIDELINES:
+               cs.SetVisible(wParam, lParam, false);
+               SetScrollBars();
+               Redraw();
+               break;
+               
+       case SCI_GETLINEVISIBLE:
+               return cs.GetVisible(wParam);
+               
+       case SCI_SETFOLDEXPANDED:
+               if (cs.SetExpanded(wParam, lParam)) {
+                       RedrawSelMargin();
+               }
+               break;
+       
+       case SCI_GETFOLDEXPANDED:
+               return cs.GetExpanded(wParam);
+               
+       case SCI_SETFOLDFLAGS:
+               foldFlags = wParam;
+               Redraw();
+               break;
+
+       case SCI_TOGGLEFOLD:
+               ToggleContraction(wParam);
+               break;
+               
+       case SCI_ENSUREVISIBLE:
+               EnsureLineVisible(wParam);
+               break;
+               
+       case SCI_SEARCHANCHOR:
+               SearchAnchor();
+               break;
+
+       case SCI_SEARCHNEXT:
+       case SCI_SEARCHPREV:
+               return SearchText(iMessage, wParam, lParam);
+               break;
+
+       case SCI_SETCARETPOLICY:
+               caretPolicy = wParam;
+               caretSlop = lParam;
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETFORE:
+               vs.styles[STYLE_DEFAULT].fore.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETBACK:
+               vs.styles[STYLE_DEFAULT].back.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETBOLD:
+               vs.styles[STYLE_DEFAULT].bold = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETITALIC:
+               vs.styles[STYLE_DEFAULT].italic = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSIZE:
+               vs.styles[STYLE_DEFAULT].size = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETFONT:
+               if (wParam == 0)
+                       return 0;
+               strcpy(vs.styles[STYLE_DEFAULT].fontName, reinterpret_cast<char *>(wParam));
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETSELFORE:
+               vs.selforeset = wParam;
+               vs.selforeground.desired = Colour(lParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSELBACK:
+               vs.selbackset = wParam;
+               vs.selbackground.desired = Colour(lParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETCARETFORE:
+               vs.caretcolour.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_ASSIGNCMDKEY:
+               kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), lParam);
+               break;
+
+       case SCI_CLEARCMDKEY:
+               kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), WM_NULL);
+               break;
+
+       case SCI_CLEARALLCMDKEYS:
+               kmap.Clear();
+               break;
+
+       case SCI_INDICSETSTYLE:
+               if (wParam <= INDIC_MAX) {
+                       vs.indicators[wParam].style = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+
+       case SCI_INDICGETSTYLE:
+               return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
+
+       case SCI_INDICSETFORE:
+               if (wParam <= INDIC_MAX) {
+                       vs.indicators[wParam].fore.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+
+       case SCI_INDICGETFORE:
+               return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.desired.AsLong() : 0;
+
+       case SCI_LINEDOWN:
+       case SCI_LINEDOWNEXTEND:
+       case SCI_LINEUP:
+       case SCI_LINEUPEXTEND:
+       case SCI_CHARLEFT:
+       case SCI_CHARLEFTEXTEND:
+       case SCI_CHARRIGHT:
+       case SCI_CHARRIGHTEXTEND:
+       case SCI_WORDLEFT:
+       case SCI_WORDLEFTEXTEND:
+       case SCI_WORDRIGHT:
+       case SCI_WORDRIGHTEXTEND:
+       case SCI_HOME:
+       case SCI_HOMEEXTEND:
+       case SCI_LINEEND:
+       case SCI_LINEENDEXTEND:
+       case SCI_DOCUMENTSTART:
+       case SCI_DOCUMENTSTARTEXTEND:
+       case SCI_DOCUMENTEND:
+       case SCI_DOCUMENTENDEXTEND:
+       case SCI_PAGEUP:
+       case SCI_PAGEUPEXTEND:
+       case SCI_PAGEDOWN:
+       case SCI_PAGEDOWNEXTEND:
+       case SCI_EDITTOGGLEOVERTYPE:
+       case SCI_CANCEL:
+       case SCI_DELETEBACK:
+       case SCI_TAB:
+       case SCI_BACKTAB:
+       case SCI_NEWLINE:
+       case SCI_FORMFEED:
+       case SCI_VCHOME:
+       case SCI_VCHOMEEXTEND:
+       case SCI_ZOOMIN:
+       case SCI_ZOOMOUT:
+       case SCI_DELWORDLEFT:
+       case SCI_DELWORDRIGHT:
+               return KeyCommand(iMessage);
+
+       case SCI_BRACEHIGHLIGHT:
+               SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
+               break;
+               
+       case SCI_BRACEBADLIGHT:
+               SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
+               break;
+
+       case SCI_BRACEMATCH:
+               // wParam is position of char to find brace for,
+               // lParam is maximum amount of text to restyle to find it
+               return BraceMatch(wParam, lParam);
+
+       case SCI_GETVIEWEOL:
+               return vs.viewEOL;
+
+       case SCI_SETVIEWEOL:
+               vs.viewEOL = wParam;
+               Redraw();
+               break;
+
+       case SCI_GETEDGECOLUMN:
+               return theEdge;
+               
+       case SCI_SETEDGECOLUMN:
+               theEdge = wParam;
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETEDGEMODE:
+               return edgeState;
+               
+       case SCI_SETEDGEMODE:
+               edgeState = wParam;
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETEDGECOLOUR:
+               return vs.edgecolour.desired.AsLong();
+               
+       case SCI_SETEDGECOLOUR:
+               vs.edgecolour.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETDOCPOINTER:
+               return reinterpret_cast<LRESULT>(pdoc);
+
+       case SCI_SETDOCPOINTER:
+               SetDocPointer(reinterpret_cast<Document *>(lParam));
+               return 0;
+
+       case SCI_SETMODEVENTMASK:
+               modEventMask = wParam;
+               return 0;
+               
+       case SCI_CONVERTEOLS:
+               pdoc->ConvertLineEnds(wParam);
+               SetSelection(currentPos, anchor);       // Ensure selection inside document
+               return 0;
+
+#ifdef MACRO_SUPPORT
+       case SCI_STARTRECORD:
+               recordingMacro = 1;
+               return 0;
+
+       case SCI_STOPRECORD:
+               recordingMacro = 0;
+               return 0;
+#endif
+               
+       default:
+               return DefWndProc(iMessage, wParam, lParam);
+       }
+       //Platform::DebugPrintf("end wnd proc\n");
+       return 0l;
+}
diff --git a/contrib/src/stc/scintilla/src/Editor.h b/contrib/src/stc/scintilla/src/Editor.h
new file mode 100644 (file)
index 0000000..4ff3347
--- /dev/null
@@ -0,0 +1,281 @@
+// Scintilla source code edit control
+// Editor.h - defines the main editor class
+// Copyright 1998-2000 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
+
+class Caret {
+public:
+       bool active;
+       bool on;
+       int period;
+               
+       Caret();
+};
+
+class Timer {
+
+public:
+       bool ticking;
+       int ticksToWait;
+       enum {tickSize = 100};
+       int tickerID;
+               
+       Timer();
+};
+
+class LineLayout {
+public:
+       // Drawing is only performed for maxLineLength characters on each line.
+       enum {maxLineLength = 4000};
+       int numCharsInLine;
+       char chars[maxLineLength];
+       char styles[maxLineLength];
+       char indicators[maxLineLength];
+       int positions[maxLineLength];
+};
+
+class Editor : public DocWatcher {
+protected:     // ScintillaBase subclass needs access to much of Editor
+
+       // On GTK+, Scintilla is a container widget holding two scroll bars and a drawing area
+       // whereas on Windows there is just one window with both scroll bars turned on.
+       // Therefore, on GTK+ the following are separate windows but only one window on Windows.
+       Window wMain;   // The Scintilla parent window
+       Window wDraw;   // The text drawing area
+
+       // 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;
+       
+       bool hideSelection;
+       bool inOverstrike;
+
+       // 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;
+
+       int xOffset;                            // Horizontal scrolled amount in pixels
+       int xCaretMargin;       // Ensure this many pixels visible on both sides of caret
+       
+       Surface pixmapLine;
+       Surface pixmapSelMargin;
+       Surface pixmapSelPattern;
+       // Intellimouse support - currently only implemented for Windows
+       unsigned int ucWheelScrollLines;
+       short cWheelDelta; //wheel delta from roll
+
+       KeyMap kmap;
+
+       Caret caret;
+       Timer timer;
+
+       Point lastClick;
+       unsigned int lastClickTime;
+       enum { selChar, selWord, selLine } selectionType;
+       Point ptMouseLast;
+       bool firstExpose;
+       bool inDragDrop;
+       bool dropWentOutside;
+       int posDrag;
+       int posDrop;
+       int lastXChosen;
+       int lineAnchor;
+       int originalAnchorPos;
+       int currentPos;
+       int anchor;
+       int topLine;
+       int posTopLine;
+       
+       bool needUpdateUI;
+       Position braces[2];
+       int bracesMatchStyle;
+       
+       int edgeState;
+       int theEdge;
+
+       enum { notPainting, painting, paintAbandoned } paintState;
+       PRectangle rcPaint;
+       bool paintingAllText;
+       
+       int modEventMask;
+       
+       char *dragChars;
+       int lenDrag;
+       bool dragIsRectangle;
+       enum { selStream, selRectangle, selRectangleFixed } selType;
+       int xStartSelect;
+       int xEndSelect;
+       
+       int caretPolicy;
+       int caretSlop;
+
+       int searchAnchor;
+
+#ifdef MACRO_SUPPORT
+       int recordingMacro;
+#endif
+
+       int foldFlags;
+       ContractionState cs;
+
+       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();
+
+       PRectangle GetClientRectangle();
+       PRectangle GetTextRectangle();
+       
+       int LinesOnScreen();
+       int LinesToScroll();
+       int MaxScrollPos();
+       Point LocationFromPosition(unsigned int pos);
+       int XFromPosition(unsigned int pos);
+       int PositionFromLocation(Point pt);
+       int PositionFromLineX(int line, int x);
+       int LineFromLocation(Point pt);
+       void SetTopLine(int topLineNew);
+       
+       void RedrawRect(PRectangle rc);
+       void Redraw();
+       void RedrawSelMargin();
+       PRectangle RectangleFromRange(int start, int end);
+       void InvalidateRange(int start, int end);
+       
+       int CurrentPosition();
+       bool SelectionEmpty();
+       int SelectionStart(int line=-1);
+       int SelectionEnd(int line=-1);
+       void SetSelection(int currentPos_, int anchor_);
+       void SetSelection(int currentPos_);
+       void SetEmptySelection(int currentPos_);
+       int MovePositionTo(int newPos, bool extend = false);
+       int MovePositionSoVisible(int pos, int moveDir);
+       void SetLastXChosen();
+
+       void ScrollTo(int line);
+       virtual void ScrollText(int linesToMove);
+       void HorizontalScrollTo(int xPos);
+       void EnsureCaretVisible(bool useMargin=true);
+       void ShowCaretAtCurrentPosition();
+       void DropCaret();
+       void InvalidateCaret();
+
+       void PaintSelMargin(Surface *surface, PRectangle &rc);
+        void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll);
+       void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, 
+               PRectangle rcLine, LineLayout &ll);
+       void Paint(Surface *surfaceWindow, PRectangle rcArea);
+       long FormatRange(bool draw, FORMATRANGE *pfr);
+
+       virtual void SetVerticalScrollPos() = 0;
+       virtual void SetHorizontalScrollPos() = 0;
+       virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
+       void SetScrollBarsTo(PRectangle rsClient);
+       void SetScrollBars();
+
+       virtual void AddChar(char ch);
+       void ClearSelection();
+       void ClearAll();
+       void Cut();
+       void PasteRectangular(int pos, const char *ptr, int len);
+       virtual void Copy() = 0;
+       virtual void Paste() = 0;
+       void Clear();
+       void SelectAll();
+       void Undo();
+       void Redo();
+       void DelChar();
+       void DelCharBack();
+       virtual void ClaimSelection() = 0;
+
+       virtual void NotifyChange() = 0;
+       virtual void NotifyFocus(bool focus);
+       virtual void NotifyParent(SCNotification scn) = 0;
+       virtual void NotifyStyleNeeded(int endStyleNeeded);
+       void NotifyChar(char ch);
+       void NotifySavePoint(bool isSavePoint);
+       void NotifyModifyAttempt();
+       virtual void NotifyDoubleClick(Point pt, bool shift);
+       void NotifyUpdateUI();
+       bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
+       void NotifyNeedShown(int pos, int len);
+       
+       void NotifyModifyAttempt(Document *document, void *userData);
+       void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
+       void NotifyModified(Document *document, DocModification mh, void *userData);
+       void NotifyDeleted(Document *document, void *userData);
+       
+#ifdef MACRO_SUPPORT
+       void NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam);
+#endif
+
+       void PageMove(int direction, bool extend=false);
+       virtual int KeyCommand(UINT iMessage);
+       virtual int KeyDefault(int /* key */, int /*modifiers*/);
+       int KeyDown(int key, bool shift, bool ctrl, bool alt);
+
+       bool GetWhitespaceVisible();
+       void SetWhitespaceVisible(bool view);
+
+       void Indent(bool forwards);
+
+       long FindText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+       void SearchAnchor();
+       long SearchText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+       void GoToLine(int lineNo);
+
+       char *CopyRange(int start, int end);
+       int SelectionRangeLength();
+       char *CopySelectionRange();
+       void CopySelectionIntoDrag();
+       void SetDragPosition(int newPos);
+       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);
+       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();
+       virtual void SetTicking(bool on) = 0;
+       virtual void SetMouseCapture(bool on) = 0;
+       virtual bool HaveMouseCapture() = 0;
+
+       void CheckForChangeOutsidePaint(Range r);
+       int BraceMatch(int position, int maxReStyle);
+       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 line);
+
+       virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) = 0;
+       
+public:
+       // Public so scintilla_send_message can use it
+       virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+       // Public so scintilla_set_id can use it
+       int ctrlID;     
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/Indicator.cxx b/contrib/src/stc/scintilla/src/Indicator.cxx
new file mode 100644 (file)
index 0000000..fb6ad09
--- /dev/null
@@ -0,0 +1,45 @@
+// Scintilla source code edit control
+// Indicator.cxx - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 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"
+
+void Indicator::Draw(Surface *surface, PRectangle &rc) {
+       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 {        // Either INDIC_PLAIN or unknown
+               surface->MoveTo(rc.left, ymid);
+               surface->LineTo(rc.right, ymid);
+       }
+}
+
diff --git a/contrib/src/stc/scintilla/src/Indicator.h b/contrib/src/stc/scintilla/src/Indicator.h
new file mode 100644 (file)
index 0000000..2472ced
--- /dev/null
@@ -0,0 +1,18 @@
+// Scintilla source code edit control
+// Indicator.h - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef INDICATOR_H
+#define INDICATOR_H
+
+class Indicator {
+public:
+       int style;
+       ColourPair fore;
+       Indicator() : style(INDIC_PLAIN), fore(Colour(0,0,0)) {
+       }
+       void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/KeyMap.cxx b/contrib/src/stc/scintilla/src/KeyMap.cxx
new file mode 100644 (file)
index 0000000..f339cd2
--- /dev/null
@@ -0,0 +1,111 @@
+// Scintilla source code edit control
+// KeyMap.cxx  - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 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"
+
+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, UINT 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++;
+}
+
+UINT 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;
+}
+
+KeyToCommand KeyMap::MapDefault[] = {
+    VK_DOWN,   SCI_NORM,       SCI_LINEDOWN,
+    VK_DOWN,   SCI_SHIFT,      SCI_LINEDOWNEXTEND,
+    VK_UP,             SCI_NORM,       SCI_LINEUP,
+    VK_UP,             SCI_SHIFT,      SCI_LINEUPEXTEND,
+    VK_LEFT,           SCI_NORM,       SCI_CHARLEFT,
+    VK_LEFT,           SCI_SHIFT,      SCI_CHARLEFTEXTEND,
+    VK_LEFT,           SCI_CTRL,       SCI_WORDLEFT,
+    VK_LEFT,           SCI_CSHIFT,     SCI_WORDLEFTEXTEND,
+    VK_RIGHT,  SCI_NORM,       SCI_CHARRIGHT,
+    VK_RIGHT,  SCI_SHIFT,      SCI_CHARRIGHTEXTEND,
+    VK_RIGHT,  SCI_CTRL,       SCI_WORDRIGHT,
+    VK_RIGHT,  SCI_CSHIFT,     SCI_WORDRIGHTEXTEND,
+    VK_HOME,   SCI_NORM,       SCI_VCHOME,
+    VK_HOME,   SCI_SHIFT,      SCI_VCHOMEEXTEND,
+    VK_HOME,   SCI_CTRL,       SCI_DOCUMENTSTART,
+    VK_HOME,   SCI_CSHIFT,     SCI_DOCUMENTSTARTEXTEND,
+    VK_END,            SCI_NORM,       SCI_LINEEND,
+    VK_END,            SCI_SHIFT,      SCI_LINEENDEXTEND,
+    VK_END,            SCI_CTRL,       SCI_DOCUMENTEND,
+    VK_END,            SCI_CSHIFT,     SCI_DOCUMENTENDEXTEND,
+    VK_PRIOR,  SCI_NORM,       SCI_PAGEUP,
+    VK_PRIOR,  SCI_SHIFT,      SCI_PAGEUPEXTEND,
+    VK_NEXT,   SCI_NORM,       SCI_PAGEDOWN,
+    VK_NEXT,   SCI_SHIFT,      SCI_PAGEDOWNEXTEND,
+    VK_DELETE,         SCI_NORM,       WM_CLEAR,
+    VK_DELETE,         SCI_SHIFT,      WM_CUT,
+    VK_DELETE,         SCI_CTRL,       SCI_DELWORDRIGHT,
+    VK_INSERT,         SCI_NORM,       SCI_EDITTOGGLEOVERTYPE,
+    VK_INSERT,         SCI_SHIFT,      WM_PASTE,
+    VK_INSERT,         SCI_CTRL,       WM_COPY,
+    VK_ESCAPE,         SCI_NORM,       SCI_CANCEL,
+    VK_BACK,           SCI_NORM,       SCI_DELETEBACK,
+    VK_BACK,           SCI_CTRL,       SCI_DELWORDLEFT,
+    'Z',                       SCI_CTRL,       WM_UNDO,
+    'Y',                       SCI_CTRL,       SCI_REDO,
+    'X',                       SCI_CTRL,       WM_CUT,
+    'C',                       SCI_CTRL,       WM_COPY,
+    'V',                       SCI_CTRL,       WM_PASTE,
+    'A',                       SCI_CTRL,       SCI_SELECTALL,
+    VK_TAB,            SCI_NORM,       SCI_TAB,
+    VK_TAB,            SCI_SHIFT,      SCI_BACKTAB,
+    VK_RETURN,         SCI_NORM,       SCI_NEWLINE,
+    'L',                       SCI_CTRL,       SCI_FORMFEED,
+    VK_ADD,            SCI_CTRL,       SCI_ZOOMIN,
+    VK_SUBTRACT,       SCI_CTRL,       SCI_ZOOMOUT,
+    0,0,0,
+};
+
diff --git a/contrib/src/stc/scintilla/src/KeyMap.h b/contrib/src/stc/scintilla/src/KeyMap.h
new file mode 100644 (file)
index 0000000..814f3aa
--- /dev/null
@@ -0,0 +1,35 @@
+// Scintilla source code edit control
+// KeyMap.h - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 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
+
+#define SCI_NORM 0
+#define SCI_SHIFT SHIFT_PRESSED
+#define SCI_CTRL LEFT_CTRL_PRESSED
+#define SCI_ALT LEFT_ALT_PRESSED
+#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
+
+class KeyToCommand {
+public:
+       int key;
+       int modifiers;
+       UINT msg;
+};
+
+class KeyMap {
+       KeyToCommand *kmap;
+       int len;
+       int alloc;
+       static KeyToCommand MapDefault[];
+public:
+       KeyMap();
+       ~KeyMap();
+       void Clear();
+       void AssignCmdKey(int key, int modifiers, UINT msg);
+       UINT Find(int key, int modifiers);      // 0 returned on failure
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/KeyWords.cxx b/contrib/src/stc/scintilla/src/KeyWords.cxx
new file mode 100644 (file)
index 0000000..20f6762
--- /dev/null
@@ -0,0 +1,2217 @@
+// SciTE - Scintilla based Text Editor
+// KeyWords.cxx - colourise for particular languages
+// Copyright 1998-2000 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"
+
+inline bool IsLeadByte(int codePage, char ch) {
+#if PLAT_GTK
+       // TODO: support DBCS under GTK+
+       return false;
+#elif PLAT_WIN 
+       return codePage && IsDBCSLeadByteEx(codePage, ch);
+#elif PLAT_WX 
+       return false;
+#endif 
+}
+
+inline bool iswordchar(char ch) {
+       return isalnum(ch) || ch == '.' || ch == '_';
+}
+
+inline bool iswordstart(char ch) {
+       return isalnum(ch) || ch == '_';
+}
+
+enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
+
+static int IndentAmount(StylingContext &styler, int line, int *flags) {
+       int end = styler.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 = styler.LineStart(line);
+       char ch = styler[pos];
+       int indent = 0;
+       bool inPrevPrefix = line > 0;
+       int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
+       while ((ch == ' ' || ch == '\t') && (pos < end)) {
+               if (inPrevPrefix) {
+                       char chPrev = styler[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 = styler[++pos];
+       }
+       
+       *flags = spaceFlags;
+       indent += SC_FOLDLEVELBASE;
+       if (isspace(ch)) // Completely empty line
+               return indent | SC_FOLDLEVELWHITEFLAG;
+       else
+               return indent;
+}
+
+inline bool isoperator(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 == '>' || ch == ',' || ch == '/' ||
+               ch == '?' || ch == '!' || ch == '.' || ch == '~')
+               return true;
+       return false;
+}
+
+static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_C_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseCppDoc(int codePage, int startPos, int length,
+                            int initStyle, WordList &keywords, StylingContext &styler) {
+
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+
+       int state = initStyle;
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       int visChars = 0;
+       for (unsigned int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((fold) && ((ch == '\r' && chNext != '\n') || (ch == '\n'))) {
+                       int lev = levelPrev;
+                       if (visChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       styler.SetLevel(lineCurrent, lev);
+                       lineCurrent++;
+                       visChars = 0;
+                       levelPrev = levelCurrent;
+               }
+               if (!isspace(ch))
+                       visChars++;
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_STRINGEOL) {
+                       if (ch != '\r' && ch != '\n') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                       }
+               }
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (styler.SafeGetCharAt(i + 2) == '*')
+                                       state = SCE_C_COMMENTDOC;
+                               else
+                                       state = SCE_C_COMMENT;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '/') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_CHARACTER;
+                               startSeg = i;
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_PREPROCESSOR;
+                               startSeg = i;
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_C_OPERATOR);
+                               startSeg = i + 1;
+                               if ((ch == '{') || (ch == '}')) {
+                                       levelCurrent += (ch == '{') ? 1 : -1;
+                               }
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordCpp(startSeg, i - 1, keywords, styler);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                               if (ch == '/' && chNext == '*') {
+                                       if (styler.SafeGetCharAt(i + 2) == '*')
+                                               state = SCE_C_COMMENTDOC;
+                                       else
+                                               state = SCE_C_COMMENT;
+                               } else if (ch == '/' && chNext == '/') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_CHARACTER;
+                               } else if (ch == '#') {
+                                       state = SCE_C_PREPROCESSOR;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                                       if ((ch == '{') || (ch == '}')) {
+                                               levelCurrent += (ch == '{') ? 1 : -1;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_PREPROCESSOR) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_COMMENT) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTDOC) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 3) || ((initStyle == SCE_C_COMMENTDOC) && (startSeg == startPos)))) {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_STRINGEOL;
+                                       startSeg = i;
+                               } else if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_CHARACTER) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_STRINGEOL;
+                                       startSeg = i;
+                               } else if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '/' && chNext == '*') {
+                                       if (styler.SafeGetCharAt(i + 2) == '*')
+                                               state = SCE_C_COMMENTDOC;
+                                       else
+                                               state = SCE_C_COMMENT;
+                               } else if (ch == '/' && chNext == '/') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_CHARACTER;
+                               } else if (ch == '#') {
+                                       state = SCE_C_PREPROCESSOR;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                                       if ((ch == '{') || (ch == '}')) {
+                                               levelCurrent += (ch == '{') ? 1 : -1;
+                                       }
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, 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);
+               
+       }
+}
+
+inline bool isPerlOperator(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 == '<' || ch == '>' || ch == ',' || ch == '/' ||
+               ch == '?' || ch == '!' || ch == '.' || ch == '~')
+               return true;
+       return false;
+}
+
+static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_PL_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_PL_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_PL_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+       return chAttr;
+}
+
+static bool isEndVar(char ch) {
+       return !isalnum(ch) && ch != '#' && ch != '$' &&
+              ch != '_' && ch != '\'';
+}
+
+static bool isMatch(StylingContext &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;
+}
+
+static bool isOKQuote(char ch) {
+       if (isalnum(ch))
+               return false;
+       if (isspace(ch))
+               return false;
+       if (iscntrl(ch))
+               return false;
+       return true;
+}
+
+static char opposite(char ch) {
+       if (ch == '(')
+               return ')';
+       if (ch == '[')
+               return ']';
+       if (ch == '{')
+               return '}';
+       if (ch == '<')
+               return '>';
+       return ch;
+}
+
+static void ColourisePerlDoc(int codePage, int startPos, int length, int initStyle,
+                             WordList &keywords, StylingContext &styler) {
+       char sooked[100];
+       int quotes = 0;
+       char quoteDown = 'd';
+       char quoteUp = 'd';
+       int quoteRep = 1;
+       int sookedpos = 0;
+       bool preferRE = true;
+       sooked[sookedpos] = '\0';
+       int state = initStyle;
+       int lengthDoc = startPos + length;
+       // If in a long distance lexical state, seek to the beginning  to find quote characters
+       if (state == SCE_PL_HERE || state == SCE_PL_REGEX || 
+               state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) {
+               while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
+                       startPos--;
+               }
+               state = SCE_PL_DEFAULT;
+       }
+       styler.StartAt(startPos);
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               char chNext2 = styler.SafeGetCharAt(i + 2);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_PL_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (ch == 's' && !isalnum(chNext)) {
+                                       state = SCE_PL_REGSUBST;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 2;
+                                       startSeg = i;
+                               } else if (ch == 'm' && !isalnum(chNext)) {
+                                       state = SCE_PL_REGEX;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 1;
+                                       startSeg = i;
+                               } else if (ch == 't' && chNext == 'r' && !isalnum(chNext2)) {
+                                       state = SCE_PL_REGSUBST;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 2;
+                                       startSeg = i;
+                                       i++;
+                                       chNext = chNext2;
+                               } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isalnum(chNext2)) {
+                                       state = SCE_PL_LONGQUOTE;
+                                       startSeg = i;
+                                       i++;
+                                       chNext = chNext2;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 1;
+                               } else {
+                                       state = SCE_PL_WORD;
+                                       startSeg = i;
+                                       preferRE = false;
+                               }
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_STRING;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               if (chPrev == '&') {
+                                       // Archaic call
+                                       styler.ColourSegment(i, i, state);
+                                       startSeg = i + 1;
+                               } else {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_PL_CHARACTER;
+                                       startSeg = i;
+                               }
+                       } else if (ch == '`') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_BACKTICKS;
+                               startSeg = i;
+                       } else if (ch == '$') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalnum(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_SCALAR;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_SCALAR);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                                       chNext = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_SCALAR);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '@') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_ARRAY;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_ARRAY);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_ARRAY);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '%') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_HASH;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_HASH);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_HASH);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_SYMBOLTABLE;
+                               startSeg = i;
+                       } else if (ch == '/' && preferRE) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_REGEX;
+                               quoteUp = '/';
+                               quoteDown = '/';
+                               quotes = 1;
+                               quoteRep = 1;
+                               startSeg = i;
+                       } else if (ch == '<' && chNext == '<') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_HERE;
+                               startSeg = i;
+                               i++;
+                               ch = chNext;
+                               chNext = chNext2;
+                               quotes = 0;
+                               sookedpos = 0;
+                               sooked[sookedpos] = '\0';
+                       } else if (ch == '=' && isalpha(chNext)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_POD;
+                               startSeg = i;
+                               quotes = 0;
+                               sookedpos = 0;
+                               sooked[sookedpos] = '\0';
+                       } else if (isPerlOperator(ch)) {
+                               if (ch == ')' || ch == ']')
+                                       preferRE = false;
+                               else
+                                       preferRE = true;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_PL_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_PL_WORD) {
+                       if (!iswordchar(ch) && ch != '\'') {    // Archaic Perl has quotes inside names
+                               if (isMatch(styler, lengthDoc, startSeg, "__DATA__")) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+                                       state = SCE_PL_DATASECTION;
+                               } else if (isMatch(styler, lengthDoc, startSeg, "__END__")) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+                                       state = SCE_PL_DATASECTION;
+                               } else {
+                                       if (classifyWordPerl(startSeg, i - 1, keywords, styler) == SCE_PL_WORD)
+                                               preferRE = true;
+                                       state = SCE_PL_DEFAULT;
+                                       startSeg = i;
+                                       if (ch == '#') {
+                                               state = SCE_PL_COMMENTLINE;
+                                       } else if (ch == '\"') {
+                                               state = SCE_PL_STRING;
+                                       } else if (ch == '\'') {
+                                               state = SCE_PL_CHARACTER;
+                                       } else if (ch == '<' && chNext == '<') {
+                                               state = SCE_PL_HERE;
+                                               quotes = 0;
+                                               startSeg = i;
+                                               sookedpos = 0;
+                                               sooked[sookedpos] = '\0';
+                                       } else if (isPerlOperator(ch)) {
+                                               if (ch == ')' || ch == ']')
+                                                       preferRE = false;
+                                               else
+                                                       preferRE = true;
+                                               styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+                                               state = SCE_PL_DEFAULT;
+                                               startSeg = i + 1;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_PL_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_PL_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_HERE) {
+                               if (isalnum(ch) && quotes < 2) {
+                                       sooked[sookedpos++] = ch;
+                                       sooked[sookedpos] = '\0';
+                                       if (quotes == 0)
+                                               quotes = 1;
+                               } else {
+                                       quotes++;
+                               }
+
+                               if (quotes > 1 && isMatch(styler, lengthDoc, i, sooked)) {
+                                       styler.ColourSegment(startSeg, i + sookedpos - 1, SCE_PL_HERE);
+                                       state = SCE_PL_DEFAULT;
+                                       i += sookedpos;
+                                       startSeg = i;
+                                       chNext = ' ';
+                               }
+                       } else if (state == SCE_PL_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_BACKTICKS) {
+                               if (ch == '`') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_POD) {
+                               if (ch == '=') {
+                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
+                                               styler.ColourSegment(startSeg, i - 1 + 4, state);
+                                               i += 4;
+                                               startSeg = i;
+                                               state = SCE_PL_DEFAULT;
+                                               chNext = ' ';
+                                               ch = ' ';
+                                       }
+                               }
+                       } else if (state == SCE_PL_SCALAR) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_ARRAY) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_HASH) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_SYMBOLTABLE) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_REF) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_REGEX) {
+                               if (!quoteUp && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(ch);
+                                       quotes++;
+                               } else {
+                                       if (ch == quoteDown && chPrev != '\\') {
+                                               quotes--;
+                                               if (quotes == 0) {
+                                                       quoteRep--;
+                                                       if (quoteUp == quoteDown) {
+                                                               quotes++;
+                                                       }
+                                               }
+                                               if (!isalpha(chNext)) {
+                                                       if (quoteRep <= 0) {
+                                                               styler.ColourSegment(startSeg, i, state);
+                                                               startSeg = i + 1;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = ' ';
+                                                       }
+                                               }
+                                       } else if (ch == quoteUp && chPrev != '\\') {
+                                               quotes++;
+                                       } else if (!isalpha(chNext)) {
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                       }
+                               }
+                       } else if (state == SCE_PL_REGSUBST) {
+                               if (!quoteUp && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(ch);
+                                       quotes++;
+                               } else {
+                                       if (ch == quoteDown && chPrev != '\\') {
+                                               quotes--;
+                                               if (quotes == 0) {
+                                                       quoteRep--;
+                                               }
+                                               if (!isalpha(chNext)) {
+                                                       if (quoteRep <= 0) {
+                                                               styler.ColourSegment(startSeg, i, state);
+                                                               startSeg = i + 1;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = ' ';
+                                                       }
+                                               }
+                                               if (quoteUp == quoteDown) {
+                                                       quotes++;
+                                               }
+                                       } else if (ch == quoteUp && chPrev != '\\') {
+                                               quotes++;
+                                       } else if (!isalpha(chNext)) {
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                       }
+                               }
+                       } else if (state == SCE_PL_LONGQUOTE) {
+                               if (!quoteDown && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(quoteUp);
+                                       quotes++;
+                               } else if (ch == quoteDown) {
+                                       quotes--;
+                                       if (quotes == 0) {
+                                               quoteRep--;
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                               if (quoteUp == quoteDown) {
+                                                       quotes++;
+                                               }
+                                       }
+                               } else if (ch == quoteUp) {
+                                       quotes++;
+                               }
+                       }
+
+                       if (state == SCE_PL_DEFAULT) {    // One of the above succeeded
+                               if (ch == '#') {
+                                       state = SCE_PL_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_PL_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_PL_CHARACTER;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_PL_WORD;
+                                       preferRE = false;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+
+static int classifyWordVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_DEFAULT;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_C_WORD;
+                       if (strcmp(s, "rem") == 0)
+                               chAttr = SCE_C_COMMENTLINE;
+               }
+       }
+       styler.ColourSegment(start, end, chAttr);
+       if (chAttr == SCE_C_COMMENTLINE)
+               return SCE_C_COMMENTLINE;
+       else
+               return SCE_C_DEFAULT;
+}
+
+static void ColouriseVBDoc(int codePage, int startPos, int length, int initStyle,
+                           WordList &keywords, StylingContext &styler) {
+       int state = initStyle;
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       for (int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               state = classifyWordVB(startSeg, i - 1, keywords, styler);
+                               if (state == SCE_C_DEFAULT) {
+                                       startSeg = i;
+                                       if (ch == '\'') {
+                                               state = SCE_C_COMMENTLINE;
+                                       } else if (ch == '\"') {
+                                               state = SCE_C_STRING;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               // VB doubles quotes to preserve them
+                               if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '\'') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               }
+                       }
+               }
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+static void classifyWordPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]);
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_P_IDENTIFIER;
+       if (0 == strcmp(prevWord, "class"))
+               chAttr = SCE_P_CLASSNAME;
+       else if (0 == strcmp(prevWord, "def"))
+               chAttr = SCE_P_DEFNAME;
+       else if (wordIsNumber)
+               chAttr = SCE_P_NUMBER;
+       else if (keywords.InList(s))
+               chAttr = SCE_P_WORD;
+       styler.ColourSegment(start, end, chAttr);
+       strcpy(prevWord, s);
+}
+
+static void ColourisePyDoc(int codePage, int startPos, int length, int initStyle, WordList &keywords, StylingContext &styler) {
+       //Platform::DebugPrintf("Python coloured\n");
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int whingeLevel = styler.GetPropSet().GetInt("tab.timmy.whinge.level");
+       char prevWord[200];
+       prevWord[0] = '\0';
+       if (length == 0)
+               return ;
+       int lineCurrent = styler.GetLine(startPos);
+       int spaceFlags = 0;
+       // TODO: Need to check previous line for indentation for both folding and bad indentation
+       int indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
+
+       int state = initStyle & 31;
+       char chPrev = ' ';
+       char chPrev2 = ' ';
+       char chNext = styler[startPos];
+       char chNext2 = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       bool atStartLine = true;
+       for (int i = startPos; i <= lengthDoc; i++) {
+       
+               if (atStartLine) {
+                       if (whingeLevel == 1) {
+                               styler.SetFlags((spaceFlags & wsInconsistent) ? 64 : 0, state);
+                       } else if (whingeLevel == 2) {
+                               styler.SetFlags((spaceFlags & wsSpaceTab) ? 64 : 0, state);
+                       } else if (whingeLevel == 3) {
+                               styler.SetFlags((spaceFlags & wsSpace) ? 64 : 0, state);
+                       } else if (whingeLevel == 4) {
+                               styler.SetFlags((spaceFlags & wsTab) ? 64 : 0, state);
+                       }
+                       atStartLine = false;
+               }
+               
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               chNext2 = styler.SafeGetCharAt(i + 2);
+               
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
+                               // Perform colourisation of white space and triple quoted strings at end of each line to allow
+                               // tab marking to work inside white space and triple quoted strings
+                               styler.ColourSegment(startSeg, i, state);
+                               startSeg = i + 1;
+                       }
+
+                       int lev = indentCurrent;
+                       int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               }
+                       }
+                       indentCurrent = indentNext;
+                       if (fold) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       atStartLine = true;
+               }
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       chPrev2 = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_P_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_P_WORD;
+                               startSeg = i;
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_P_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               startSeg = i;
+                               if (chNext == '\"' && chNext2 == '\"') {
+                                       i += 2;
+                                       state = SCE_P_TRIPLEDOUBLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_P_STRING;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               startSeg = i;
+                               if (chNext == '\'' && chNext2 == '\'') {
+                                       i += 2;
+                                       state = SCE_P_TRIPLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_P_CHARACTER;
+                               }
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_P_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_P_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordPy(startSeg, i - 1, keywords, styler, prevWord);
+                               state = SCE_P_DEFAULT;
+                               startSeg = i;
+                               if (ch == '#') {
+                                       state = SCE_P_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       if (chNext == '\"' && chNext2 == '\"') {
+                                               i += 2;
+                                               state = SCE_P_TRIPLEDOUBLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_P_STRING;
+                                       }
+                               } else if (ch == '\'') {
+                                       if (chNext == '\'' && chNext2 == '\'') {
+                                               i += 2;
+                                               state = SCE_P_TRIPLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_P_CHARACTER;
+                                       }
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_P_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               } else {
+                       if (state == SCE_P_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_P_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_TRIPLE) {
+                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_TRIPLEDOUBLE) {
+                               if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev2 = chPrev;
+               chPrev = ch;
+       }
+       if (startSeg <= lengthDoc) {
+               if (state == SCE_P_DEFAULT) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_WORD) {
+                       classifyWordPy(startSeg, lengthDoc, keywords, styler, prevWord);
+               } else if (state == SCE_P_COMMENTLINE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_STRING) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_CHARACTER) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_TRIPLE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_TRIPLEDOUBLE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               }
+       }
+}
+
+static void ColouriseBatchLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       if (0 == strncmp(lineBuffer, "REM", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "rem", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "SET", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (0 == strncmp(lineBuffer, "set", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (lineBuffer[0] == ':') {
+               styler.ColourSegment(0, lengthLine - 1, 3);
+       } else {
+               styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColouriseBatchDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i < startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseBatchLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseBatchLine(lineBuffer, linePos, styler);
+}
+
+enum { eScriptNone, eScriptJS, eScriptVBS, eScriptPython };
+static int segIsScriptingIndicator(StylingContext &styler, unsigned int start, unsigned int end, int prevValue) {
+       char s[100];
+       s[0] = '\0';
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+Platform::DebugPrintf("Scripting indicator [%s]\n", s);
+       if (strstr(s, "vbs"))
+               return eScriptVBS;
+       if (strstr(s, "pyth"))
+               return eScriptPython;
+       if (strstr(s, "javas"))
+               return eScriptJS;
+       if (strstr(s, "jscr"))
+               return eScriptJS;
+               
+       return prevValue;
+}
+
+static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.') ||
+                           (styler[start] == '-') || (styler[start] == '#');
+       char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
+       if (wordIsNumber) {
+               chAttr = SCE_H_NUMBER;
+       } else {
+               char s[100];
+               s[0] = '\0';
+               for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+                       s[i] = tolower(styler[start + i]);
+                       s[i + 1] = '\0';
+               }
+               if (keywords.InList(s))
+                       chAttr = SCE_H_ATTRIBUTE;
+       }
+       styler.ColourTo(end, chAttr);
+}
+
+static int classifyTagHTML(unsigned int start, unsigned int end,
+                         WordList &keywords, StylingContext &styler) {
+       char s[100];
+       // Copy after the '<'
+       unsigned int i = 0;
+       for (int cPos=start; cPos <= end && i < 30; cPos++) {
+               char ch = styler[cPos];
+               if (ch != '<')
+                       s[i++] = tolower(ch);
+       }
+       s[i] = '\0';
+       char chAttr = SCE_H_TAGUNKNOWN;
+       if (s[0] == '!' && s[1] == '-' && s[2] == '-') {        //Comment
+               chAttr = SCE_H_COMMENT;
+       } else if (s[0] == '/') {       // Closing tag
+               if (keywords.InList(s + 1))
+                       chAttr = SCE_H_TAG;
+       } else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_H_TAG;
+                       if (0 == strcmp(s, "script"))
+                               chAttr = SCE_H_SCRIPT;
+               }
+       }
+       styler.ColourTo(end, chAttr);
+       return chAttr;
+}
+
+static void classifyWordHTJS(unsigned int start, unsigned int end,
+                             WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_HJ_WORD;
+       if (wordIsNumber)
+               chAttr = SCE_HJ_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_HJ_KEYWORD;
+       }
+       styler.ColourTo(end, chAttr);
+}
+
+static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_HB_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_HB_NUMBER;
+       else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_HB_WORD;
+                       if (strcmp(s, "rem") == 0)
+                               chAttr = SCE_HB_COMMENTLINE;
+               }
+       }
+       styler.ColourTo(end, chAttr);
+       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, StylingContext &styler, char *prevWord) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]);
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\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, chAttr);
+       strcpy(prevWord, s);
+}
+
+inline bool ishtmlwordchar(char ch) {
+       return isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || 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 isLineEnd(char ch) {
+       return ch == '\r' || ch == '\n';
+}
+
+static void ColouriseHyperTextDoc(int codePage, int startPos, int length,
+                                  int initStyle, WordList &keywords, WordList &keywords2, WordList &keywords3, WordList &keywords4, 
+                                 StylingContext &styler) {
+       
+       styler.StartAt(startPos, 63);
+       bool lastTagWasScript = false;
+       char prevWord[200];
+       prevWord[0] = '\0';
+       int scriptLanguage = eScriptJS;
+       int state = initStyle;
+       // If inside a tag, it may be a script tage, so reread from the start to ensure any language tas are seen
+       if (InTagState(state)) {
+               while ((startPos > 1) && (InTagState(styler.StyleAt(startPos - 1)))) {
+                       startPos--;
+               }
+               state = SCE_H_DEFAULT;
+       }
+       styler.StartAt(startPos, 63);
+
+       int lineState = eScriptVBS;
+       int lineCurrent = styler.GetLine(startPos);
+       if (lineCurrent > 0)
+               lineState = styler.GetLineState(lineCurrent);
+       int defaultScript = lineState &0xff;
+       int beforeASP = (lineState >> 8) &0xff;
+       int inASP = (lineState >> 16) &0xff;
+       
+       char chPrev = ' ';
+       char chPrev2 = ' ';
+       styler.StartSegment(startPos);
+       int lengthDoc = startPos + length;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = styler[i];
+               char chNext = styler.SafeGetCharAt(i + 1);
+               char chNext2 = styler.SafeGetCharAt(i + 2);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chPrev2 = ' ';
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       // New line -> record any line state onto /next/ line
+                       lineCurrent++;
+                       styler.SetLineState(lineCurrent, 
+                               defaultScript | (beforeASP << 8) | (inASP << 16));
+               }
+               
+               // Handle ASP even within other constructs as it is a preprocessor
+               if ((ch == '<') && (chNext == '%')) {
+                       beforeASP = state;
+                       styler.ColourTo(i - 1, state);
+                       if (chNext2 == '@') {
+                               styler.ColourTo(i + 2, SCE_H_ASP);
+                               state = SCE_H_ASPAT;
+                               i+=2;
+                       } else {
+                               if (defaultScript == eScriptVBS)
+                                       state = SCE_HB_START;
+                               else if  (defaultScript == eScriptPython)
+                                       state = SCE_HP_START;
+                               else
+                                       state = SCE_HJ_START;
+                               if (chNext2 == '=') {
+                                       styler.ColourTo(i + 2, SCE_H_ASP);
+                                       i+=2;
+                               } else {
+                                       styler.ColourTo(i + 1, SCE_H_ASP);
+                                       i++;
+                               }
+                       }
+                       inASP = 1;
+                       continue;
+               }
+               if (inASP && (ch == '%') && (chNext == '>')) {
+                       if (state == SCE_H_ASPAT)
+                               defaultScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, defaultScript);
+                       // Bounce out of any ASP mode
+                       styler.ColourTo(i - 1, state);
+                       //if (state == SCE_H_ASPAT)
+                       //      styler.ColourTo(i+1, SCE_H_ASPAT);
+                       //else
+                               styler.ColourTo(i+1, SCE_H_ASP);
+                       i++;
+                       state = beforeASP;
+                       beforeASP = SCE_H_DEFAULT;
+                       inASP = 0;
+                       continue;
+               }
+               
+               if (state == SCE_H_DEFAULT) {
+                       if (ch == '<') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                               if (chNext == '?') {
+                                       styler.ColourTo(i + 1, SCE_H_XMLSTART);
+                                       i++;
+                                       ch = chNext;
+                               }
+                       } else if (ch == '&') {
+                               styler.ColourTo(i - 1, SCE_H_DEFAULT);
+                               state = SCE_H_ENTITY;
+                       }
+               } else if (state == SCE_H_COMMENT) {
+                       if ((ch == '>') && (chPrev == '-')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_ENTITY) {
+                       if (ch == ';') {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_TAGUNKNOWN) {
+                       if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+                               int eClass = classifyTagHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+                               lastTagWasScript = eClass == SCE_H_SCRIPT;
+                               if (lastTagWasScript) {
+                                       scriptLanguage = eScriptJS;
+                                       eClass = SCE_H_TAG;
+                               }
+                               if (ch == '>') {
+                                       styler.ColourTo(i, SCE_H_TAG);
+                                       if (lastTagWasScript) {
+                                               if (scriptLanguage == eScriptVBS)
+                                                       state = SCE_HB_START;
+                                               else if  (scriptLanguage == eScriptPython)
+                                                       state = SCE_HP_START;
+                                               else
+                                                       state = SCE_HJ_START;
+                                       } else {
+                                               state = SCE_H_DEFAULT;
+                                       }
+                               } else {
+                                       if (eClass == SCE_H_COMMENT) {
+                                               state = SCE_H_COMMENT;
+                                       } else {
+                                               state = SCE_H_OTHER;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_H_ATTRIBUTE) {
+                       if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, scriptLanguage);
+                               classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+                               if (ch == '>') {
+                                       styler.ColourTo(i, SCE_H_TAG);
+                                       if (lastTagWasScript) {
+                                               if (scriptLanguage == eScriptVBS)
+                                                       state = SCE_HB_START;
+                                               else if  (scriptLanguage == eScriptPython)
+                                                       state = SCE_HP_START;
+                                               else
+                                                       state = SCE_HJ_START;
+                                       } else {
+                                               state = SCE_H_DEFAULT;
+                                       }
+                               } else {
+                                       state = SCE_H_OTHER;
+                               }
+                       }
+               } else if (state == SCE_H_ASP) {
+                       if ((ch == '>') && (chPrev == '%')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_ASPAT) {
+                       if ((ch == '>') && (chPrev == '%')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_OTHER) {
+                       if (ch == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_H_TAG);
+                               if (lastTagWasScript) {
+                                       if (scriptLanguage == eScriptVBS)
+                                               state = SCE_HB_START;
+                                       else if  (scriptLanguage == eScriptPython)
+                                               state = SCE_HP_START;
+                                       else
+                                               state = SCE_HJ_START;
+                               } else {
+                                       state = SCE_H_DEFAULT;
+                               }
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_SINGLESTRING;
+                       } else if (ch == '/' && chNext == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       } else if (ch == '?' && chNext == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_XMLEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       } else if (ishtmlwordchar(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_ATTRIBUTE;
+                       }
+               } else if (state == SCE_H_DOUBLESTRING) {
+                       if (ch == '\"') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+                               styler.ColourTo(i, SCE_H_DOUBLESTRING);
+                               state = SCE_H_OTHER;
+                       }
+               } else if (state == SCE_H_SINGLESTRING) {
+                       if (ch == '\'') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+                               styler.ColourTo(i, SCE_H_SINGLESTRING);
+                               state = SCE_H_OTHER;
+                       }
+               } else if (state == SCE_HJ_DEFAULT || state == SCE_HJ_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_WORD;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext2 == '*')
+                                       state = SCE_HJ_COMMENTDOC;
+                               else
+                                       state = SCE_HJ_COMMENT;
+                       } else if (ch == '/' && chNext == '/') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_SINGLESTRING;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_COMMENTLINE;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                               state = SCE_HJ_DEFAULT;
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HJ_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HJ_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HJ_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler);
+                               //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 (isoperator(ch)) {
+                                       styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                                       state = SCE_HJ_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HJ_COMMENT) {
+                       if (ch == '/' && chPrev == '*') {
+                               state = SCE_HJ_DEFAULT;
+                               styler.ColourTo(i, SCE_HJ_COMMENT);
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_HJ_COMMENTDOC) {
+                       if (ch == '/' && chPrev == '*') {
+                               state = SCE_HJ_DEFAULT;
+                               styler.ColourTo(i, SCE_HJ_COMMENTDOC);
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_HJ_COMMENTLINE) {
+                       if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+                               state = SCE_HJ_DEFAULT;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               // Common to hide end script tag in comment
+                               styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+                               state = SCE_H_TAGUNKNOWN;
+                       }
+               } else if (state == SCE_HJ_DOUBLESTRING) {
+                       if (ch == '\\') {
+                               if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                       i++;
+                               }
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i, SCE_HJ_DOUBLESTRING);
+                               state = SCE_HJ_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (isLineEnd(ch)) {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HJ_STRINGEOL;
+                       }
+               } else if (state == SCE_HJ_SINGLESTRING) {
+                       if (ch == '\\') {
+                               if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                       i++;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i, SCE_HJ_SINGLESTRING);
+                               state = SCE_HJ_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (isLineEnd(ch)) {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HJ_STRINGEOL;
+                       }
+               } else if (state == SCE_HJ_STRINGEOL) {
+                       if (!isLineEnd(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_DEFAULT;
+                       }
+               } else if (state == SCE_HB_DEFAULT || state == SCE_HB_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_WORD;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_STRING;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HB_DEFAULT);
+                               state = SCE_HB_DEFAULT;
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HB_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HB_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HB_WORD) {
+                       if (!iswordchar(ch)) {
+                               state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler);
+                               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, SCE_HB_DEFAULT);
+                                               state = SCE_HB_DEFAULT;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_HB_STRING) {
+                       if (ch == '\"') {
+                               styler.ColourTo(i, state);
+                               state = SCE_HB_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HB_STRINGEOL;
+                       }
+               } else if (state == SCE_HB_COMMENTLINE) {
+                       if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_DEFAULT;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               // Common to hide end script tag in comment
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       }
+               } else if (state == SCE_HB_STRINGEOL) {
+                       if (!isLineEnd(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_DEFAULT;
+                       }
+               } else if (state == SCE_HP_DEFAULT || state == SCE_HP_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_WORD;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_COMMENTLINE;
+                       } else if (ch == '#') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext == '\"' && chNext2 == '\"') {
+                                       i += 2;
+                                       state = SCE_HP_TRIPLEDOUBLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_HP_STRING;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext == '\'' && chNext2 == '\'') {
+                                       i += 2;
+                                       state = SCE_HP_TRIPLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_HP_CHARACTER;
+                               }
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HP_OPERATOR);
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HP_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HP_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
+                               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 = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_HP_STRING;
+                                       }
+                               } else if (ch == '\'') {
+                                       if (chNext == '\'' && chNext2 == '\'') {
+                                               i += 2;
+                                               state = SCE_HP_TRIPLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_HP_CHARACTER;
+                                       }
+                               } else if (isoperator(ch)) {
+                                       styler.ColourTo(i, SCE_HP_OPERATOR);
+                               }
+                       }
+               } else {
+                       if (state == SCE_HP_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_TRIPLE) {
+                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_TRIPLEDOUBLE) {
+                               if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       }
+               }
+               if (state == SCE_HB_DEFAULT) {    // One of the above succeeded
+                       if (ch == '\"') {
+                               state = SCE_HB_STRING;
+                       } else if (ch == '\'') {
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (iswordstart(ch)) {
+                               state = SCE_HB_WORD;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i, SCE_HB_DEFAULT);
+                       }
+               }
+               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 == '\"') {
+                               state = SCE_HJ_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               state = SCE_HJ_SINGLESTRING;
+                       } else if (iswordstart(ch)) {
+                               state = SCE_HJ_WORD;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                       }
+               }
+               chPrev2 = chPrev;
+               chPrev = ch;
+       }
+       styler.ColourTo(lengthDoc - 1, state);
+}
+
+static void ColourisePropsLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       int i = 0;
+       while (isspace(lineBuffer[i]) && (i < lengthLine))      // Skip initial spaces
+               i++;
+       if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (lineBuffer[i] == '[') {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (lineBuffer[i] == '@') {
+               styler.ColourSegment(0, i, 4);
+               if (lineBuffer[++i] == '=')
+                       styler.ColourSegment(i, i, 3);
+               if (++i < lengthLine)
+                       styler.ColourSegment(i, lengthLine - 1, 0);
+       } else {
+               while (lineBuffer[i] != '=' && (i < lengthLine))        // Search the '=' character
+                       i++;
+               if (lineBuffer[i] == '=') {
+                       styler.ColourSegment(0, i - 1, 0);
+                       styler.ColourSegment(i, i, 3);
+                       if (++i < lengthLine)
+                               styler.ColourSegment(i, lengthLine - 1, 0);
+               } else
+                       styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColourisePropsDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       lineBuffer[linePos] = '\0';
+                       ColourisePropsLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColourisePropsLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseMakeLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       int i = 0;
+       while (isspace(lineBuffer[i]) && (i < lengthLine))
+               i++;
+       if (lineBuffer[i] == '#' || lineBuffer[i] == '!') {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else {
+               styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColouriseMakeDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseMakeLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseMakeLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseErrorListLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       if (lineBuffer[0] == '>') {
+               // Command or return status
+               styler.ColourSegment(0, lengthLine - 1, 4);
+       } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "Error ", strlen("Error "))) {
+               // Borland error message
+               styler.ColourSegment(0, lengthLine - 1, 5);
+       } else if (0 == strncmp(lineBuffer, "Warning ", strlen("Warning "))) {
+               // Borland warning message
+               styler.ColourSegment(0, lengthLine - 1, 5);
+       } else {
+               // Look for <filename>:<line>:message
+               // Look for <filename>(line)message
+               // Look for <filename>(line,pos)message
+               int state = 0;
+               for (int i = 0; i < lengthLine; i++) {
+                       if (state == 0 && lineBuffer[i] == ':' && isdigit(lineBuffer[i + 1])) {
+                               state = 1;
+                       } else if (state == 0 && lineBuffer[i] == '(') {
+                               state = 10;
+                       } else if (state == 1 && isdigit(lineBuffer[i])) {
+                               state = 2;
+                       } else if (state == 2 && lineBuffer[i] == ':') {
+                               state = 3;
+                               break;
+                       } else if (state == 2 && !isdigit(lineBuffer[i])) {
+                               state = 99;
+                       } else if (state == 10 && isdigit(lineBuffer[i])) {
+                               state = 11;
+                       } else if (state == 11 && lineBuffer[i] == ',') {
+                               state = 14;
+                       } else if (state == 11 && lineBuffer[i] == ')') {
+                               state = 12;
+                               break;
+                       } else if (state == 12 && lineBuffer[i] == ':') {
+                               state = 13;
+                       } else if (state == 14 && lineBuffer[i] == ')') {
+                               state = 15;
+                               break;
+                       } else if (((state == 11) || (state == 14)) && !((lineBuffer[i] == ' ') || isdigit(lineBuffer[i]))) {
+                               state = 99;
+                       }
+               }
+               if (state == 3) {
+                       styler.ColourSegment(0, lengthLine - 1, 2);
+               } else if ((state == 14) || (state == 15)) {
+                       styler.ColourSegment(0, lengthLine - 1, 3);
+               } else {
+                       styler.ColourSegment(0, lengthLine - 1, 0);
+               }
+       }
+}
+
+static void ColouriseErrorListDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseErrorListLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseErrorListLine(lineBuffer, linePos, styler);
+}
+
+static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = toupper(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_C_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseSQLDoc(int codePage, int startPos, int length,
+                            int initStyle, WordList &keywords, StylingContext &styler) {
+
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int lineCurrent = styler.GetLine(startPos);
+       int spaceFlags = 0;
+       int indentCurrent = 0;
+
+       int state = initStyle;
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       bool prevCr = false;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
+                       int lev = indentCurrent;
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
+                               if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               }
+                       }
+                       if (fold) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+               }
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENT;
+                               startSeg = i;
+                       } else if (ch == '-' && chNext == '-') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_C_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordSQL(startSeg, i - 1, keywords, styler);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                               if (ch == '/' && chNext == '*') {
+                                       state = SCE_C_COMMENT;
+                               } else if (ch == '-' && chNext == '-') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_STRING;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_COMMENT) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+                                       state = SCE_C_DEFAULT;
+                                       styler.ColourSegment(startSeg, i, state);
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               if (ch == '\'') {
+                                       if ( chNext == '\'' ) {
+                                               i++;
+                                       } else {
+                                               styler.ColourSegment(startSeg, i, state);
+                                               state = SCE_C_DEFAULT;
+                                               i++;
+                                               startSeg = i;
+                                       }
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '/' && chNext == '*') {
+                                       state = SCE_C_COMMENT;
+                               } else if (ch == '-' && chNext == '-') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_STRING;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc - 1, state);
+}
+
+void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle,
+                  int language, WordList *keywordlists[], StylingContext &styler) {
+       //Platform::DebugPrintf("ColouriseDoc <%s>\n", language);
+       if (language == SCLEX_PYTHON) {
+               // Python uses a different mask because bad indentation is marked by oring with 32
+               styler.StartAt(startPos, 127);
+               ColourisePyDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+       } else if (language == SCLEX_PERL) {
+               // 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
+               ColourisePerlDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+       } else if ((language == SCLEX_HTML) || (language == SCLEX_XML)) {
+               // Lexer for HTML requires more lexical states (6 bits worth) than most lexers
+               ColouriseHyperTextDoc(codePage, startPos, lengthDoc, initStyle, 
+                       *keywordlists[0], *keywordlists[1], *keywordlists[2], *keywordlists[3], styler);
+       } else {
+               styler.StartAt(startPos);
+               if (language == SCLEX_CPP) {
+                       ColouriseCppDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_SQL) {
+                       ColouriseSQLDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_VB) {
+                       ColouriseVBDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_PROPERTIES) {
+                       ColourisePropsDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_ERRORLIST) {
+                       ColouriseErrorListDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_MAKEFILE) {
+                       ColouriseMakeDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_BATCH) {
+                       ColouriseBatchDoc(startPos, lengthDoc, initStyle, styler);
+               } else {
+                       // Null language means all style bytes are 0 so just mark the end - no need to fill in.
+                       styler.StartAt(startPos + lengthDoc - 1);
+                       styler.ColourSegment(0, 0, 0);
+               }
+       }
+}
diff --git a/contrib/src/stc/scintilla/src/LineMarker.cxx b/contrib/src/stc/scintilla/src/LineMarker.cxx
new file mode 100644 (file)
index 0000000..9afccb8
--- /dev/null
@@ -0,0 +1,125 @@
+// Scintilla source code edit control
+// LineMarker.cxx - defines the look of a line marker in the margin 
+// Copyright 1998-2000 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 "LineMarker.h"
+
+void LineMarker::Draw(Surface *surface, PRectangle &rc) {
+       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;
+       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) {
+               int armSize = dimOn2-2;
+               Point xpts[] = {
+               Point(centreX - armSize, centreY),
+               Point(centreX, centreY),
+               Point(centreX, centreY - armSize),
+               Point(centreX, centreY - armSize),
+               Point(centreX, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX, centreY),
+               Point(centreX, centreY + armSize),
+               Point(centreX, centreY + armSize),
+               Point(centreX, centreY),
+               Point(centreX - armSize, centreY),
+               };
+               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) {
+               int armSize = dimOn2-2;
+               Point pts[] = {
+               Point(centreX - armSize, centreY - 1),
+               Point(centreX + armSize, centreY -1),
+               Point(centreX + armSize, centreY +1),
+               Point(centreX - armSize, centreY + 1),
+               };
+               Point xpts[] = {
+               Point(centreX - armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX - armSize, centreY),
+               };
+               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) {
+               // An invisible marker so don't draw anything
+       } else { // 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);
+       }
+}
diff --git a/contrib/src/stc/scintilla/src/LineMarker.h b/contrib/src/stc/scintilla/src/LineMarker.h
new file mode 100644 (file)
index 0000000..f22241b
--- /dev/null
@@ -0,0 +1,22 @@
+// Scintilla source code edit control
+// LineMarker.h - defines the look of a line marker in the margin 
+// Copyright 1998-2000 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
+
+class LineMarker {
+public:
+       int markType;
+       ColourPair fore;
+       ColourPair back;
+       LineMarker() {
+               markType = SC_MARK_CIRCLE;
+               fore = Colour(0,0,0);
+               back = Colour(0xff,0xff,0xff);
+       }
+       void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/PropSet.cxx b/contrib/src/stc/scintilla/src/PropSet.cxx
new file mode 100644 (file)
index 0000000..7e2a906
--- /dev/null
@@ -0,0 +1,399 @@
+// SciTE - Scintilla based Text Editor
+// PropSet.cxx - a java style properties file module
+// Copyright 1998-2000 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 <ctype.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+
+bool EqualCaseInsensitive(const char *a, const char *b) {
+#if PLAT_GTK
+       return 0 == strcasecmp(a, b);
+#elif PLAT_WIN
+       return 0 == stricmp(a, b);
+#elif PLAT_WX
+       return 0 == wxStricmp(a, b);
+#endif
+}
+
+// Get a line of input. If end of line escaped with '\\' then continue reading.
+static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
+       bool continuation = true;
+       while ((len > 1) && lenData > 0) {
+               char ch = *fpc;
+               fpc++;
+               lenData--;
+               if ((ch == '\r') || (ch == '\n')) {
+                       if (!continuation) {
+                               if ((lenData > 0) && (ch == '\r') && ((*fpc) == '\n')) {
+                                       // munch the second half of a crlf
+                                       fpc++;
+                                       lenData--;
+                               }
+                               *s++ = '\0';
+                               return true;
+                       }
+               } else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
+                       continuation = true;
+               } else {
+                       continuation = false;
+                       *s++ = ch;
+                       len--;
+               }
+       }
+       return false;
+}
+
+PropSet::PropSet() {
+       superPS = 0;
+       size = 10;
+       used = 0;
+       vals = new char * [size];
+}
+
+PropSet::~PropSet() {
+       superPS = 0;
+       Clear();
+       delete []vals;
+}
+
+void PropSet::EnsureCanAddEntry() {
+       if (used >= size - 2) {
+               int newsize = size + 10;
+               char **newvals = new char * [newsize];
+
+               for (int i = 0; i < used; i++) {
+                       newvals[i] = vals[i];
+               }
+               delete []vals;
+               vals = newvals;
+               size = newsize;
+       }
+}
+
+void PropSet::Set(const char *key, const char *val) {
+       EnsureCanAddEntry();
+       for (int i = 0; i < used; i += 2) {
+               if (EqualCaseInsensitive(vals[i], key)) {
+                       // Replace current value
+                       delete [](vals[i + 1]);
+                       vals[i + 1] = StringDup(val);
+                       return;
+               }
+       }
+       // Not found
+       vals[used++] = StringDup(key);
+       vals[used++] = StringDup(val);
+}
+
+void PropSet::Set(char *keyval) {
+       char *eqat = strchr(keyval, '=');
+       if (eqat) {
+               *eqat = '\0';
+               Set(keyval, eqat + 1);
+               *eqat = '=';
+       }
+}
+
+SString PropSet::Get(const char *key) {
+       for (int i = 0; i < used; i += 2) {
+               if (EqualCaseInsensitive(vals[i], key)) {
+                       return vals[i + 1];
+               }
+       }
+       if (superPS) {
+               // Failed here, so try in base property set
+               return superPS->Get(key);
+       } else {
+               return "";
+       }
+}
+
+int PropSet::GetInt(const char *key, int defaultValue) {
+       SString val = Get(key);
+       if (val.length())
+               return Get(key).value();
+       else
+               return defaultValue;
+}
+
+bool isprefix(const char *target, const char *prefix) {
+       while (*target && *prefix) {
+               if (toupper(*target) != toupper(*prefix))
+                       return false;
+               target++;
+               prefix++;
+       }
+       if (*prefix)
+               return false;
+       else
+               return true;
+}
+
+bool issuffix(const char *target, const char *suffix) {
+       int lentarget = strlen(target);
+       int lensuffix = strlen(suffix);
+       if (lensuffix > lentarget)
+               return false;
+       for (int i = lensuffix - 1; i >= 0; i--) {
+               if (toupper(target[i + lentarget - lensuffix]) != toupper(suffix[i]))
+                       return false;
+       }
+       return true;
+}
+
+SString PropSet::GetWild(const char *keybase, const char *filename) {
+       for (int i = 0; i < used; i += 2) {
+               if (isprefix(vals[i], keybase)) {
+                       char *orgkeyfile = vals[i] + strlen(keybase);
+                       char *keyfile = NULL;
+
+                       if (strstr(orgkeyfile, "$(") == orgkeyfile) {
+                               char *cpendvar = strchr(orgkeyfile, ')');
+                               if (cpendvar) {
+                                       int lenvar = cpendvar - orgkeyfile - 2;         // Subtract the $()
+                                       char *var = static_cast<char *>(malloc(lenvar + 1));
+                                       strncpy(var, orgkeyfile + 2, lenvar);
+                                       var[lenvar] = '\0';
+                                       SString s = Get(var);
+                                       free(var);
+                                       keyfile = strdup(s.c_str());
+                               }
+                       }
+                       char *keyptr = keyfile;
+
+                       if (keyfile == NULL)
+                               keyfile = orgkeyfile;
+
+                       for (; ; ) {
+                               char *del = strchr(keyfile, ';');
+                               if (del == NULL)
+                                       del = keyfile + strlen(keyfile);
+                               char delchr = *del;
+                               *del = '\0';
+                               if (*keyfile == '*') {
+                                       if (issuffix(filename, keyfile + 1)) {
+                                               *del = delchr;
+                                               free(keyptr);
+                                               return vals[i + 1];
+                                       }
+                               } else if (EqualCaseInsensitive(keyfile, filename)) {
+                                       *del = delchr;
+                                       free(keyptr);
+                                       return vals[i + 1];
+                               }
+                               if (delchr == '\0')
+                                       break;
+                               *del = delchr;
+                               keyfile = del + 1;
+                       }
+                       free(keyptr);
+
+                       if (EqualCaseInsensitive(vals[i], keybase)) {
+                               return vals[i + 1];
+                       }
+               }
+       }
+       if (superPS) {
+               // Failed here, so try in base property set
+               return superPS->GetWild(keybase, filename);
+       } else {
+               return "";
+       }
+}
+
+SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
+       char *base = StringDup(GetWild(keybase, filename).c_str());
+       char *cpvar = strstr(base, "$(");
+       while (cpvar) {
+               char *cpendvar = strchr(cpvar, ')');
+               if (cpendvar) {
+                       int lenvar = cpendvar - cpvar - 2;      // Subtract the $()
+                       char *var = new char[lenvar + 1];
+                       strncpy(var, cpvar + 2, lenvar);
+                       var[lenvar] = '\0';
+                       SString val = GetWild(var, filename);
+                       int newlenbase = strlen(base) + val.length() - lenvar;
+                       char *newbase = new char[newlenbase];
+                       strncpy(newbase, base, cpvar - base);
+                       strcpy(newbase + (cpvar - base), val.c_str());
+                       strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
+                       delete []var;
+                       delete []base;
+                       base = newbase;
+               }
+               cpvar = strstr(base, "$(");
+       }
+       SString sret = base;
+       delete []base;
+       return sret;
+}
+
+void PropSet::Clear() {
+       for (int i = 0; i < used; i++) {
+               delete [](vals[i]);
+               vals[i] = 0;
+       }
+       used = 0;
+}
+
+void PropSet::ReadFromMemory(const char *data, int len) {
+       if (len > 0) {
+               const char *pd = data;
+               char linebuf[60000];
+               while (GetFullLine(pd, len, linebuf, sizeof(linebuf))) {
+                       if (isalpha(linebuf[0]))
+                               Set(linebuf);
+               }
+       }
+}
+
+void PropSet::Read(const char *filename) {
+       //printf("Opening properties <%s>\n", filename);
+       Clear();
+       char propsData[60000];
+       FILE *rcfile = fopen(filename, "rb");
+       if (rcfile) {
+               int lenFile = fread(propsData, 1, sizeof(propsData), rcfile);
+               fclose(rcfile);
+               ReadFromMemory(propsData, lenFile);
+       } else {
+               //printf("Could not open <%s>\n", filename);
+       }
+}
+
+static bool iswordsep(char ch, bool onlyLineEnds) {
+       if (!isspace(ch))
+               return false;
+       if (!onlyLineEnds)
+               return true;
+       return ch == '\r' || ch == '\n';
+}
+
+// Creates an array that points into each word in the string and puts \0 terminators
+// after each word.
+static char **ArrayFromWordList(char *wordlist, bool onlyLineEnds = false) {
+       char prev = '\n';
+       int words = 0;
+       for (int j = 0; wordlist[j]; j++) {
+               if (!iswordsep(wordlist[j], onlyLineEnds) && iswordsep(prev, onlyLineEnds))
+                       words++;
+               prev = wordlist[j];
+       }
+       char **keywords = new char * [words + 1];
+       if (keywords) {
+               words = 0;
+               prev = '\0';
+               int len = strlen(wordlist);
+               for (int k = 0; k < len; k++) {
+                       if (!iswordsep(wordlist[k], onlyLineEnds)) {
+                               if (!prev) {
+                                       keywords[words] = &wordlist[k];
+                                       words++;
+                               }
+                       } else {
+                               wordlist[k] = '\0';
+                       }
+                       prev = wordlist[k];
+               }
+               keywords[words] = &wordlist[len];
+       }
+       return keywords;
+}
+
+void WordList::Clear() {
+       if (words) {
+               delete []words;
+               delete []list;
+       }
+       words = 0;
+       list = 0;
+       len = 0;
+}
+
+void WordList::Set(const char *s) {
+       len = 0;
+       list = StringDup(s);
+       words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+char *WordList::Allocate(int size) {
+       list = new char[size + 1];
+       list[size] = '\0';
+       return list;
+}
+
+void WordList::SetFromAllocated() {
+       len = 0;
+       words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+// Shell sort based upon public domain C implementation by Raymond Gardner 1991
+// Used here because of problems with mingw qsort.
+static void SortWordList(char **words, unsigned int len) {
+       unsigned int gap = len / 2;
+
+       while (gap > 0) {
+               unsigned int i = gap;
+               while (i < len) {
+                       unsigned int j = i;
+                       char **a = words + j;
+                       do {
+                               j -= gap;
+                               char **b = a;
+                               a -= gap;
+                               if (strcmp(*a, *b) > 0) {
+                                       char *tmp = *a;
+                                       *a = *b;
+                                       *b = tmp;
+                               } else {
+                                       break;
+                               }
+                       } while (j >= gap);
+                       i++;
+               }
+               gap = gap / 2;
+       }
+}
+
+bool WordList::InList(const char *s) {
+       if (0 == words)
+               return false;
+       if (len == 0) {
+               for (int i = 0; words[i][0]; i++)
+                       len++;
+               SortWordList(words, len);
+               for (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) {
+                       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++;
+               }
+       }
+       return false;
+}
diff --git a/contrib/src/stc/scintilla/src/SVector.h b/contrib/src/stc/scintilla/src/SVector.h
new file mode 100644 (file)
index 0000000..7bc9487
--- /dev/null
@@ -0,0 +1,110 @@
+// Scintilla source code edit control
+// SVector.h - a simple expandable vector
+// Copyright 1998-1999 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
+
+// A simple expandable vector. 
+// T must support assignment.
+// 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.
+template<class T, int sizeIncrement>
+class SVector {
+       T *v;
+       unsigned int size;      // Number of elements allocated
+       unsigned int len;       // Number of elements in vector
+       bool allocFailure;      // A memory allocation call has failed
+       
+       // Internally allocate more elements than the user wants to avoid 
+       // thrashng the memory allocator
+       void SizeTo(int newSize) {
+               if (newSize < sizeIncrement)
+                       newSize += sizeIncrement;
+               else 
+                       newSize = (newSize * 3) / 2;
+               T* newv = new T[newSize];
+               if (!newv) {
+                       allocFailure = true;
+                       return;
+               }
+               size = newSize;
+               for (int i=0; i<len; i++) {
+                       newv[i] = v[i];
+               }
+               delete []v;
+               v = newv;
+       }
+       
+public:
+       SVector() {
+               allocFailure = false;
+               v = 0;
+               len = 0;
+               size = 0;
+       }
+       ~SVector() {
+               Free();
+       }
+       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();
+                       }
+               }
+       }
+       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;
+       }
+       T &operator[](unsigned int i) {
+               if (i >= len) {
+                       if (i >= size) {
+                               SizeTo(i);
+                       }
+                       len = i+1;
+               }
+               return v[i];
+       }
+       void Free() {
+               delete []v;
+               v = 0;
+               size = 0;
+               len = 0;
+       }
+       void SetLength(int newLen) {
+               if (newLength > len) {
+                       if (newLength >= size) {
+                               SizeTo(newLength);
+                       }
+               }
+               len = newLen;
+       }
+       int Length() const {
+               return len;
+       }
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/ScintillaBase.cxx b/contrib/src/stc/scintilla/src/ScintillaBase.cxx
new file mode 100644 (file)
index 0000000..eb68904
--- /dev/null
@@ -0,0 +1,399 @@
+// Scintilla source code edit control
+// ScintillaBase.cxx - an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 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"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+ScintillaBase::ScintillaBase() {
+#ifdef SCI_LEXER       
+       lexLanguage = SCLEX_CONTAINER;
+       for (int wl=0;wl<numWordLists;wl++)
+               keyWordLists[wl] = new WordList;
+#endif
+}
+
+ScintillaBase::~ScintillaBase() {}
+
+void ScintillaBase::Finalise() {
+       popup.Destroy();
+}
+
+void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
+       Editor::RefreshColourPalette(pal, want);
+       ct.RefreshColourPalette(pal, want);
+}
+
+void ScintillaBase::AddChar(char ch) {
+       bool acActiveBeforeCharAdded = ac.Active();
+       Editor::AddChar(ch);
+       if (acActiveBeforeCharAdded)
+               AutoCompleteChanged(ch);
+}
+
+void ScintillaBase::Command(int cmdId) {
+
+       switch (cmdId) {
+
+       case idAutoComplete:    // Nothing to do
+               break;
+
+       case idCallTip:         // Nothing to do
+               break;
+
+       case idcmdUndo:
+               WndProc(WM_UNDO, 0, 0);
+               break;
+
+       case idcmdRedo:
+               WndProc(SCI_REDO, 0, 0);
+               break;
+
+       case idcmdCut:
+               WndProc(WM_CUT, 0, 0);
+               break;
+
+       case idcmdCopy:
+               WndProc(WM_COPY, 0, 0);
+               break;
+
+       case idcmdPaste:
+               WndProc(WM_PASTE, 0, 0);
+               break;
+
+       case idcmdDelete:
+               WndProc(WM_CLEAR, 0, 0);
+               break;
+
+       case idcmdSelectAll:
+               WndProc(SCI_SELECTALL, 0, 0);
+               break;
+       }
+}
+
+int ScintillaBase::KeyCommand(UINT 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();
+                       AutoCompleteChanged();
+                       EnsureCaretVisible();
+                       return 0;
+               case SCI_TAB:
+                       AutoCompleteCompleted();
+                       return 0;
+
+               default:
+                       ac.Cancel();
+               }
+       }
+
+       if (ct.inCallTipMode) {
+               if (
+                   (iMessage != SCI_CHARLEFT) &&
+                   (iMessage != SCI_CHARLEFTEXTEND) &&
+                   (iMessage != SCI_CHARRIGHT) &&
+                   (iMessage != SCI_CHARLEFTEXTEND) &&
+                   (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
+                   (iMessage != SCI_DELETEBACK)
+               ) {
+                       ct.CallTipCancel();
+               }
+               if (iMessage == SCI_DELETEBACK) {
+                       if (currentPos <= ct.posStartCallTip) {
+                               ct.CallTipCancel();
+                       }
+               }
+       }
+       return Editor::KeyCommand(iMessage);
+}
+
+void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
+       //Platform::DebugPrintf("AutoCOmplete %s\n", list);
+       ct.CallTipCancel();
+
+       ac.Start(wDraw, idAutoComplete, currentPos, lenEntered);
+
+       PRectangle rcClient = GetClientRectangle();
+       Point pt = LocationFromPosition(currentPos-lenEntered);
+
+       //Platform::DebugPrintf("Auto complete %x\n", lbAutoComplete);
+       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 - 5;
+       if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+           pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
+               rcac.top = pt.y - heightLB;
+               if (rcac.top < 0) {
+                       heightLB += rcac.top;
+                       rcac.top = 0;
+               }
+       } else {
+               rcac.top = pt.y + vs.lineHeight;
+       }
+       rcac.right = rcac.left + widthLB;
+       rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
+       ac.lb.SetPositionRelative(rcac, wMain);
+       ac.lb.SetFont(vs.styles[0].font);
+
+       int maxStrLen = 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.GetPosition();
+       int heightAlloced = rcList.bottom - rcList.top;
+       // Make an allowance for large strings in list
+       rcList.left = pt.x - 5;
+       rcList.right = rcList.left + Platform::Maximum(widthLB, maxStrLen * 8 + 16);
+       if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+           pt.y >= (rcClient.bottom + rcClient.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);
+       //lbAutoComplete.SetPosition(rcList);
+       ac.Show();
+}
+
+void ScintillaBase::AutoCompleteCancel() {
+       ac.Cancel();
+}
+
+void ScintillaBase::AutoCompleteMove(int delta) {
+       ac.Move(delta);
+}
+
+void ScintillaBase::AutoCompleteChanged(char ch) {
+       if (currentPos <= ac.posStart) {
+               ac.Cancel();
+       } else if (ac.IsStopChar(ch)) {
+               ac.Cancel();
+       } else {
+               char wordCurrent[1000];
+               int i;
+               int startWord = ac.posStart - ac.startLen;
+               for (i = startWord; i < currentPos; i++)
+                       wordCurrent[i - startWord] = pdoc->CharAt(i);
+               wordCurrent[i - startWord] = '\0';
+               ac.Select(wordCurrent);
+       }
+}
+
+void ScintillaBase::AutoCompleteCompleted() {
+       int item = ac.lb.GetSelection();
+       char selected[200];
+       if (item != -1) {
+               ac.lb.GetValue(item, selected, sizeof(selected));
+       }
+       ac.Cancel();
+       if (currentPos != ac.posStart) {
+               pdoc->DeleteChars(ac.posStart, currentPos - ac.posStart);
+       }
+       SetEmptySelection(ac.posStart);
+       if (item != -1) {
+               pdoc->InsertString(currentPos, selected + ac.startLen);
+               SetEmptySelection(currentPos + strlen(selected + ac.startLen));
+       }
+}
+
+void ScintillaBase::ContextMenu(Point pt) {
+       popup.CreatePopUp();
+       AddToPopUp("Undo", idcmdUndo, pdoc->CanUndo());
+       AddToPopUp("Redo", idcmdRedo, pdoc->CanRedo());
+       AddToPopUp("");
+       AddToPopUp("Cut", idcmdCut, currentPos != anchor);
+       AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
+       AddToPopUp("Paste", idcmdPaste, WndProc(EM_CANPASTE, 0, 0));
+       AddToPopUp("Delete", idcmdDelete, currentPos != anchor);
+       AddToPopUp("");
+       AddToPopUp("Select All", idcmdSelectAll);
+       popup.Show(pt, wMain);
+}
+
+void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+       AutoCompleteCancel();
+       ct.CallTipCancel();
+       Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+#ifdef SCI_LEXER
+void ScintillaBase::Colourise(int start, int end) {
+       int lengthDoc = Platform::SendScintilla(wMain.GetID(), SCI_GETLENGTH, 0, 0);
+       if (end == -1)
+               end = lengthDoc;
+       int len = end - start;
+
+       PropSet props;
+       
+       StylingContext styler(wMain.GetID(), props);
+
+       int styleStart = 0;
+       if (start > 0)
+               styleStart = styler.StyleAt(start - 1);
+
+       ColouriseDoc(pdoc->dbcsCodePage, start, len, styleStart, lexLanguage, keyWordLists, styler);
+       styler.Flush();
+}
+#endif
+
+void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) {
+#ifdef SCI_LEXER
+       if (lexLanguage != SCLEX_CONTAINER) {
+               int endStyled = Platform::SendScintilla(wMain.GetID(), SCI_GETENDSTYLED, 0, 0);
+               int lineEndStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEFROMCHAR, endStyled, 0);
+               endStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEINDEX, lineEndStyled, 0);
+               Colourise(endStyled, endStyleNeeded);
+               return;
+       }
+#endif
+       Editor::NotifyStyleNeeded(endStyleNeeded);
+}
+
+LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       switch (iMessage) {
+       case SCI_AUTOCSHOW:
+               AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
+               break;
+
+       case SCI_AUTOCCANCEL:
+               AutoCompleteCancel();
+               break;
+
+       case SCI_AUTOCACTIVE:
+               return ac.Active();
+
+       case SCI_AUTOCPOSSTART:
+               return ac.posStart;
+
+       case SCI_AUTOCCOMPLETE:
+               AutoCompleteCompleted();
+               break;
+
+       case SCI_AUTOCSTOPS:
+               ac.SetStopChars(reinterpret_cast<char *>(lParam));
+               break;
+
+       case SCI_CALLTIPSHOW: {
+                       AutoCompleteCancel();
+                       if (!ct.wCallTip.Created()) {
+                               PRectangle rc = ct.CallTipStart(currentPos, LocationFromPosition(wParam),
+                                                               reinterpret_cast<char *>(lParam),
+                                                               vs.styles[0].fontName, vs.styles[0].size);
+                               // 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, wDraw);
+                               ct.wCallTip.Show();
+                       }
+               }
+               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 = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+               
+#ifdef SCI_LEXER
+       case SCI_SETLEXER:
+               lexLanguage = wParam;
+               break;
+               
+       case SCI_GETLEXER:
+               return lexLanguage;
+               
+       case SCI_COLOURISE:
+               Colourise(wParam, lParam);
+               break;
+               
+       case SCI_SETPROPERTY:
+               props.Set(reinterpret_cast<const char *>(wParam), 
+                       reinterpret_cast<const char *>(lParam));
+               break;
+               
+       case SCI_SETKEYWORDS:
+               if ((wParam >= 0) && (wParam < numWordLists)) {
+                       keyWordLists[wParam]->Clear();
+                       keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
+               }
+               break;
+#endif
+
+       default:
+               return Editor::WndProc(iMessage, wParam, lParam);
+       }
+       return 0l;
+}
diff --git a/contrib/src/stc/scintilla/src/ScintillaBase.h b/contrib/src/stc/scintilla/src/ScintillaBase.h
new file mode 100644 (file)
index 0000000..e9f8f28
--- /dev/null
@@ -0,0 +1,68 @@
+// Scintilla source code edit control
+// ScintillaBase.h - defines an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 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
+
+class ScintillaBase : public Editor {
+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
+       };
+
+       Menu popup;
+       AutoComplete ac;
+
+       CallTip ct;
+
+#ifdef SCI_LEXER
+       int lexLanguage;
+       PropSet props;
+       enum {numWordLists=5};
+       WordList *keyWordLists[numWordLists];
+       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 AddChar(char ch);
+       void Command(int cmdId);
+       virtual int KeyCommand(UINT iMessage);
+       
+       void AutoCompleteStart(int lenEntered, const char *list);
+       void AutoCompleteCancel();
+       void AutoCompleteMove(int delta);
+       void AutoCompleteChanged(char ch=0);
+       void AutoCompleteCompleted();
+
+       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 NotifyStyleNeeded(int endStyleNeeded);
+public:
+       // Public so scintilla_send_message can use it
+       virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/Style.cxx b/contrib/src/stc/scintilla/src/Style.cxx
new file mode 100644 (file)
index 0000000..5631231
--- /dev/null
@@ -0,0 +1,63 @@
+// Scintilla source code edit control
+// Style.cxx - defines the font and colour style for a class of text
+// Copyright 1998-2000 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 "Style.h"
+
+Style::Style() {
+       Clear();
+}
+
+Style::~Style() {
+       font.Release();
+}
+
+Style &Style::operator=(const Style &source) {
+       if (this == &source)
+               return *this;
+       Clear();
+       fore.desired = source.fore.desired;
+       back.desired = source.back.desired;
+       bold = source.bold;
+       italic = source.italic;
+       size = source.size;
+       strcpy(fontName, source.fontName);
+       eolFilled = source.eolFilled;
+       return *this;
+}
+
+void Style::Clear(Colour fore_, Colour back_, int size_, const char *fontName_, 
+       bool bold_, bool italic_, bool eolFilled_) {
+       fore.desired = fore_;
+       back.desired = back_;
+       bold = bold_;
+       italic = italic_;
+       size = size_;
+       strcpy(fontName, fontName_);
+       eolFilled = eolFilled_;
+       font.Release();
+}
+
+void Style::Realise(Surface &surface, int zoomLevel) {
+       int sizeZoomed = size + zoomLevel;
+       if (sizeZoomed <= 2)    // Hangs if sizeZoomed <= 1
+               sizeZoomed = 2;
+               
+       int deviceHeight = (sizeZoomed * surface.LogPixelsY()) / 72;
+       font.Create(fontName, deviceHeight, bold, italic);
+
+       ascent = surface.Ascent(font);
+       descent = surface.Descent(font);
+       // Probably more typographically correct to include leading
+       // but that means more complex drawing as leading must be erased
+       //lineHeight = surface.ExternalLeading() + surface.Height();
+       externalLeading = surface.ExternalLeading(font);
+       lineHeight = surface.Height(font);
+       aveCharWidth = surface.AverageCharWidth(font);
+       spaceWidth = surface.WidthChar(font, ' ');
+}
diff --git a/contrib/src/stc/scintilla/src/Style.h b/contrib/src/stc/scintilla/src/Style.h
new file mode 100644 (file)
index 0000000..916b646
--- /dev/null
@@ -0,0 +1,37 @@
+// Scintilla source code edit control
+// Style.h - defines the font and colour style for a class of text
+// Copyright 1998-2000 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
+
+class Style {
+public:
+       ColourPair fore;
+       ColourPair back;
+       bool bold;
+       bool italic;
+       int size;
+       char fontName[100];
+       bool eolFilled;
+
+       Font font;
+       unsigned int lineHeight;
+       unsigned int ascent;
+       unsigned int descent;
+       unsigned int externalLeading;
+       unsigned int aveCharWidth;
+       unsigned int spaceWidth;
+
+       Style();
+       ~Style();
+       Style &operator=(const Style &source);
+       void Clear(Colour fore_=Colour(0,0,0), Colour back_=Colour(0xff,0xff,0xff),
+               int size_=Platform::DefaultFontSize(), 
+               const char *fontName_=Platform::DefaultFont(), 
+               bool bold_=false, bool italic_=false, bool eolFilled_=false);
+       void Realise(Surface &surface, int zoomLevel);
+};
+
+#endif
diff --git a/contrib/src/stc/scintilla/src/ViewStyle.cxx b/contrib/src/stc/scintilla/src/ViewStyle.cxx
new file mode 100644 (file)
index 0000000..001ecdb
--- /dev/null
@@ -0,0 +1,183 @@
+// Scintilla source code edit control
+// ViewStyle.cxx - store information on how the document is to be viewed
+// Copyright 1998-2000 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 "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+
+MarginStyle::MarginStyle() : 
+       symbol(false), width(16), mask(0xffffffff), sensitive(false) {
+}
+
+ViewStyle::ViewStyle() {
+       Init();
+}
+
+ViewStyle::ViewStyle(const ViewStyle &source) {
+       Init();
+       for (int sty=0;sty<=STYLE_MAX;sty++) {
+               styles[sty] = source.styles[sty];
+       }
+       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;
+       selbar.desired = source.selbar.desired;
+       selbarlight.desired = source.selbarlight.desired;
+       caretcolour.desired = source.caretcolour.desired;
+       edgecolour.desired = source.edgecolour.desired;
+       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;
+       viewEOL = source.viewEOL;
+       showMarkedLines = source.showMarkedLines;               
+}
+
+ViewStyle::~ViewStyle() {
+}
+
+void ViewStyle::Init() {
+       indicators[0].style = INDIC_SQUIGGLE;
+       indicators[0].fore = Colour(0, 0x7f, 0);
+       indicators[1].style = INDIC_TT;
+       indicators[1].fore = Colour(0, 0, 0xff);
+       indicators[2].style = INDIC_PLAIN;
+       indicators[2].fore = Colour(0xff, 0, 0);
+
+       lineHeight = 1;
+       maxAscent = 1;
+       maxDescent = 1;
+       aveCharWidth = 8;
+       spaceWidth = 8;
+
+       selforeset = false;
+       selforeground.desired = Colour(0xff, 0, 0);
+       selbackset = true;
+       selbackground.desired = Colour(0xc0, 0xc0, 0xc0);
+       selbar.desired = Platform::Chrome();
+       selbarlight.desired = Platform::ChromeHighlight();
+       styles[STYLE_LINENUMBER].fore.desired = Colour(0, 0, 0);
+       styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+       //caretcolour.desired = Colour(0xff, 0, 0);
+       caretcolour.desired = Colour(0, 0, 0);
+       edgecolour.desired = Colour(0xc0, 0xc0, 0xc0);
+       
+       leftMarginWidth = 1;
+       rightMarginWidth = 1;
+       ms[0].symbol = false;
+       ms[0].width = 0;
+       ms[0].mask = 0;
+       ms[1].symbol = true;
+       ms[1].width = 16;
+       ms[1].mask = ~SC_MASK_FOLDERS;
+       ms[2].symbol = true;
+       ms[2].width = 14;       // Nice width for arrows
+       ms[2].mask = SC_MASK_FOLDERS;
+       ms[2].width = 0;        // Nice width for arrows
+       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].symbol;
+               if (ms[margin].width > 0)
+                       maskInLine &= ~ms[margin].mask;
+       }
+       zoomLevel = 0;
+       viewWhitespace = false;
+       viewEOL = false;
+       showMarkedLines = true;
+}
+
+void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
+       unsigned int i;
+       for (i=0;i<(sizeof(styles)/sizeof(styles[0]));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++) {
+               pal.WantFind(markers[i].fore, want);
+               pal.WantFind(markers[i].back, want);
+       }
+       pal.WantFind(selforeground, want);
+       pal.WantFind(selbackground, want);
+       pal.WantFind(selbar, want);
+       pal.WantFind(selbarlight, want);
+       pal.WantFind(caretcolour, want);
+       pal.WantFind(edgecolour, want);
+}
+
+void ViewStyle::Refresh(Surface &surface) {
+       selbar.desired = Platform::Chrome();
+       selbarlight.desired = Platform::ChromeHighlight();
+       maxAscent = 1;
+       maxDescent = 1;
+       for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
+               styles[i].Realise(surface, zoomLevel);
+               if (maxAscent < styles[i].ascent)
+                       maxAscent = styles[i].ascent;
+               if (maxDescent < styles[i].descent)
+                       maxDescent = styles[i].descent;
+       }
+       
+       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].symbol;
+               if (ms[margin].width > 0)
+                       maskInLine &= ~ms[margin].mask;
+       }
+}
+
+void ViewStyle::ResetDefaultStyle() {
+       styles[STYLE_DEFAULT].Clear();
+}
+
+void ViewStyle::ClearStyles() {
+       // Reset all styles to be like the default style
+       for (int i=0; i<=STYLE_MAX; i++) {
+               if (i != STYLE_DEFAULT) {
+                       styles[i].Clear(
+                               styles[STYLE_DEFAULT].fore.desired, 
+                               styles[STYLE_DEFAULT].back.desired, 
+                               styles[STYLE_DEFAULT].size, 
+                               styles[STYLE_DEFAULT].fontName, 
+                               styles[STYLE_DEFAULT].bold, 
+                               styles[STYLE_DEFAULT].italic);
+               }
+       }
+       styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+}
+
diff --git a/contrib/src/stc/scintilla/src/ViewStyle.h b/contrib/src/stc/scintilla/src/ViewStyle.h
new file mode 100644 (file)
index 0000000..9448720
--- /dev/null
@@ -0,0 +1,59 @@
+// Scintilla source code edit control
+// ViewStyle.h - store information on how the document is to be viewed
+// Copyright 1998-2000 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
+
+class MarginStyle {
+public:
+       bool symbol;
+       int width;
+       int mask;
+       bool sensitive;
+       MarginStyle();
+};
+
+class ViewStyle {
+public:
+       Style styles[STYLE_MAX + 1];
+       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 selbar;
+       ColourPair selbarlight;
+       // Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
+       int leftMarginWidth;            // Spacing margin on left of text
+       int rightMarginWidth;   // Spacing margin on left of text
+       enum { margins=3 };
+       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;
+       bool viewWhitespace;
+       bool viewEOL;
+       bool showMarkedLines;
+       ColourPair caretcolour;
+       ColourPair edgecolour;
+       
+       ViewStyle();
+       ViewStyle(const ViewStyle &source);
+       ~ViewStyle();
+       void Init();
+       void RefreshColourPalette(Palette &pal, bool want);
+       void Refresh(Surface &surface);
+       void ResetDefaultStyle();
+       void ClearStyles();
+};
+
+#endif
diff --git a/contrib/src/stc/stc.cpp b/contrib/src/stc/stc.cpp
new file mode 100644 (file)
index 0000000..d4b02e8
--- /dev/null
@@ -0,0 +1,1386 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        stc.cpp
+// Purpose:     A wxWindows implementation of Scintilla.  This class is the
+//              one meant to be used directly by wx applications.  It does not
+//              derive directly from the Scintilla classes, but instead
+//              delegates most things to the real Scintilla class.
+//              This allows the use of Scintilla without polluting the
+//              namespace with all the classes and itentifiers from Scintilla.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/stc/stc.h"
+#include "ScintillaWX.h"
+
+#include <wx/tokenzr.h>
+
+//----------------------------------------------------------------------
+
+const wxChar* wxSTCNameStr = "stcwindow";
+
+BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl)
+    EVT_PAINT                   (wxStyledTextCtrl::OnPaint)
+    EVT_SCROLLWIN               (wxStyledTextCtrl::OnScrollWin)
+    EVT_SIZE                    (wxStyledTextCtrl::OnSize)
+    EVT_LEFT_DOWN               (wxStyledTextCtrl::OnMouseLeftDown)
+    EVT_MOTION                  (wxStyledTextCtrl::OnMouseMove)
+    EVT_LEFT_UP                 (wxStyledTextCtrl::OnMouseLeftUp)
+    EVT_RIGHT_UP                (wxStyledTextCtrl::OnMouseRightUp)
+    EVT_CHAR                    (wxStyledTextCtrl::OnChar)
+    EVT_KILL_FOCUS              (wxStyledTextCtrl::OnLoseFocus)
+    EVT_SET_FOCUS               (wxStyledTextCtrl::OnGainFocus)
+    EVT_SYS_COLOUR_CHANGED      (wxStyledTextCtrl::OnSysColourChanged)
+    EVT_ERASE_BACKGROUND        (wxStyledTextCtrl::OnEraseBackground)
+    EVT_MENU_RANGE              (-1, -1, wxStyledTextCtrl::OnMenu)
+END_EVENT_TABLE()
+
+//----------------------------------------------------------------------
+// Constructor and Destructor
+
+wxStyledTextCtrl::wxStyledTextCtrl(wxWindow *parent,
+                                   wxWindowID id,
+                                   const wxPoint& pos,
+                                   const wxSize& size,
+                                   long style,
+                                   const wxString& name) :
+    wxControl(parent, id, pos, size,
+              style | wxVSCROLL | wxHSCROLL | wxWANTS_CHARS,
+              wxDefaultValidator, name)
+{
+    m_swx = new ScintillaWX(this);
+    // m_keywords = new WordList;
+    m_stopWatch.Start();
+    m_readOnly = false;
+    m_undoType = wxSTC_UndoCollectAutoStart;
+}
+
+
+wxStyledTextCtrl::~wxStyledTextCtrl() {
+    delete m_swx;
+    // delete m_keywords;
+}
+
+
+//----------------------------------------------------------------------
+
+inline long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
+
+    return m_swx->WndProc(msg, wp, lp);
+}
+
+
+//----------------------------------------------------------------------
+// Text retrieval and modification
+
+wxString wxStyledTextCtrl::GetText() {
+    wxString text;
+    int   len  = GetTextLength();
+    char* buff = text.GetWriteBuf(len);
+
+    SendMsg(WM_GETTEXT, len, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+bool wxStyledTextCtrl::SetText(const wxString& text) {
+    return SendMsg(WM_SETTEXT, 0, (long)text.c_str()) != 0;
+}
+
+
+wxString wxStyledTextCtrl::GetLine(int line) {
+    wxString text;
+    int   len  = GetLineLength(line);
+    char* buff = text.GetWriteBuf(len+1);
+
+    *((WORD*)buff) = len+1;
+    SendMsg(EM_GETLINE, line, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::ReplaceSelection(const wxString& text) {
+    SendMsg(EM_REPLACESEL, 0, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::SetReadOnly(bool readOnly) {
+    SendMsg(EM_SETREADONLY, (long)readOnly);
+    m_readOnly = readOnly;
+}
+
+
+bool wxStyledTextCtrl::GetReadOnly() {
+    // TODO: need support in Scintilla to do this right,
+    //       until then we'll track it ourselves
+    return m_readOnly;
+}
+
+
+void wxStyledTextCtrl::GetTextRange(int startPos, int endPos, char* buff) {
+    TEXTRANGE tr;
+    tr.lpstrText = buff;
+    tr.chrg.cpMin = startPos;
+    tr.chrg.cpMax = endPos;
+    SendMsg(EM_GETTEXTRANGE, 0, (long)&tr);
+}
+
+
+wxString wxStyledTextCtrl::GetTextRange(int startPos, int endPos) {
+    wxString  text;
+    int       len  = endPos - startPos;
+    char*     buff = text.GetWriteBuf(len);
+    GetTextRange(startPos, endPos, buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::GetStyledTextRange(int startPos, int endPos, char* buff) {
+    TEXTRANGE tr;
+    tr.lpstrText = buff;
+    tr.chrg.cpMin = startPos;
+    tr.chrg.cpMax = endPos;
+    SendMsg(SCI_GETSTYLEDTEXT, 0, (long)&tr);
+}
+
+
+wxString wxStyledTextCtrl::GetStyledTextRange(int startPos, int endPos) {
+    wxString  text;
+    int       len  = endPos - startPos;
+    char*     buff = text.GetWriteBuf(len*2);
+    GetStyledTextRange(startPos, endPos, buff);
+    text.UngetWriteBuf(len*2);
+    return text;
+}
+
+
+void wxStyledTextCtrl::AddText(const wxString& text) {
+    SendMsg(SCI_ADDTEXT, text.Len(), (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::AddStyledText(const wxString& text) {
+    SendMsg(SCI_ADDSTYLEDTEXT, text.Len(), (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::InsertText(int pos, const wxString& text) {
+    SendMsg(SCI_INSERTTEXT, pos, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::ClearAll() {
+    SendMsg(SCI_CLEARALL);
+}
+
+
+char wxStyledTextCtrl::GetCharAt(int pos) {
+    return SendMsg(SCI_GETCHARAT, pos);
+}
+
+
+char wxStyledTextCtrl::GetStyleAt(int pos) {
+    return SendMsg(SCI_GETSTYLEAT, pos);
+}
+
+
+void wxStyledTextCtrl::SetStyleBits(int bits) {
+    SendMsg(SCI_SETSTYLEBITS, bits);
+}
+
+
+int  wxStyledTextCtrl::GetStyleBits() {
+    return SendMsg(SCI_GETSTYLEBITS);
+}
+
+
+//----------------------------------------------------------------------
+// Clipboard
+
+
+void wxStyledTextCtrl::Cut() {
+    SendMsg(WM_CUT);
+}
+
+
+void wxStyledTextCtrl::Copy() {
+    SendMsg(WM_COPY);
+}
+
+
+void wxStyledTextCtrl::Paste() {
+    SendMsg(WM_PASTE);
+}
+
+
+bool wxStyledTextCtrl::CanPaste() {
+    return SendMsg(EM_CANPASTE) != 0;
+}
+
+
+void wxStyledTextCtrl::ClearClipbrd() {
+    SendMsg(WM_CLEAR);
+}
+
+
+
+//----------------------------------------------------------------------
+// Undo and Redo
+
+void wxStyledTextCtrl::Undo() {
+    SendMsg(WM_UNDO);
+}
+
+
+bool wxStyledTextCtrl::CanUndo() {
+    return SendMsg(EM_CANUNDO) != 0;
+}
+
+
+void wxStyledTextCtrl::EmptyUndoBuffer() {
+    SendMsg(EM_EMPTYUNDOBUFFER);
+}
+
+
+void wxStyledTextCtrl::Redo() {
+    SendMsg(SCI_REDO);
+}
+
+
+bool wxStyledTextCtrl::CanRedo() {
+    return SendMsg(SCI_CANREDO) != 0;
+}
+
+
+void wxStyledTextCtrl::SetUndoCollection(wxSTC_UndoType type) {
+    SendMsg(SCI_SETUNDOCOLLECTION, type);
+    m_undoType = type;
+}
+
+
+wxSTC_UndoType wxStyledTextCtrl::GetUndoCollection() {
+    // TODO: need support in Scintilla to do this right,
+    //       until then we'll track it ourselves
+    return m_undoType;
+}
+
+
+void wxStyledTextCtrl::BeginUndoAction() {
+    SendMsg(SCI_BEGINUNDOACTION);
+}
+
+
+void wxStyledTextCtrl::EndUndoAction() {
+    SendMsg(SCI_ENDUNDOACTION);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Selection and information
+
+
+void wxStyledTextCtrl::GetSelection(int* startPos, int* endPos) {
+    SendMsg(EM_GETSEL, (long)startPos, (long)endPos);
+}
+
+
+void wxStyledTextCtrl::SetSelection(int  startPos, int  endPos) {
+    SendMsg(EM_SETSEL, startPos, endPos);
+}
+
+
+wxString wxStyledTextCtrl::GetSelectedText() {
+    wxString text;
+    int   start;
+    int   end;
+
+    GetSelection(&start, &end);
+    int   len  = end - start;
+    char* buff = text.GetWriteBuf(len);
+
+    SendMsg(EM_GETSELTEXT, 0, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::HideSelection(bool hide) {
+    SendMsg(EM_HIDESELECTION, hide);
+}
+
+
+bool wxStyledTextCtrl::GetHideSelection() {
+    return m_swx->GetHideSelection();
+}
+
+
+int wxStyledTextCtrl::GetTextLength() {
+    return SendMsg(WM_GETTEXTLENGTH);
+}
+
+
+int wxStyledTextCtrl::GetFirstVisibleLine() {
+    return SendMsg(EM_GETFIRSTVISIBLELINE);
+}
+
+
+int wxStyledTextCtrl::GetLineCount() {
+    return SendMsg(EM_GETLINECOUNT);
+}
+
+
+bool wxStyledTextCtrl::GetModified() {
+    return SendMsg(EM_GETMODIFY) != 0;
+}
+
+
+wxRect wxStyledTextCtrl::GetRect() {
+    PRectangle pr;
+    SendMsg(EM_GETRECT, 0, (long)&pr);
+
+    wxRect rect = wxRectFromPRectangle(pr);
+    return rect;
+}
+
+
+int wxStyledTextCtrl::GetLineFromPos(int pos) {
+    return SendMsg(EM_LINEFROMCHAR, pos);
+}
+
+
+int wxStyledTextCtrl::GetLineStartPos(int line) {
+    return SendMsg(EM_LINEINDEX, line);
+}
+
+
+int wxStyledTextCtrl::GetLineLengthAtPos(int pos) {
+    return SendMsg(EM_LINELENGTH, pos);
+}
+
+
+int wxStyledTextCtrl::GetLineLength(int line) {
+    return SendMsg(SCI_LINELENGTH, line);
+}
+
+
+int wxStyledTextCtrl::GetCurrentLine() {
+    int line = GetLineFromPos(GetCurrentPos());
+    return line;
+}
+
+
+wxString wxStyledTextCtrl::GetCurrentLineText(int* linePos) {
+    wxString text;
+    int   len  = GetLineLength(GetCurrentLine());
+    char* buff = text.GetWriteBuf(len+1);
+
+    int pos = SendMsg(SCI_GETCURLINE, len+1, (long)buff);
+    text.UngetWriteBuf();
+
+    if (linePos)
+        *linePos = pos;
+
+    return text;
+}
+
+
+int wxStyledTextCtrl::PositionFromPoint(wxPoint pt) {
+    Point spt(pt.x, pt.y);
+    long rv = SendMsg(EM_CHARFROMPOS, 0, (long)&spt);
+    return LOWORD(rv);
+}
+
+
+int wxStyledTextCtrl::LineFromPoint(wxPoint pt) {
+    Point spt(pt.x, pt.y);
+    long rv = SendMsg(EM_CHARFROMPOS, 0, (long)&spt);
+    return HIWORD(rv);
+}
+
+
+wxPoint wxStyledTextCtrl::PointFromPosition(int pos) {
+    Point pt;
+    SendMsg(EM_POSFROMCHAR, pos, (long)&pt);
+    return wxPoint(pt.x, pt.y);
+}
+
+
+int wxStyledTextCtrl::GetCurrentPos() {
+    return SendMsg(SCI_GETCURRENTPOS);
+}
+
+
+int wxStyledTextCtrl::GetAnchor() {
+    return SendMsg(SCI_GETANCHOR);
+}
+
+
+void wxStyledTextCtrl::SelectAll() {
+    SendMsg(SCI_SELECTALL);
+}
+
+
+void wxStyledTextCtrl::SetCurrentPosition(int pos) {
+    SendMsg(SCI_GOTOPOS, pos);
+}
+
+
+void wxStyledTextCtrl::SetAnchor(int pos) {
+    SendMsg(SCI_SETANCHOR, pos);
+}
+
+
+void wxStyledTextCtrl::GotoPos(int pos) {
+    SendMsg(SCI_GOTOPOS, pos);
+}
+
+
+void wxStyledTextCtrl::GotoLine(int line) {
+    SendMsg(SCI_GOTOLINE, line);
+}
+
+
+void wxStyledTextCtrl::ChangePosition(int delta, bool extendSelection) {
+    // TODO:  Is documented but doesn't seem to be implemented
+    //SendMsg(SCI_CHANGEPOSITION, delta, extendSelection);
+}
+
+
+void wxStyledTextCtrl::PageMove(int cmdKey, bool extendSelection) {
+    // TODO:  Is documented but doesn't seem to be implemented
+    //SendMsg(SCI_PAGEMOVE, cmdKey, extendSelection);
+}
+
+
+void wxStyledTextCtrl::ScrollBy(int columnDelta, int lineDelta) {
+    SendMsg(EM_LINESCROLL, columnDelta, lineDelta);
+}
+
+void wxStyledTextCtrl::ScrollToLine(int line) {
+    m_swx->DoScrollToLine(line);
+}
+
+
+void wxStyledTextCtrl::ScrollToColumn(int column) {
+    m_swx->DoScrollToColumn(column);
+}
+
+
+void wxStyledTextCtrl::EnsureCaretVisible() {
+    SendMsg(EM_SCROLLCARET);
+}
+
+
+void wxStyledTextCtrl::SetCaretPolicy(int policy, int slop) {
+    SendMsg(SCI_SETCARETPOLICY, policy, slop);
+}
+
+
+int wxStyledTextCtrl::GetSelectionType() {
+    return SendMsg(EM_SELECTIONTYPE);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Searching
+
+int wxStyledTextCtrl::FindText(int minPos, int maxPos,
+                                     const wxString& text,
+                                     bool caseSensitive, bool wholeWord) {
+    FINDTEXTEX  ft;
+    int         flags = 0;
+
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+    ft.chrg.cpMin = minPos;
+    ft.chrg.cpMax = maxPos;
+    ft.lpstrText = (char*)text.c_str();
+
+    return SendMsg(EM_FINDTEXT, flags, (long)&ft);
+}
+
+
+void wxStyledTextCtrl::SearchAnchor() {
+    SendMsg(SCI_SEARCHANCHOR);
+}
+
+
+int wxStyledTextCtrl::SearchNext(const wxString& text, bool caseSensitive, bool wholeWord) {
+    int flags = 0;
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+
+    return SendMsg(SCI_SEARCHNEXT, flags, (long)text.c_str());
+}
+
+
+int wxStyledTextCtrl::SearchPrev(const wxString& text, bool caseSensitive, bool wholeWord) {
+    int flags = 0;
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+
+    return SendMsg(SCI_SEARCHPREV, flags, (long)text.c_str());
+}
+
+//----------------------------------------------------------------------
+// Visible whitespace
+
+
+bool wxStyledTextCtrl::GetViewWhitespace() {
+    return SendMsg(SCI_GETVIEWWS) != 0;
+}
+
+
+void wxStyledTextCtrl::SetViewWhitespace(bool visible) {
+    SendMsg(SCI_SETVIEWWS, visible);
+}
+
+
+
+//----------------------------------------------------------------------
+// Line endings
+
+wxSTC_EOL wxStyledTextCtrl::GetEOLMode() {
+    return (wxSTC_EOL)SendMsg(SCI_GETEOLMODE);
+}
+
+
+void wxStyledTextCtrl::SetEOLMode(wxSTC_EOL mode) {
+    SendMsg(SCI_SETEOLMODE, mode);
+}
+
+
+bool wxStyledTextCtrl::GetViewEOL() {
+    return SendMsg(SCI_GETVIEWEOL) != 0;
+}
+
+
+void wxStyledTextCtrl::SetViewEOL(bool visible) {
+    SendMsg(SCI_SETVIEWEOL, visible);
+}
+
+void wxStyledTextCtrl::ConvertEOL(wxSTC_EOL mode) {
+    SendMsg(SCI_CONVERTEOLS, mode);
+}
+
+//----------------------------------------------------------------------
+// Styling
+
+int wxStyledTextCtrl::GetEndStyled() {
+    return SendMsg(SCI_GETENDSTYLED);
+}
+
+
+void wxStyledTextCtrl::StartStyling(int pos, int mask) {
+    SendMsg(SCI_STARTSTYLING, pos, mask);
+}
+
+
+void wxStyledTextCtrl::SetStyleFor(int length, int style) {
+    SendMsg(SCI_SETSTYLING, length, style);
+}
+
+
+void wxStyledTextCtrl::SetStyleBytes(int length, char* styleBytes) {
+    SendMsg(SCI_SETSTYLINGEX, length, (long)styleBytes);
+}
+
+
+//----------------------------------------------------------------------
+// Style Definition
+
+
+static long wxColourAsLong(const wxColour& co) {
+    return (((long)co.Blue()  << 16) |
+            ((long)co.Green() <<  8) |
+            ((long)co.Red()));
+}
+
+static wxColour wxColourFromLong(long c) {
+    wxColour clr;
+    clr.Set(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
+    return clr;
+}
+
+
+static wxColour wxColourFromSpec(const wxString& spec) {
+    // spec should be #RRGGBB
+    char* junk;
+    int red   = strtol(spec.Mid(1,2), &junk, 16);
+    int green = strtol(spec.Mid(3,2), &junk, 16);
+    int blue  = strtol(spec.Mid(5,2), &junk, 16);
+    return wxColour(red, green, blue);
+}
+
+
+void wxStyledTextCtrl::StyleClearAll() {
+    SendMsg(SCI_STYLECLEARALL);
+}
+
+
+void wxStyledTextCtrl::StyleResetDefault() {
+    SendMsg(SCI_STYLERESETDEFAULT);
+}
+
+
+
+// Extract style settings from a spec-string which is composed of one or
+// more of the following comma separated elements:
+//
+//      bold                    turns on bold
+//      italic                  turns on italics
+//      fore:#RRGGBB            sets the foreground colour
+//      back:#RRGGBB            sets the background colour
+//      face:[facename]         sets the font face name to use
+//      size:[num]              sets the font size in points
+//      eol                     turns on eol filling
+//
+
+void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
+
+    wxStringTokenizer tkz(spec, ",");
+    while (tkz.HasMoreTokens()) {
+        wxString token = tkz.GetNextToken();
+
+        wxString option = token.BeforeFirst(':');
+        wxString val = token.AfterFirst(':');
+
+        if (option == "bold")
+            StyleSetBold(styleNum, true);
+
+        else if (option == "italic")
+            StyleSetItalic(styleNum, true);
+
+        else if (option == "eol")
+            StyleSetEOLFilled(styleNum, true);
+
+        else if (option == "size") {
+            long points;
+            if (val.ToLong(&points))
+                StyleSetSize(styleNum, points);
+        }
+
+        else if (option == "face")
+            StyleSetFaceName(styleNum, val);
+
+        else if (option == "fore")
+            StyleSetForeground(styleNum, wxColourFromSpec(val));
+
+        else if (option == "back")
+            StyleSetBackground(styleNum, wxColourFromSpec(val));
+    }
+}
+
+
+void wxStyledTextCtrl::StyleSetForeground(int styleNum, const wxColour& colour) {
+    SendMsg(SCI_STYLESETFORE, styleNum, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::StyleSetBackground(int styleNum, const wxColour& colour) {
+    SendMsg(SCI_STYLESETBACK, styleNum, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) {
+    int      size     = font.GetPointSize();
+    wxString faceName = font.GetFaceName();
+    bool     bold     = font.GetWeight() == wxBOLD;
+    bool     italic   = font.GetStyle() != wxNORMAL;
+
+    StyleSetFontAttr(styleNum, size, faceName, bold, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size,
+                                        const wxString& faceName,
+                                        bool bold, bool italic) {
+    StyleSetSize(styleNum, size);
+    StyleSetFaceName(styleNum, faceName);
+    StyleSetBold(styleNum, bold);
+    StyleSetItalic(styleNum, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetBold(int styleNum, bool bold) {
+    SendMsg(SCI_STYLESETBOLD, styleNum, bold);
+}
+
+
+void wxStyledTextCtrl::StyleSetItalic(int styleNum, bool italic) {
+    SendMsg(SCI_STYLESETITALIC, styleNum, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetFaceName(int styleNum, const wxString& faceName) {
+    SendMsg(SCI_STYLESETFONT, styleNum, (long)faceName.c_str());
+}
+
+
+void wxStyledTextCtrl::StyleSetSize(int styleNum, int pointSize) {
+    SendMsg(SCI_STYLESETSIZE, styleNum, pointSize);
+}
+
+
+void wxStyledTextCtrl::StyleSetEOLFilled(int styleNum, bool fillEOL) {
+    SendMsg(SCI_STYLESETEOLFILLED, styleNum, fillEOL);
+}
+
+
+//----------------------------------------------------------------------
+// Margins in the edit area
+
+int wxStyledTextCtrl::GetLeftMargin() {
+    return LOWORD(SendMsg(EM_GETMARGINS));
+}
+
+
+int wxStyledTextCtrl::GetRightMargin() {
+    return HIWORD(SendMsg(EM_GETMARGINS));
+}
+
+
+void wxStyledTextCtrl::SetMargins(int left, int right) {
+    int flag = 0;
+    int val = 0;
+
+    if (right != -1) {
+        flag |= EC_RIGHTMARGIN;
+        val = right << 16;
+    }
+    if (left != -1) {
+        flag |= EC_LEFTMARGIN;
+        val |= (left & 0xffff);
+    }
+
+    SendMsg(EM_SETMARGINS, flag, val);
+}
+
+
+//----------------------------------------------------------------------
+// Margins for selection, markers, etc.
+
+void wxStyledTextCtrl::SetMarginType(int margin, int type) {
+    SendMsg(SCI_SETMARGINTYPEN, margin, type);
+}
+
+
+int  wxStyledTextCtrl::GetMarginType(int margin) {
+    return SendMsg(SCI_GETMARGINTYPEN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginWidth(int margin, int pixelWidth) {
+    SendMsg(SCI_SETMARGINWIDTHN, margin, pixelWidth);
+}
+
+
+int  wxStyledTextCtrl::GetMarginWidth(int margin) {
+    return SendMsg(SCI_GETMARGINWIDTHN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginMask(int margin, int mask) {
+    SendMsg(SCI_SETMARGINMASKN, margin, mask);
+}
+
+
+int  wxStyledTextCtrl::GetMarginMask(int margin) {
+    return SendMsg(SCI_GETMARGINMASKN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginSensitive(int margin, bool sensitive) {
+    SendMsg(SCI_SETMARGINSENSITIVEN, margin, sensitive);
+}
+
+
+bool wxStyledTextCtrl::GetMarginSensitive(int margin) {
+    return SendMsg(SCI_GETMARGINSENSITIVEN, margin);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Selection and Caret styles
+
+
+void wxStyledTextCtrl::SetSelectionForeground(const wxColour& colour) {
+    SendMsg(SCI_SETSELFORE, 0, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::SetSelectionBackground(const wxColour& colour) {
+    SendMsg(SCI_SETSELBACK, 0, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::SetCaretForeground(const wxColour& colour) {
+    SendMsg(SCI_SETCARETFORE, 0, wxColourAsLong(colour));
+}
+
+
+int wxStyledTextCtrl::GetCaretPeriod() {
+    return SendMsg(SCI_GETCARETPERIOD);
+}
+
+
+void wxStyledTextCtrl::SetCaretPeriod(int milliseconds) {
+    SendMsg(SCI_SETCARETPERIOD, milliseconds);
+}
+
+
+
+//----------------------------------------------------------------------
+// Other settings
+
+
+void wxStyledTextCtrl::SetBufferedDraw(bool isBuffered) {
+    SendMsg(SCI_SETBUFFEREDDRAW, isBuffered);
+}
+
+
+void wxStyledTextCtrl::SetTabWidth(int numChars) {
+    SendMsg(SCI_SETTABWIDTH, numChars);
+}
+
+
+void wxStyledTextCtrl::SetWordChars(const wxString& wordChars) {
+    SendMsg(SCI_SETTABWIDTH, 0, (long)wordChars.c_str());
+}
+
+
+//----------------------------------------------------------------------
+// Brace highlighting
+
+
+void wxStyledTextCtrl::BraceHighlight(int pos1, int pos2) {
+    SendMsg(SCI_BRACEHIGHLIGHT, pos1, pos2);
+}
+
+
+void wxStyledTextCtrl::BraceBadlight(int pos) {
+    SendMsg(SCI_BRACEBADLIGHT, pos);
+}
+
+
+int wxStyledTextCtrl::BraceMatch(int pos, int maxReStyle) {
+    return SendMsg(SCI_BRACEMATCH, pos, maxReStyle);
+}
+
+
+
+//----------------------------------------------------------------------
+// Markers
+
+void wxStyledTextCtrl::MarkerDefine(int markerNumber, int markerSymbol,
+                                          const wxColour& foreground,
+                                          const wxColour& background) {
+    MarkerSetType(markerNumber, markerSymbol);
+    MarkerSetForeground(markerNumber, foreground);
+    MarkerSetBackground(markerNumber, background);
+}
+
+
+void wxStyledTextCtrl::MarkerSetType(int markerNumber, int markerSymbol) {
+    SendMsg(SCI_MARKERDEFINE, markerNumber, markerSymbol);
+}
+
+
+void wxStyledTextCtrl::MarkerSetForeground(int markerNumber, const wxColour& colour) {
+    SendMsg(SCI_MARKERSETFORE, markerNumber, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::MarkerSetBackground(int markerNumber, const wxColour& colour) {
+    SendMsg(SCI_MARKERSETBACK, markerNumber, wxColourAsLong(colour));
+}
+
+
+int wxStyledTextCtrl::MarkerAdd(int line, int markerNumber) {
+    return SendMsg(SCI_MARKERADD, line, markerNumber);
+}
+
+
+void wxStyledTextCtrl::MarkerDelete(int line, int markerNumber) {
+    SendMsg(SCI_MARKERDELETE, line, markerNumber);
+}
+
+
+void wxStyledTextCtrl::MarkerDeleteAll(int markerNumber) {
+    SendMsg(SCI_MARKERDELETEALL, markerNumber);
+}
+
+
+int wxStyledTextCtrl::MarkerGet(int line) {
+    return SendMsg(SCI_MARKERGET);
+}
+
+
+int wxStyledTextCtrl::MarkerGetNextLine(int lineStart, int markerMask) {
+    return SendMsg(SCI_MARKERNEXT, lineStart, markerMask);
+}
+
+
+int wxStyledTextCtrl::MarkerGetPrevLine(int lineStart, int markerMask) {
+//    return SendMsg(SCI_MARKERPREV, lineStart, markerMask);
+    return 0;
+}
+
+
+int wxStyledTextCtrl::MarkerLineFromHandle(int handle) {
+    return SendMsg(SCI_MARKERLINEFROMHANDLE, handle);
+}
+
+
+void wxStyledTextCtrl::MarkerDeleteHandle(int handle) {
+    SendMsg(SCI_MARKERDELETEHANDLE, handle);
+}
+
+
+
+//----------------------------------------------------------------------
+// Indicators
+
+
+void wxStyledTextCtrl::IndicatorSetStyle(int indicNum, int indicStyle) {
+    SendMsg(SCI_INDICSETSTYLE, indicNum, indicStyle);
+}
+
+
+int wxStyledTextCtrl::IndicatorGetStyle(int indicNum) {
+    return SendMsg(SCI_INDICGETSTYLE, indicNum);
+}
+
+
+void wxStyledTextCtrl::IndicatorSetColour(int indicNum, const wxColour& colour) {
+    SendMsg(SCI_INDICSETSTYLE, indicNum, wxColourAsLong(colour));
+}
+
+
+
+//----------------------------------------------------------------------
+// Auto completion
+
+
+void wxStyledTextCtrl::AutoCompShow(const wxString& listOfWords) {
+    SendMsg(SCI_AUTOCSHOW, 0, (long)listOfWords.c_str());
+}
+
+
+void wxStyledTextCtrl::AutoCompCancel() {
+    SendMsg(SCI_AUTOCCANCEL);
+}
+
+
+bool wxStyledTextCtrl::AutoCompActive() {
+    return SendMsg(SCI_AUTOCACTIVE) != 0;
+}
+
+
+int wxStyledTextCtrl::AutoCompPosAtStart() {
+    return SendMsg(SCI_AUTOCPOSSTART);
+}
+
+
+void wxStyledTextCtrl::AutoCompComplete() {
+    SendMsg(SCI_AUTOCCOMPLETE);
+}
+
+
+void wxStyledTextCtrl::AutoCompStopChars(const wxString& stopChars) {
+    SendMsg(SCI_AUTOCSHOW, 0, (long)stopChars.c_str());
+}
+
+
+//----------------------------------------------------------------------
+// Call tips
+
+void wxStyledTextCtrl::CallTipShow(int pos, const wxString& text) {
+    SendMsg(SCI_CALLTIPSHOW, pos, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::CallTipCancel() {
+    SendMsg(SCI_CALLTIPCANCEL);
+}
+
+
+bool wxStyledTextCtrl::CallTipActive() {
+    return SendMsg(SCI_CALLTIPACTIVE) != 0;
+}
+
+
+int wxStyledTextCtrl::CallTipPosAtStart() {
+    return SendMsg(SCI_CALLTIPPOSSTART);
+}
+
+
+void wxStyledTextCtrl::CallTipSetHighlight(int start, int end) {
+    SendMsg(SCI_CALLTIPSETHLT, start, end);
+}
+
+
+void wxStyledTextCtrl::CallTipSetBackground(const wxColour& colour) {
+    SendMsg(SCI_CALLTIPSETBACK, wxColourAsLong(colour));
+}
+
+
+//----------------------------------------------------------------------
+// Key bindings
+
+void wxStyledTextCtrl::CmdKeyAssign(int key, int modifiers, int cmd) {
+    SendMsg(SCI_ASSIGNCMDKEY, MAKELONG(key, modifiers), cmd);
+}
+
+
+void wxStyledTextCtrl::CmdKeyClear(int key, int modifiers) {
+    SendMsg(SCI_CLEARCMDKEY, MAKELONG(key, modifiers));
+}
+
+
+void wxStyledTextCtrl::CmdKeyClearAll() {
+    SendMsg(SCI_CLEARALLCMDKEYS);
+}
+
+
+void wxStyledTextCtrl::CmdKeyExecute(int cmd) {
+    SendMsg(cmd);
+}
+
+
+
+//----------------------------------------------------------------------
+// Print formatting
+
+int
+wxStyledTextCtrl::FormatRange(bool   doDraw,
+                                    int    startPos,
+                                    int    endPos,
+                                    wxDC*  draw,
+                                    wxDC*  target,  // Why does it use two? Can they be the same?
+                                    wxRect renderRect,
+                                    wxRect pageRect) {
+    FORMATRANGE fr;
+
+    fr.hdc = draw;
+    fr.hdcTarget = target;
+    fr.rc.top = renderRect.GetTop();
+    fr.rc.left = renderRect.GetLeft();
+    fr.rc.right = renderRect.GetRight();
+    fr.rc.bottom = renderRect.GetBottom();
+    fr.rcPage.top = pageRect.GetTop();
+    fr.rcPage.left = pageRect.GetLeft();
+    fr.rcPage.right = pageRect.GetRight();
+    fr.rcPage.bottom = pageRect.GetBottom();
+    fr.chrg.cpMin = startPos;
+    fr.chrg.cpMax = endPos;
+
+    return SendMsg(EM_FORMATRANGE, doDraw, (long)&fr);
+}
+
+
+//----------------------------------------------------------------------
+// Document Sharing
+
+void* wxStyledTextCtrl::GetDocument() {
+    return (void*)SendMsg(SCI_GETDOCPOINTER);
+}
+
+
+void wxStyledTextCtrl::SetDocument(void* document) {
+    SendMsg(SCI_SETDOCPOINTER, 0, (long)document);
+}
+
+
+//----------------------------------------------------------------------
+// Long Lines
+
+int wxStyledTextCtrl::GetEdgeColumn() {
+    return SendMsg(SCI_GETEDGECOLUMN);
+}
+
+void wxStyledTextCtrl::SetEdgeColumn(int column) {
+    SendMsg(SCI_SETEDGECOLUMN, column);
+}
+
+wxSTC_EDGE wxStyledTextCtrl::GetEdgeMode() {
+    return (wxSTC_EDGE) SendMsg(SCI_GETEDGEMODE);
+}
+
+void wxStyledTextCtrl::SetEdgeMode(wxSTC_EDGE mode){
+    SendMsg(SCI_SETEDGEMODE, mode);
+}
+
+wxColour wxStyledTextCtrl::GetEdgeColour() {
+    long c = SendMsg(SCI_GETEDGECOLOUR);
+    return wxColourFromLong(c);
+}
+
+void wxStyledTextCtrl::SetEdgeColour(const wxColour& colour) {
+    SendMsg(SCI_SETEDGECOLOUR, wxColourAsLong(colour));
+}
+
+
+//----------------------------------------------------------------------
+// Lexer
+
+void     wxStyledTextCtrl::SetLexer(wxSTC_LEX lexer) {
+    SendMsg(SCI_SETLEXER, lexer);
+}
+
+
+wxSTC_LEX wxStyledTextCtrl::GetLexer() {
+    return (wxSTC_LEX)SendMsg(SCI_GETLEXER);
+}
+
+
+void     wxStyledTextCtrl::Colourise(int start, int end) {
+    SendMsg(SCI_COLOURISE, start, end);
+}
+
+
+void     wxStyledTextCtrl::SetProperty(const wxString& key, const wxString& value) {
+    SendMsg(SCI_SETPROPERTY, (long)key.c_str(), (long)value.c_str());
+}
+
+
+void     wxStyledTextCtrl::SetKeywords(int keywordSet, const wxString& keywordList) {
+    SendMsg(SCI_SETKEYWORDS, keywordSet, (long)keywordList.c_str());
+}
+
+
+
+//----------------------------------------------------------------------
+// Event handlers
+
+void wxStyledTextCtrl::OnPaint(wxPaintEvent& evt) {
+    wxPaintDC dc(this);
+    wxRegion  region = GetUpdateRegion();
+
+    m_swx->DoPaint(&dc, region.GetBox());
+}
+
+void wxStyledTextCtrl::OnScrollWin(wxScrollWinEvent& evt) {
+    if (evt.GetOrientation() == wxHORIZONTAL)
+        m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
+    else
+        m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
+}
+
+void wxStyledTextCtrl::OnSize(wxSizeEvent& evt) {
+    wxSize sz = GetClientSize();
+    m_swx->DoSize(sz.x, sz.y);
+}
+
+void wxStyledTextCtrl::OnMouseLeftDown(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonDown(Point(pt.x, pt.y), m_stopWatch.Time(),
+                      evt.ShiftDown(), evt.ControlDown(), evt.AltDown());
+}
+
+void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonMove(Point(pt.x, pt.y));
+}
+
+void wxStyledTextCtrl::OnMouseLeftUp(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonUp(Point(pt.x, pt.y), m_stopWatch.Time(),
+                      evt.ControlDown());
+}
+
+
+void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoContextMenu(Point(pt.x, pt.y));
+}
+
+void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) {
+    int  processed = 0;
+    long key = evt.KeyCode();
+    if ((key > WXK_ESCAPE) &&
+        (key != WXK_DELETE) && (key < 255) &&
+        !evt.ControlDown() && !evt.AltDown()) {
+
+        m_swx->DoAddChar(key);
+        processed = true;
+    }
+    else {
+        key = toupper(key);
+        processed = m_swx->DoKeyDown(key, evt.ShiftDown(),
+                                     evt.ControlDown(), evt.AltDown());
+    }
+    if (! processed)
+        evt.Skip();
+}
+
+void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) {
+    m_swx->DoLoseFocus();
+}
+
+void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) {
+    m_swx->DoGainFocus();
+}
+
+void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& evt) {
+    m_swx->DoSysColourChange();
+}
+
+void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& evt) {
+    // do nothing to help avoid flashing
+}
+
+
+
+void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
+    m_swx->DoCommand(evt.GetId());
+}
+
+
+//----------------------------------------------------------------------
+// Turn notifications from Scintilla into events
+
+void wxStyledTextCtrl::NotifyChange() {
+    wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
+    GetEventHandler()->ProcessEvent(evt);
+}
+
+void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
+    SCNotification& scn = *_scn;
+    int eventType = 0;
+    switch (scn.nmhdr.code) {
+    case SCN_STYLENEEDED:
+        eventType = wxEVT_STC_STYLENEEDED;
+        break;
+    case SCN_CHARADDED:
+        eventType = wxEVT_STC_CHARADDED;
+        break;
+    case SCN_UPDATEUI:
+        eventType = wxEVT_STC_UPDATEUI;
+        break;
+    case SCN_SAVEPOINTREACHED:
+        eventType = wxEVT_STC_SAVEPOINTREACHED;
+        break;
+    case SCN_SAVEPOINTLEFT:
+        eventType = wxEVT_STC_SAVEPOINTLEFT;
+        break;
+    case SCN_MODIFYATTEMPTRO:
+        eventType = wxEVT_STC_ROMODIFYATTEMPT;
+        break;
+    case SCN_DOUBLECLICK:
+        eventType = wxEVT_STC_DOUBLECLICK;
+        break;
+    case SCN_MODIFIED:
+        eventType = wxEVT_STC_MODIFIED;
+        break;
+    case SCN_KEY:
+        eventType = wxEVT_STC_KEY;
+        break;
+    case SCN_MACRORECORD:
+        eventType = wxEVT_STC_MACRORECORD;
+        break;
+    case SCN_MARGINCLICK:
+        eventType = wxEVT_STC_MARGINCLICK;
+        break;
+    case SCN_NEEDSHOWN:
+        eventType = wxEVT_STC_NEEDSHOWN;
+        break;
+    }
+    if (eventType) {
+        wxStyledTextEvent evt(eventType, GetId());
+        evt.SetPosition(scn.position);
+        evt.SetKey(scn.ch);
+        evt.SetModifiers(scn.modifiers);
+        if (eventType == wxEVT_STC_MODIFIED) {
+            evt.SetModificationType(scn.modificationType);
+            evt.SetText(scn.text);
+            evt.SetLength(scn.length);
+            evt.SetLinesAdded(scn.linesAdded);
+            evt.SetLine(scn.line);
+            evt.SetFoldLevelNow(scn.foldLevelNow);
+            evt.SetFoldLevelPrev(scn.foldLevelPrev);
+        }
+        if (eventType == wxEVT_STC_MARGINCLICK)
+            evt.SetMargin(scn.margin);
+        if (eventType == wxEVT_STC_MACRORECORD) {
+            evt.SetMessage(scn.message);
+            evt.SetWParam(scn.wParam);
+            evt.SetLParam(scn.lParam);
+        }
+
+        GetEventHandler()->ProcessEvent(evt);
+    }
+}
+
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+
+wxStyledTextEvent::wxStyledTextEvent(wxEventType commandType, int id)
+    : wxCommandEvent(commandType, id)
+{
+    m_position = 0;
+    m_key = 0;
+    m_modifiers = 0;
+    m_modificationType = 0;
+    m_length = 0;
+    m_linesAdded = 0;
+    m_line = 0;
+    m_foldLevelNow = 0;
+    m_foldLevelPrev = 0;
+    m_margin = 0;
+    m_message = 0;
+    m_wParam = 0;
+    m_lParam = 0;
+
+
+}
+
+bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; }
+bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; }
+bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; }
+
+void wxStyledTextEvent::CopyObject(wxObject& obj) const {
+    wxCommandEvent::CopyObject(obj);
+
+    wxStyledTextEvent* o = (wxStyledTextEvent*)&obj;
+    o->m_position =      m_position;
+    o->m_key =           m_key;
+    o->m_modifiers =     m_modifiers;
+    o->m_modificationType = m_modificationType;
+    o->m_text =          m_text;
+    o->m_length =        m_length;
+    o->m_linesAdded =    m_linesAdded;
+    o->m_line =          m_line;
+    o->m_foldLevelNow =  m_foldLevelNow;
+    o->m_foldLevelPrev = m_foldLevelPrev;
+
+    o->m_margin =        m_margin;
+
+    o->m_message =       m_message;
+    o->m_wParam =        m_wParam;
+    o->m_lParam =        m_lParam;
+
+
+
+}
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+
diff --git a/include/wx/stc/stc.h b/include/wx/stc/stc.h
new file mode 100644 (file)
index 0000000..4920f70
--- /dev/null
@@ -0,0 +1,547 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        stc.h
+// Purpose:     A wxWindows implementation of Scintilla.  This class is the
+//              one meant to be used directly by wx applications.  It does not
+//              derive directly from the Scintilla classes, and in fact there
+//              is no mention of Scintilla classes at all in this header.
+//              This class delegates all method calls and events to the
+//              Scintilla objects and so forth.  This allows the use of
+//              Scintilla without polluting the namespace with all the
+//              classes and itentifiers from Scintilla.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __stc_h__
+#define __stc_h__
+
+
+#include <wx/wx.h>
+
+
+//----------------------------------------------------------------------
+// constants and stuff
+
+enum wxSTC_UndoType {
+    wxSTC_UndoCollectNone,
+    wxSTC_UndoCollectAutoStart
+};
+
+
+enum wxSTC_EOL {
+    wxSTC_EOL_CRLF,
+    wxSTC_EOL_CR,
+    wxSTC_EOL_LF
+};
+
+enum wxSTC_EDGE {
+    wxSTC_EDGE_NONE,
+    wxSTC_EDGE_LINE,
+    wxSTC_EDGE_BACKGROUND
+};
+
+
+
+const int wxSTC_LEX_STYLE_MAX     = 31;
+const int wxSTC_STYLE_DEFAULT     = 32;
+const int wxSTC_STYLE_LINENUMBER  = 33;
+const int wxSTC_STYLE_BRACELIGHT  = 34;
+const int wxSTC_STYLE_BRACEBAD    = 35;
+const int wxSTC_STYLE_CONTROLCHAR = 36;
+const int wxSTC_STYLE_MAX         = 63;
+const int wxSTC_STYLE_MASK        = 31;
+
+const int wxSTC_MARKER_MAX        = 31;
+const int wxSTC_MARK_CIRCLE       = 0;
+const int wxSTC_MARK_ROUNDRECT    = 1;
+const int wxSTC_MARK_ARROW        = 2;
+const int wxSTC_MARK_SMALLRECT    = 3;
+const int wxSTC_MARK_SHORTARROW   = 4;
+const int wxSTC_MARK_EMPTY        = 5;
+
+const int wxSTC_INDIC_PLAIN       = 0;
+const int wxSTC_INDIC_SQUIGGLE    = 1;
+const int wxSTC_INDIC_TT          = 2;
+const int wxSTC_INDIC0_MASK       = 32;
+const int wxSTC_INDIC1_MASK       = 64;
+const int wxSTC_INDIC2_MASK       = 128;
+const int wxSTC_INDICS_MASK       = (wxSTC_INDIC0_MASK | wxSTC_INDIC1_MASK | wxSTC_INDIC2_MASK);
+
+
+// key commands
+enum {
+    wxSTC_CMD_LINEDOWN = 2300,
+    wxSTC_CMD_LINEDOWNEXTEND,
+    wxSTC_CMD_LINEUP,
+    wxSTC_CMD_LINEUPEXTEND,
+    wxSTC_CMD_CHARLEFT,
+    wxSTC_CMD_CHARLEFTEXTEND,
+    wxSTC_CMD_CHARRIGHT,
+    wxSTC_CMD_CHARRIGHTEXTEND,
+    wxSTC_CMD_WORDLEFT,
+    wxSTC_CMD_WORDLEFTEXTEND,
+    wxSTC_CMD_WORDRIGHT,
+    wxSTC_CMD_WORDRIGHTEXTEND,
+    wxSTC_CMD_HOME,
+    wxSTC_CMD_HOMEEXTEND,
+    wxSTC_CMD_LINEEND,
+    wxSTC_CMD_LINEENDEXTEND,
+    wxSTC_CMD_DOCUMENTSTART,
+    wxSTC_CMD_DOCUMENTSTARTEXTEND,
+    wxSTC_CMD_DOCUMENTEND,
+    wxSTC_CMD_DOCUMENTENDEXTEND,
+    wxSTC_CMD_PAGEUP,
+    wxSTC_CMD_PAGEUPEXTEND,
+    wxSTC_CMD_PAGEDOWN,
+    wxSTC_CMD_PAGEDOWNEXTEND,
+    wxSTC_CMD_EDITTOGGLEOVERTYPE,
+    wxSTC_CMD_CANCEL,
+    wxSTC_CMD_DELETEBACK,
+    wxSTC_CMD_TAB,
+    wxSTC_CMD_BACKTAB,
+    wxSTC_CMD_NEWLINE,
+    wxSTC_CMD_FORMFEED,
+    wxSTC_CMD_VCHOME,
+    wxSTC_CMD_VCHOMEEXTEND,
+    wxSTC_CMD_ZOOMIN,
+    wxSTC_CMD_ZOOMOUT,
+    wxSTC_CMD_DELWORDLEFT,
+    wxSTC_CMD_DELWORDRIGHT
+};
+
+
+enum wxSTC_LEX {
+    wxSTC_LEX_CONTAINER=0,
+    wxSTC_LEX_NULL,
+    wxSTC_LEX_PYTHON,
+    wxSTC_LEX_CPP,
+    wxSTC_LEX_HTML,
+    wxSTC_LEX_XML,
+    wxSTC_LEX_PERL,
+    wxSTC_LEX_SQL,
+    wxSTC_LEX_VB,
+    wxSTC_LEX_PROPERTIES,
+    wxSTC_LEX_ERRORLIST,
+    wxSTC_LEX_MAKEFILE,
+    wxSTC_LEX_BATCH,
+};
+
+
+
+const int wxSTC_CARET_SLOP    = 0x01;
+const int WXSTC_CARET_CENTER  = 0x02;
+const int wxSTC_CARET_STRICT  = 0x04;
+
+const int wxSTC_MARGIN_SYMBOL = 0;
+const int wxSTC_MARGIN_NUMBER = 1;
+
+
+class  ScintillaWX;                      // forward declare
+class  WordList;
+struct SCNotification;
+
+
+extern const wxChar* wxSTCNameStr;
+
+//----------------------------------------------------------------------
+
+class wxStyledTextCtrl : public wxControl {
+public:
+
+    wxStyledTextCtrl(wxWindow *parent, wxWindowID id,
+                     const wxPoint& pos = wxDefaultPosition,
+                     const wxSize& size = wxDefaultSize, long style = 0,
+                     const wxString& name = wxSTCNameStr);
+    ~wxStyledTextCtrl();
+
+
+
+    // Text retrieval and modification
+    wxString GetText();
+    bool     SetText(const wxString& text);
+    wxString GetLine(int line);
+    void     ReplaceSelection(const wxString& text);
+    void     SetReadOnly(bool readOnly);
+    bool     GetReadOnly();
+    wxString GetTextRange(int startPos, int endPos);
+    wxString GetStyledTextRange(int startPos, int endPos);
+    void     GetTextRange(int startPos, int endPos, char* buff);
+    void     GetStyledTextRange(int startPos, int endPos, char* buff);
+    void     AddText(const wxString& text);
+    void     AddStyledText(const wxString& text);
+    void     InsertText(int pos, const wxString& text);
+    void     ClearAll();
+    char     GetCharAt(int pos);
+    char     GetStyleAt(int pos);
+    void     SetStyleBits(int bits);
+    int      GetStyleBits();
+
+
+    // Clipboard
+    void     Cut();
+    void     Copy();
+    void     Paste();
+    bool     CanPaste();
+    void     ClearClipbrd();  // avoiding name conflict with virtual in wxWindow
+
+
+    // Undo and Redo
+    void     Undo();
+    bool     CanUndo();
+    void     EmptyUndoBuffer();
+    void     Redo();
+    bool     CanRedo();
+    void     SetUndoCollection(wxSTC_UndoType type);
+    wxSTC_UndoType GetUndoCollection();
+    void     BeginUndoAction();
+    void     EndUndoAction();
+
+
+    // Selection and information
+    void     GetSelection(int* startPos, int* endPos);
+    void     SetSelection(int  startPos, int  endPos);
+    wxString GetSelectedText();
+    void     HideSelection(bool hide);
+    bool     GetHideSelection();
+
+    int      GetTextLength();
+    int      GetFirstVisibleLine();
+    bool     GetModified();
+    int      GetLineCount();
+    wxRect   GetRect();
+    int      GetLineFromPos(int pos);
+    int      GetLineStartPos(int line);
+    int      GetLineLengthAtPos(int pos);
+    int      GetLineLength(int line);
+    wxString GetCurrentLineText(int* linePos=NULL);
+    int      GetCurrentLine();
+    int      PositionFromPoint(wxPoint pt);
+    int      LineFromPoint(wxPoint pt);
+    wxPoint  PointFromPosition(int pos);
+    int      GetCurrentPos();
+    int      GetAnchor();
+    void     SelectAll();
+    void     SetCurrentPosition(int pos);
+    void     SetAnchor(int pos);
+    void     GotoPos(int pos);
+    void     GotoLine(int line);
+    void     ChangePosition(int delta, bool extendSelection);
+    void     PageMove(int cmdKey, bool extendSelection);
+
+    void     ScrollBy(int columnDelta, int lineDelta);
+    void     ScrollToLine(int line);
+    void     ScrollToColumn(int column);
+    void     EnsureCaretVisible();
+    void     SetCaretPolicy(int policy, int slop=0);
+    int      GetSelectionType();
+
+
+
+    // Searching
+    int      FindText(int minPos, int maxPos, const wxString& text,
+                      bool caseSensitive, bool wholeWord);
+    void     SearchAnchor();
+    int      SearchNext(const wxString& text, bool caseSensitive, bool wholeWord);
+    int      SearchPrev(const wxString& text, bool caseSensitive, bool wholeWord);
+
+
+    // Visible whitespace
+    bool     GetViewWhitespace();
+    void     SetViewWhitespace(bool visible);
+
+
+    // Line endings
+    wxSTC_EOL GetEOLMode();
+    void     SetEOLMode(wxSTC_EOL mode);
+    bool     GetViewEOL();
+    void     SetViewEOL(bool visible);
+    void     ConvertEOL(wxSTC_EOL mode);
+
+
+    // Styling
+    int      GetEndStyled();
+    void     StartStyling(int pos, int mask);
+    void     SetStyleFor(int length, int style);
+    void     SetStyleBytes(int length, char* styleBytes);
+
+
+    // Style Definition
+    void     StyleClearAll();
+    void     StyleResetDefault();
+    void     StyleSetSpec(int styleNum, const wxString& spec);
+    void     StyleSetForeground(int styleNum, const wxColour& colour);
+    void     StyleSetBackground(int styleNum, const wxColour& colour);
+    void     StyleSetFont(int styleNum, wxFont& font);
+    void     StyleSetFontAttr(int styleNum, int size, const wxString& faceName, bool bold, bool italic);
+    void     StyleSetBold(int styleNum, bool bold);
+    void     StyleSetItalic(int styleNum, bool italic);
+    void     StyleSetFaceName(int styleNum, const wxString& faceName);
+    void     StyleSetSize(int styleNum, int pointSize);
+    void     StyleSetEOLFilled(int styleNum, bool fillEOL);
+
+
+    // Margins in the edit area
+    int      GetLeftMargin();
+    int      GetRightMargin();
+    void     SetMargins(int left, int right);
+
+
+    // Margins for selection, markers, etc.
+    void SetMarginType(int margin, int type);
+    int  GetMarginType(int margin);
+    void SetMarginWidth(int margin, int pixelWidth);
+    int  GetMarginWidth(int margin);
+    void SetMarginMask(int margin, int mask);
+    int  GetMarginMask(int margin);
+    void SetMarginSensitive(int margin, bool sensitive);
+    bool GetMarginSensitive(int margin);
+
+
+    // Selection and Caret styles
+    void     SetSelectionForeground(const wxColour& colour);
+    void     SetSelectionBackground(const wxColour& colour);
+    void     SetCaretForeground(const wxColour& colour);
+    int      GetCaretPeriod();
+    void     SetCaretPeriod(int milliseconds);
+
+
+    // Other settings
+    void     SetBufferedDraw(bool isBuffered);
+    void     SetTabWidth(int numChars);
+    void     SetWordChars(const wxString& wordChars);
+
+
+    // Brace highlighting
+    void     BraceHighlight(int pos1, int pos2);
+    void     BraceBadlight(int pos);
+    int      BraceMatch(int pos, int maxReStyle=0);
+
+
+    // Markers
+    void     MarkerDefine(int markerNumber, int markerSymbol,
+                          const wxColour& foreground,
+                          const wxColour& background);
+    void     MarkerSetType(int markerNumber, int markerSymbol);
+    void     MarkerSetForeground(int markerNumber, const wxColour& colour);
+    void     MarkerSetBackground(int markerNumber, const wxColour& colour);
+    int      MarkerAdd(int line, int markerNumber);
+    void     MarkerDelete(int line, int markerNumber);
+    void     MarkerDeleteAll(int markerNumber);
+    int      MarkerGet(int line);
+    int      MarkerGetNextLine(int lineStart, int markerMask);
+    int      MarkerGetPrevLine(int lineStart, int markerMask);
+    int      MarkerLineFromHandle(int handle);
+    void     MarkerDeleteHandle(int handle);
+
+
+    // Indicators
+    void     IndicatorSetStyle(int indicNum, int indicStyle);
+    int      IndicatorGetStyle(int indicNum);
+    void     IndicatorSetColour(int indicNum, const wxColour& colour);
+
+
+    // Auto completion
+    void     AutoCompShow(const wxString& listOfWords);
+    void     AutoCompCancel();
+    bool     AutoCompActive();
+    int      AutoCompPosAtStart();
+    void     AutoCompComplete();
+    void     AutoCompStopChars(const wxString& stopChars);
+
+
+    // Call tips
+    void     CallTipShow(int pos, const wxString& text);
+    void     CallTipCancel();
+    bool     CallTipActive();
+    int      CallTipPosAtStart();
+    void     CallTipSetHighlight(int start, int end);
+    void     CallTipSetBackground(const wxColour& colour);
+
+
+    // Key bindings
+    void     CmdKeyAssign(int key, int modifiers, int cmd);
+    void     CmdKeyClear(int key, int modifiers);
+    void     CmdKeyClearAll();
+    void     CmdKeyExecute(int cmd);
+
+
+    // Print formatting
+    int      FormatRange(bool   doDraw,
+                         int    startPos,
+                         int    endPos,
+                         wxDC*  draw,
+                         wxDC*  target,  // Why does it use two? Can they be the same?
+                         wxRect renderRect,
+                         wxRect pageRect);
+
+
+    // Document Sharing (multiple views)
+    void*    GetDocument();
+    void     SetDocument(void* document);
+    // TODO: create a wx wrapper for Scintilla's document class
+
+
+    // TODO: Folding
+
+
+    // Long Lines
+    int      GetEdgeColumn();
+    void     SetEdgeColumn(int column);
+    wxSTC_EDGE GetEdgeMode();
+    void     SetEdgeMode(wxSTC_EDGE mode);
+    wxColour GetEdgeColour();
+    void     SetEdgeColour(const wxColour& colour);
+
+
+    // Lexer
+    void     SetLexer(wxSTC_LEX lexer);
+    wxSTC_LEX GetLexer();
+    void     Colourise(int start, int end);
+    void     SetProperty(const wxString& key, const wxString& value);
+    void     SetKeywords(int keywordSet, const wxString& keywordList);
+
+
+
+private:
+    // Event handlers
+    void OnPaint(wxPaintEvent& evt);
+    void OnScrollWin(wxScrollWinEvent& evt);
+    void OnSize(wxSizeEvent& evt);
+    void OnMouseLeftDown(wxMouseEvent& evt);
+    void OnMouseMove(wxMouseEvent& evt);
+    void OnMouseLeftUp(wxMouseEvent& evt);
+    void OnMouseRightUp(wxMouseEvent& evt);
+    void OnChar(wxKeyEvent& evt);
+    void OnLoseFocus(wxFocusEvent& evt);
+    void OnGainFocus(wxFocusEvent& evt);
+    void OnSysColourChanged(wxSysColourChangedEvent& evt);
+    void OnEraseBackground(wxEraseEvent& evt);
+    void OnMenu(wxCommandEvent& evt);
+
+
+    // Turn notifications from Scintilla into events
+    void NotifyChange();
+    void NotifyParent(SCNotification* scn);
+
+    long SendMsg(int msg, long wp=0, long lp=0);
+
+private:
+    DECLARE_EVENT_TABLE()
+
+    ScintillaWX*        m_swx;
+    wxStopWatch         m_stopWatch;
+    bool                m_readOnly;
+    wxSTC_UndoType      m_undoType;
+
+
+    friend class ScintillaWX;
+    friend class Platform;
+};
+
+//----------------------------------------------------------------------
+
+class wxStyledTextEvent : public wxCommandEvent {
+public:
+    wxStyledTextEvent(wxEventType commandType, int id);
+    ~wxStyledTextEvent() {}
+
+    void SetPosition(int pos)        { m_position = pos; }
+    void SetKey(int k)               { m_key = k; }
+    void SetModifiers(int m)         { m_modifiers = m; }
+    void SetModificationType(int t)  { m_modificationType = t; }
+    void SetText(const char* t)      { m_text = t; }
+    void SetLength(int len)          { m_length = len; }
+    void SetLinesAdded(int num)      { m_linesAdded = num; }
+    void SetLine(int val)            { m_line = val; }
+    void SetFoldLevelNow(int val)    { m_foldLevelNow = val; }
+    void SetFoldLevelPrev(int val)   { m_foldLevelPrev = val; }
+    void SetMargin(int val)          { m_margin = val; }
+    void SetMessage(int val)         { m_message = val; }
+    void SetWParam(int val)          { m_wParam = val; }
+    void SetLParam(int val)          { m_lParam = val; }
+
+    int  GetPosition() const         { return m_position; }
+    int  GetKey()  const             { return m_key; }
+    int  GetModifiers() const        { return m_modifiers; }
+    int  GetModificationType() const { return m_modificationType; }
+    wxString GetText() const         { return m_text; }
+    int  GetLength() const           { return m_length; }
+    int  GetLinesAdded() const       { return m_linesAdded; }
+    int  GetLine() const             { return m_line; }
+    int  GetFoldLevelNow() const     { return m_foldLevelNow; }
+    int  GetFoldLevelPrev() const    { return m_foldLevelPrev; }
+    int  GetMargin() const           { return m_margin; }
+    int  GetMessage() const          { return m_message; }
+    int  GetWParam() const           { return m_wParam; }
+    int  GetLParam() const           { return m_lParam; }
+
+    bool GetShift() const;
+    bool GetControl() const;
+    bool GetAlt() const;
+
+    void CopyObject(wxObject& obj) const;
+
+private:
+    int  m_position;
+    int  m_key;
+    int  m_modifiers;
+
+    int  m_modificationType;    // wxEVT_STC_MODIFIED
+    wxString m_text;
+    int  m_length;
+    int  m_linesAdded;
+    int  m_line;
+    int  m_foldLevelNow;
+    int  m_foldLevelPrev;
+
+    int  m_margin;              // wxEVT_STC_MARGINCLICK
+
+    int  m_message;             // wxEVT_STC_MACRORECORD
+    int  m_wParam;
+    int  m_lParam;
+
+};
+
+
+
+enum {
+    wxEVT_STC_CHANGE = 1650,
+    wxEVT_STC_STYLENEEDED,
+    wxEVT_STC_CHARADDED,
+    wxEVT_STC_UPDATEUI,
+    wxEVT_STC_SAVEPOINTREACHED,
+    wxEVT_STC_SAVEPOINTLEFT,
+    wxEVT_STC_ROMODIFYATTEMPT,
+    wxEVT_STC_DOUBLECLICK,
+    wxEVT_STC_MODIFIED,
+    wxEVT_STC_KEY,
+    wxEVT_STC_MACRORECORD,
+    wxEVT_STC_MARGINCLICK,
+    wxEVT_STC_NEEDSHOWN
+};
+
+typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
+
+#define EVT_STC_CHANGE(id, fn) { wxEVT_STC_CHANGE, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_STYLENEEDED(id, fn) { wxEVT_STC_STYLENEEDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_CHARADDED(id, fn) { wxEVT_STC_CHARADDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_UPDATEUI(id, fn) { wxEVT_STC_UPDATEUI, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_SAVEPOINTREACHED(id, fn) { wxEVT_STC_SAVEPOINTREACHED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_SAVEPOINTLEFT(id, fn) { wxEVT_STC_SAVEPOINTLEFT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_ROMODIFYATTEMPT(id, fn) { wxEVT_STC_ROMODIFYATTEMPT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_DOUBLECLICK(id, fn) { wxEVT_STC_DOUBLECLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_MODIFIED(id, fn) { wxEVT_STC_MODIFIED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_CMDKEY(id, fn) { wxEVT_STC_CMDKEY, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+#define EVT_STC_UNKNOWNCMDKEY(id, fn) { wxEVT_STC_UNKNOWNCMDKEY, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxStyledTextEventFunction) & fn, (wxObject *) NULL },
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+#endif
+
+
diff --git a/samples/stc/.cvsignore b/samples/stc/.cvsignore
new file mode 100644 (file)
index 0000000..bfe355b
--- /dev/null
@@ -0,0 +1 @@
+stctest.res
diff --git a/samples/stc/makefile.vc b/samples/stc/makefile.vc
new file mode 100644 (file)
index 0000000..956b781
--- /dev/null
@@ -0,0 +1,14 @@
+# File:                makefile.vc  For stectrl
+# Author:      Robin Dunn
+# Created:     1-Feb-2000
+# Updated:
+
+WXDIR = $(WXWIN)
+PROGRAM = stctest
+
+OBJECTS = $(PROGRAM).obj
+EXTRALIBS = $(WXDIR)\contrib\lib\stc$(LIBEXT).lib
+EXTRAINC = -I$(WXDIR)\contrib\include
+
+!include $(WXDIR)\src\makeprog.vc
+
diff --git a/samples/stc/stctest.cpp b/samples/stc/stctest.cpp
new file mode 100644 (file)
index 0000000..fe337aa
--- /dev/null
@@ -0,0 +1,204 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        stctest.cpp
+// Purpose:     sample of using wxStyledTextCtrl
+// Author:      Robin Dunn
+// Modified by:
+// Created:     3-Feb-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+    #pragma implementation "stctest.cpp"
+    #pragma interface "stctest.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+// for all others, include the necessary headers (this file is usually all you
+// need because it includes almost all "standard" wxWindows headers
+#ifndef WX_PRECOMP
+    #include "wx/wx.h"
+#endif
+
+#include <wx/wfstream.h>
+
+#include <wx/stc/stc.h>
+
+//----------------------------------------------------------------------
+
+class MyApp : public wxApp
+{
+public:
+    virtual bool OnInit();
+};
+
+//----------------------------------------------------------------------
+
+// Define a new frame type: this is going to be our main frame
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
+
+    void OnQuit(wxCommandEvent& event);
+    void OnAbout(wxCommandEvent& event);
+    void OnStyleNeeded(wxStyledTextEvent& event);
+
+private:
+    wxStyledTextCtrl* ed;
+
+    DECLARE_EVENT_TABLE()
+};
+
+
+// IDs for the controls and the menu commands
+enum
+{
+    // menu items
+    ID_Quit = 1,
+    ID_About,
+    ID_ED
+};
+
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+    EVT_MENU            (ID_Quit,  MyFrame::OnQuit)
+    EVT_MENU            (ID_About, MyFrame::OnAbout)
+    EVT_STC_STYLENEEDED (ID_ED, MyFrame::OnStyleNeeded)
+END_EVENT_TABLE()
+
+IMPLEMENT_APP(MyApp)
+
+//----------------------------------------------------------------------
+// `Main program' equivalent: the program execution "starts" here
+
+bool MyApp::OnInit()
+{
+    MyFrame *frame = new MyFrame("Testing wxStyledTextCtrl",
+                                 wxPoint(5, 5), wxSize(400, 600));
+
+    frame->Show(TRUE);
+    return TRUE;
+}
+
+//----------------------------------------------------------------------
+
+// frame constructor
+MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
+       : wxFrame((wxFrame *)NULL, -1, title, pos, size)
+{
+#ifdef __WXMAC__
+    // we need this in order to allow the about menu relocation, since ABOUT is
+    // not the default id of the about menu
+    wxApp::s_macAboutMenuItemId = ID_About;
+#endif
+
+
+    // create a menu bar
+    wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF);
+
+    // the "About" item should be in the help menu
+    wxMenu *helpMenu = new wxMenu;
+    helpMenu->Append(ID_About, "&About...\tCtrl-A", "Show about dialog");
+
+    menuFile->Append(ID_Quit, "E&xit\tAlt-X", "Quit this program");
+
+    // now append the freshly created menu to the menu bar...
+    wxMenuBar *menuBar = new wxMenuBar();
+    menuBar->Append(menuFile, "&File");
+    menuBar->Append(helpMenu, "&Help");
+
+    // ... and attach this menu bar to the frame
+    SetMenuBar(menuBar);
+
+#if wxUSE_STATUSBAR
+    CreateStatusBar(2);
+    SetStatusText("Testing wxStyledTextCtrl");
+#endif // wxUSE_STATUSBAR
+
+
+    //----------------------------------------
+    // Setup the editor
+    ed = new wxStyledTextCtrl(this, ID_ED);
+
+    // Default font
+    wxFont font(8, wxMODERN, wxNORMAL, wxNORMAL);
+    ed->StyleSetFont(wxSTC_STYLE_DEFAULT, font);
+    ed->StyleClearAll();
+
+    ed->StyleSetForeground(0,  wxColour(0x80, 0x80, 0x80));
+    ed->StyleSetForeground(1,  wxColour(0x00, 0x7f, 0x00));
+    //ed->StyleSetForeground(2,  wxColour(0x00, 0x7f, 0x00));
+    ed->StyleSetForeground(3,  wxColour(0x7f, 0x7f, 0x7f));
+    ed->StyleSetForeground(4,  wxColour(0x00, 0x7f, 0x7f));
+    ed->StyleSetForeground(5,  wxColour(0x00, 0x00, 0x7f));
+    ed->StyleSetForeground(6,  wxColour(0x7f, 0x00, 0x7f));
+    ed->StyleSetForeground(7,  wxColour(0x7f, 0x00, 0x7f));
+    ed->StyleSetForeground(8,  wxColour(0x00, 0x7f, 0x7f));
+    ed->StyleSetForeground(9,  wxColour(0x7f, 0x7f, 0x7f));
+    ed->StyleSetForeground(10, wxColour(0x00, 0x00, 0x00));
+    ed->StyleSetForeground(11, wxColour(0x00, 0x00, 0x00));
+    ed->StyleSetBold(5,  TRUE);
+    ed->StyleSetBold(10, TRUE);
+
+#ifdef __WXMSW__
+    ed->StyleSetSpec(2, "fore:#007f00,bold,face:Arial,size:7");
+#else
+    ed->StyleSetSpec(2, "fore:#007f00,bold,face:Helvetica,size:7");
+#endif
+
+    // give it some text to play with
+    wxFile   file("stctest.cpp");
+    wxString st;
+
+    char* buff = st.GetWriteBuf(file.Length());
+    file.Read(buff, file.Length());
+    st.UngetWriteBuf();
+
+    ed->InsertText(0, st);
+    ed->EmptyUndoBuffer();
+
+    ed->SetLexer(wxSTC_LEX_CPP);
+    ed->SetKeywords(0,
+                    "asm auto bool break case catch char class const "
+                    "const_cast continue default delete do double "
+                    "dynamic_cast else enum explicit export extern "
+                    "false float for friend goto if inline int long "
+                    "mutable namespace new operator private protected "
+                    "public register reinterpret_cast return short signed "
+                    "sizeof static static_cast struct switch template this "
+                    "throw true try typedef typeid typename union unsigned "
+                    "using virtual void volatile wchar_t while");
+
+}
+
+
+// event handlers
+
+void MyFrame::OnStyleNeeded(wxStyledTextEvent& event) {
+    int currEndStyled = ed->GetEndStyled();
+    ed->Colourise(currEndStyled, event.GetPosition());
+}
+
+
+
+
+void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+    // TRUE is to force the frame to close
+    Close(TRUE);
+}
+
+void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+    wxString msg;
+    msg.Printf( _T("Testing wxStyledTextCtrl...\n"));
+
+    wxMessageBox(msg, "About This Test", wxOK | wxICON_INFORMATION, this);
+}
diff --git a/samples/stc/stctest.rc b/samples/stc/stctest.rc
new file mode 100644 (file)
index 0000000..b86c4e2
--- /dev/null
@@ -0,0 +1 @@
+#include "wx/msw/wx.rc"
diff --git a/src/stc/PlatWX.cpp b/src/stc/PlatWX.cpp
new file mode 100644 (file)
index 0000000..0dbd3d5
--- /dev/null
@@ -0,0 +1,585 @@
+// Scintilla source code edit control
+// PlatWX.cxx - implementation of platform facilities on wxWindows
+// Copyright 1998-1999 by Neil Hodgson <neilh@scintilla.org>
+//                        Robin Dunn <robin@aldunn.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+
+#include "Platform.h"
+#include "wx/stc/stc.h"
+
+Point Point::FromLong(long lpoint) {
+    return Point(lpoint & 0xFFFF, lpoint >> 32);
+}
+
+wxRect wxRectFromPRectangle(PRectangle prc) {
+    wxRect rc(prc.left, prc.top,
+              prc.right-prc.left+1, prc.bottom-prc.top+1);
+    return rc;
+}
+
+PRectangle PRectangleFromwxRect(wxRect rc) {
+    return PRectangle(rc.GetLeft(), rc.GetTop(), rc.GetRight(), rc.GetBottom());
+}
+
+Colour::Colour(long lcol) {
+    co.Set(lcol & 0xff, (lcol >> 8) & 0xff, (lcol >> 16) & 0xff);
+}
+
+Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
+    co.Set(red, green, blue);
+}
+
+bool Colour::operator==(const Colour &other) const {
+    return co == other.co;
+}
+
+long Colour::AsLong() const {
+    return (((long)co.Blue()  << 16) |
+            ((long)co.Green() <<  8) |
+            ((long)co.Red()));
+}
+
+unsigned int Colour::GetRed() {
+    return co.Red();
+}
+
+unsigned int Colour::GetGreen() {
+    return co.Green();
+}
+
+unsigned int Colour::GetBlue() {
+    return co.Blue();
+}
+
+Palette::Palette() {
+    used = 0;
+    allowRealization = false;
+}
+
+Palette::~Palette() {
+    Release();
+}
+
+void Palette::Release() {
+    used = 0;
+}
+
+// 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 < numEntries) {
+            entries[used].desired = cp.desired;
+            entries[used].allocated = cp.desired;
+            used++;
+        }
+    } else {
+        for (int i=0; i < used; i++) {
+            if (entries[i].desired == cp.desired) {
+                cp.allocated = entries[i].allocated;
+                return;
+            }
+        }
+        cp.allocated = cp.desired;
+    }
+}
+
+void Palette::Allocate(Window &) {
+    if (allowRealization) {
+    }
+}
+
+
+Font::Font() {
+    id = 0;
+    ascent = 0;
+}
+
+Font::~Font() {
+}
+
+void Font::Create(const char *faceName, int size, bool bold, bool italic) {
+    Release();
+    id = new wxFont(size,
+                    wxDEFAULT,
+                    italic ? wxITALIC :  wxNORMAL,
+                    bold ? wxBOLD : wxNORMAL,
+                    false,
+                    faceName);
+}
+
+
+void Font::Release() {
+    if (id)
+        delete id;
+    id = 0;
+}
+
+
+Surface::Surface() :
+    hdc(0), hdcOwned(0), bitmap(0),
+    x(0), y(0) {
+}
+
+Surface::~Surface() {
+    Release();
+}
+
+void Surface::Release() {
+    if (bitmap) {
+        ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
+        delete bitmap;
+        bitmap = 0;
+    }
+    if (hdcOwned) {
+        delete hdc;
+        hdc = 0;
+        hdcOwned = false;
+    }
+}
+
+
+bool Surface::Initialised() {
+    return hdc != 0;
+}
+
+void Surface::Init() {
+    Release();
+    hdc = new wxMemoryDC();
+    hdcOwned = true;
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::Init(SurfaceID hdc_) {
+    Release();
+    hdc = hdc_;
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::InitPixMap(int width, int height, Surface *surface_) {
+    Release();
+    hdc = new wxMemoryDC(surface_->hdc);
+    hdcOwned = true;
+    bitmap = new wxBitmap(width, height);
+    ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
+    // **** ::SetTextAlign(hdc, TA_BASELINE);
+}
+
+void Surface::PenColour(Colour fore) {
+    hdc->SetPen(wxPen(fore.co, 1, wxSOLID));
+}
+
+void Surface::BrushColor(Colour back) {
+    hdc->SetBrush(wxBrush(back.co, wxSOLID));
+}
+
+void Surface::SetFont(Font &font_) {
+    hdc->SetFont(*font_.GetID());
+}
+
+int Surface::LogPixelsY() {
+    return hdc->GetPPI().y;
+}
+
+void Surface::MoveTo(int x_, int y_) {
+    x = x_;
+    y = y_;
+}
+
+void Surface::LineTo(int x_, int y_) {
+    hdc->DrawLine(x,y, x_,y_);
+    x = x_;
+    y = y_;
+}
+
+void Surface::Polygon(Point *pts, int npts, Colour fore,
+                      Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawPolygon(npts, (wxPoint*)pts);
+}
+
+void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::FillRectangle(PRectangle rc, Colour back) {
+    BrushColor(back);
+    hdc->SetPen(*wxTRANSPARENT_PEN);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
+    wxBrush br;
+    if (surfacePattern.bitmap)
+        br = wxBrush(*surfacePattern.bitmap);
+    else    // Something is wrong so display in red
+        br = wxBrush(*wxRED, wxSOLID);
+    hdc->SetPen(*wxTRANSPARENT_PEN);
+    hdc->SetBrush(br);
+    hdc->DrawRectangle(wxRectFromPRectangle(rc));
+}
+
+void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 8);
+}
+
+void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
+    PenColour(fore);
+    BrushColor(back);
+    hdc->DrawEllipse(wxRectFromPRectangle(rc));
+}
+
+void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
+    hdc->Blit(rc.left, rc.top, rc.Width(), rc.Height(),
+              surfaceSource.hdc, from.x, from.y, wxCOPY);
+}
+
+void Surface::DrawText(PRectangle rc, Font &font, int ybase,
+                       const char *s, int len, Colour fore, Colour back) {
+    SetFont(font);
+    hdc->SetTextForeground(fore.co);
+    hdc->SetTextBackground(back.co);
+    FillRectangle(rc, back);
+
+    // ybase is where the baseline should be, but wxWin uses the upper left
+    // corner, so I need to calculate the real position for the text...
+    hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
+}
+
+void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) {
+    SetFont(font);
+    hdc->SetTextForeground(fore.co);
+    hdc->SetTextBackground(back.co);
+    FillRectangle(rc, back);
+    hdc->SetClippingRegion(wxRectFromPRectangle(rc));
+
+    // see comments above
+    hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
+    hdc->DestroyClippingRegion();
+}
+
+int Surface::WidthText(Font &font, const char *s, int len) {
+    SetFont(font);
+    int w;
+    int h;
+    hdc->GetTextExtent(wxString(s, len), &w, &h);
+    return w;
+}
+
+void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) {
+    SetFont(font);
+    int totalWidth = 0;
+    for (int i=0; i<len; i++) {
+        int w;
+        int h;
+        hdc->GetTextExtent(s[i], &w, &h);
+        totalWidth += w;
+        positions[i] = totalWidth;
+    }
+}
+
+int Surface::WidthChar(Font &font, char ch) {
+    SetFont(font);
+    int w;
+    int h;
+    hdc->GetTextExtent(ch, &w, &h);
+    return w;
+}
+
+#define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+int Surface::Ascent(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    font.ascent = h - d;
+    return font.ascent;
+}
+
+int Surface::Descent(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    return d;
+}
+
+int Surface::InternalLeading(Font &font) {
+    return 0;
+}
+
+int Surface::ExternalLeading(Font &font) {
+    SetFont(font);
+    int w, h, d, e;
+    hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
+    return e;
+}
+
+int Surface::Height(Font &font) {
+    SetFont(font);
+    return hdc->GetCharHeight();
+}
+
+int Surface::AverageCharWidth(Font &font) {
+    SetFont(font);
+    return hdc->GetCharWidth();
+}
+
+int Surface::SetPalette(Palette *pal, bool inBackGround) {
+    return 0;  // **** figure out what to do with palettes...
+}
+
+void Surface::SetClip(PRectangle rc) {
+    hdc->SetClippingRegion(wxRectFromPRectangle(rc));
+}
+
+
+
+Window::~Window() {
+}
+
+void Window::Destroy() {
+    if (id)
+        id->Destroy();
+    id = 0;
+}
+
+bool Window::HasFocus() {
+    return wxWindow::FindFocus() == id;
+}
+
+PRectangle Window::GetPosition() {
+    wxRect rc(id->GetPosition(), id->GetSize());
+    return PRectangleFromwxRect(rc);
+}
+
+void Window::SetPosition(PRectangle rc) {
+    id->SetSize(rc.left, rc.top, rc.Width(), rc.Height());
+}
+
+void Window::SetPositionRelative(PRectangle rc, Window) {
+    SetPosition(rc);  // ????
+}
+
+PRectangle Window::GetClientPosition() {
+    wxSize sz = id->GetClientSize();
+    return  PRectangle(0, 0, sz.x - 1, sz.y - 1);
+}
+
+void Window::Show(bool show) {
+    id->Show(show);
+}
+
+void Window::InvalidateAll() {
+    id->Refresh(false);
+}
+
+void Window::InvalidateRectangle(PRectangle rc) {
+    id->Refresh(false, &wxRectFromPRectangle(rc));
+}
+
+void Window::SetFont(Font &font) {
+    id->SetFont(*font.GetID());
+}
+
+void Window::SetCursor(Cursor curs) {
+    int cursorId;
+
+    switch (curs) {
+    case cursorText:
+        cursorId = wxCURSOR_IBEAM;
+        break;
+    case cursorArrow:
+        cursorId = wxCURSOR_ARROW;
+        break;
+    case cursorUp:
+        cursorId = wxCURSOR_ARROW; // ** no up arrow...  wxCURSOR_UPARROW;
+        break;
+    case cursorWait:
+        cursorId = wxCURSOR_WAIT;
+        break;
+    case cursorHoriz:
+        cursorId = wxCURSOR_SIZEWE;
+        break;
+    case cursorVert:
+        cursorId = wxCURSOR_SIZENS;
+        break;
+    case cursorReverseArrow:
+        cursorId = wxCURSOR_POINT_RIGHT;
+        break;
+    default:
+        cursorId = wxCURSOR_ARROW;
+        break;
+    }
+
+    id->SetCursor(wxCursor(cursorId));
+}
+
+
+void Window::SetTitle(const char *s) {
+    id->SetTitle(s);
+}
+
+
+
+ListBox::ListBox() {
+}
+
+ListBox::~ListBox() {
+}
+
+void ListBox::Create(Window &parent, int ctrlID) {
+    id = new wxListBox(parent.id, ctrlID, wxDefaultPosition, wxDefaultSize,
+                       0, NULL, wxLB_SINGLE | wxLB_SORT);
+}
+
+void ListBox::Clear() {
+    ((wxListBox*)id)->Clear();
+}
+
+void ListBox::Append(char *s) {
+    ((wxListBox*)id)->Append(s);
+}
+
+int ListBox::Length() {
+    return ((wxListBox*)id)->Number();
+}
+
+void ListBox::Select(int n) {
+    ((wxListBox*)id)->SetSelection(n);
+}
+
+int ListBox::GetSelection() {
+    return ((wxListBox*)id)->GetSelection();
+}
+
+int ListBox::Find(const char *prefix) {
+    return ((wxListBox*)id)->FindString(prefix);
+}
+
+void ListBox::GetValue(int n, char *value, int len) {
+    wxString text = ((wxListBox*)id)->GetString(n);
+    strncpy(value, text.c_str(), len);
+    value[len-1] = '\0';
+}
+
+void ListBox::Sort() {
+    // wxWindows keeps sorted so no need to sort
+}
+
+
+Menu::Menu() : id(0) {
+}
+
+void Menu::CreatePopUp() {
+    Destroy();
+    id = new wxMenu();
+}
+
+void Menu::Destroy() {
+    if (id)
+        delete id;
+    id = 0;
+}
+
+void Menu::Show(Point pt, Window &w) {
+    w.GetID()->PopupMenu(id, pt.x - 4, pt.y);
+    Destroy();
+}
+
+
+Colour Platform::Chrome() {
+    wxColour c;
+    c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
+    return Colour(c.Red(), c.Green(), c.Blue());
+}
+
+Colour Platform::ChromeHighlight() {
+    wxColour c;
+    c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT);
+    return Colour(c.Red(), c.Green(), c.Blue());
+}
+
+const char *Platform::DefaultFont() {
+    return wxNORMAL_FONT->GetFaceName();
+}
+
+int Platform::DefaultFontSize() {
+    return 8;
+}
+
+unsigned int Platform::DoubleClickTime() {
+    return 500;   // **** ::GetDoubleClickTime();
+}
+
+void Platform::DebugDisplay(const char *s) {
+    wxLogDebug(s);
+}
+
+bool Platform::IsKeyDown(int key) {
+    return false;  // I don't think we'll need this.
+}
+
+long Platform::SendScintilla(WindowID w,
+                             unsigned int msg,
+                             unsigned long wParam,
+                             long lParam) {
+
+    wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
+    return stc->SendMsg(msg, wParam, lParam);
+}
+
+
+// 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
+
+void Platform::DebugPrintf(const char *format, ...) {
+#ifdef TRACE
+    char buffer[2000];
+    va_list pArguments;
+    va_start(pArguments, format);
+    vsprintf(buffer,format,pArguments);
+    va_end(pArguments);
+    Platform::DebugDisplay(buffer);
+#endif
+}
+
+int Platform::Clamp(int val, int minVal, int maxVal) {
+    if (val > maxVal)
+        val = maxVal;
+    if (val < minVal)
+        val = minVal;
+    return val;
+}
+
+
+
+
+
+
diff --git a/src/stc/README.txt b/src/stc/README.txt
new file mode 100644 (file)
index 0000000..46bc58f
--- /dev/null
@@ -0,0 +1,47 @@
+This contrib is the wxStyledTextCtrl, which is a wrapper around the
+Scintilla edit control.  (See www.scintilla.org)
+
+There is still VERY MUCH to be done, most notable of which is a more
+advanced sample that exercises more of the code.  (I havn't tested
+AutoComplete or CallTips, or most of the event types at all yet.)  And
+also documentation, adding wrappers for some new scintilla
+functionality, building and testing on wxGTK, etc.  Be patient, it all
+will get there soon.
+
+
+
+Let me describe a bit about the architecture I am implementing...
+Obviously there is the Platform layer which implements the varioius
+platform classes by using wxWindows classes and filling in where
+needed.  Then there is a ScintillaWX class that is derived from
+ScintillaBase and implements the necessary virtual methods that
+Scintilla needs to fully funciton.  This class however is not meant to
+ever be used directly by wx programmers.  I call it one end of the
+bridge between the wx and Scintilla worlds.  The other end of the
+bridge is a class called wxStyledTextCtrl that looks, feels and acts
+like other classes in wxWindows.  Here is a diagram:
+
+
+ +------------------+          +-------------------+
+ | wxStyledTextCtrl |--bridge--|    ScintillaWX    |
+ +------------------+          +-------------------+
+                               |   ScintillaBase   |
+                               +-------------------+
+                               |       Editor      |
+                               +-------------------+
+                               |     PlatWX        |
+                               +-------------------+
+
+
+wxStyledTextCtrl derives from wxControl so it has a window that can be
+drawn upon.  When a wxStyledTextCtrl is constructed it constructs a
+ScintillaWX for itself and passes itself to the scintilla object to be
+set as the wMain and wDraw attributes.  All method calls on the STC
+are sent over the bridge in the form of calls to ScintiallWX::WndProc.
+All notifications are sent back over the bridge and turned into
+wxEvents.
+
+
+Robin
+
+
diff --git a/src/stc/ScintillaWX.cpp b/src/stc/ScintillaWX.cpp
new file mode 100644 (file)
index 0000000..5b82473
--- /dev/null
@@ -0,0 +1,457 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        ScintillaWX.cxx
+// Purpose:     A wxWindows implementation of Scintilla.  A class derived
+//              from ScintillaBase that uses the "wx platform" defined in
+//              PlatformWX.cxx  This class is one end of a bridge between
+//              the wx world and the Scintilla world.  It needs a peer
+//              object of type wxStyledTextCtrl to function.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#include "ScintillaWX.h"
+#include "wx/stc/stc.h"
+
+
+//----------------------------------------------------------------------
+
+const int H_SCROLL_MAX  = 2000;
+const int H_SCROLL_STEP = 20;
+const int H_SCROLL_PAGE = 200;
+
+//----------------------------------------------------------------------
+// Helper classes
+
+class wxSTCTimer : public wxTimer {
+public:
+    wxSTCTimer(ScintillaWX* swx) {
+        this->swx = swx;
+    }
+
+    void Notify() {
+        swx->DoTick();
+    }
+
+private:
+    ScintillaWX* swx;
+};
+
+
+
+bool wxSTCDropTarget::OnDropText(wxCoord x, wxCoord y, const wxString& data) {
+    return swx->DoDropText(x, y, data);
+}
+
+wxDragResult  wxSTCDropTarget::OnEnter(wxCoord x, wxCoord y, wxDragResult def) {
+    return swx->DoDragEnter(x, y, def);
+}
+
+wxDragResult  wxSTCDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult def) {
+    return swx->DoDragOver(x, y, def);
+}
+
+void  wxSTCDropTarget::OnLeave() {
+    swx->DoDragLeave();
+}
+
+
+
+//----------------------------------------------------------------------
+// Constructor/Destructor
+
+
+ScintillaWX::ScintillaWX(wxStyledTextCtrl* win) {
+    capturedMouse = false;
+    wMain = win;
+    wDraw = win;
+    stc   = win;
+    Initialise();
+}
+
+
+ScintillaWX::~ScintillaWX() {
+    SetTicking(false);
+}
+
+//----------------------------------------------------------------------
+// base class virtuals
+
+
+void ScintillaWX::Initialise() {
+    //ScintillaBase::Initialise();
+    dropTarget.SetScintilla(this);
+    stc->SetDropTarget(&dropTarget);
+}
+
+
+void ScintillaWX::Finalise() {
+    ScintillaBase::Finalise();
+}
+
+
+void ScintillaWX::StartDrag() {
+    wxDropSource        source;
+    wxTextDataObject    data(dragChars);
+    wxDragResult        result;
+
+    source.SetData(data);
+    result = source.DoDragDrop(TRUE);
+    if (result == wxDragMove && dropWentOutside)
+        ClearSelection();
+    inDragDrop = FALSE;
+    SetDragPosition(invalidPosition);
+}
+
+
+void ScintillaWX::SetTicking(bool on) {
+    wxSTCTimer* steTimer;
+    if (timer.ticking != on) {
+        timer.ticking = on;
+        if (timer.ticking) {
+            steTimer = new wxSTCTimer(this);
+            steTimer->Start(timer.tickSize);
+            timer.tickerID = (int)steTimer;
+        } else {
+            steTimer = (wxSTCTimer*)timer.tickerID;
+            steTimer->Stop();
+            delete steTimer;
+            timer.tickerID = 0;
+        }
+    }
+    timer.ticksToWait = caret.period;
+}
+
+
+void ScintillaWX::SetMouseCapture(bool on) {
+    if (on)
+        wMain.GetID()->CaptureMouse();
+    else
+        wMain.GetID()->ReleaseMouse();
+    capturedMouse = on;
+}
+
+
+bool ScintillaWX::HaveMouseCapture() {
+    return capturedMouse;
+}
+
+
+void ScintillaWX::ScrollText(int linesToMove) {
+    int dy = vs.lineHeight * (linesToMove);
+    // TODO: calculate the rectangle to refreshed...
+    wMain.GetID()->ScrollWindow(0, dy);
+}
+
+void ScintillaWX::SetVerticalScrollPos() {
+    wMain.GetID()->SetScrollPos(wxVERTICAL, topLine);
+}
+
+void ScintillaWX::SetHorizontalScrollPos() {
+    wMain.GetID()->SetScrollPos(wxHORIZONTAL, xOffset);
+}
+
+
+bool ScintillaWX::ModifyScrollBars(int nMax, int nPage) {
+    bool modified = false;
+    int  sbMax    = wMain.GetID()->GetScrollRange(wxVERTICAL);
+    int  sbThumb  = wMain.GetID()->GetScrollThumb(wxVERTICAL);
+    int  sbPos    = wMain.GetID()->GetScrollPos(wxVERTICAL);
+
+
+    if (sbMax != nMax || sbThumb != nPage) {
+        wMain.GetID()->SetScrollbar(wxVERTICAL, sbPos, nPage, nMax);
+        modified = true;
+    }
+
+    sbMax    = wMain.GetID()->GetScrollRange(wxHORIZONTAL);
+    sbThumb  = wMain.GetID()->GetScrollThumb(wxHORIZONTAL);
+    if ((sbMax != H_SCROLL_MAX) || (sbThumb != H_SCROLL_STEP)) {
+        wMain.GetID()->SetScrollbar(wxHORIZONTAL, 0, H_SCROLL_STEP, H_SCROLL_MAX);
+        modified = true;
+    }
+    return modified;
+}
+
+
+void ScintillaWX::NotifyChange() {
+    stc->NotifyChange();
+}
+
+
+void ScintillaWX::NotifyParent(SCNotification scn) {
+    stc->NotifyParent(&scn);
+}
+
+
+
+void ScintillaWX::Copy() {
+    if (currentPos != anchor) {
+        char* text = CopySelectionRange();
+        textDO.SetText(text);
+        wxTheClipboard->Open();
+        wxTheClipboard->SetData(&textDO);
+        wxTheClipboard->Close();
+    }
+}
+
+
+void ScintillaWX::Paste() {
+    pdoc->BeginUndoAction();
+    ClearSelection();
+
+    wxTextDataObject data;
+    bool canPaste;
+
+    wxTheClipboard->Open();
+    canPaste = wxTheClipboard->GetData(data);
+    wxTheClipboard->Close();
+    if (canPaste) {
+        wxString str = data.GetText();
+        int      len = str.Length();
+        pdoc->InsertString(currentPos, str.c_str(), len);
+        SetEmptySelection(currentPos + len);
+    }
+
+    pdoc->EndUndoAction();
+    NotifyChange();
+    Redraw();
+}
+
+
+bool ScintillaWX::CanPaste() {
+    wxTextDataObject data;
+    bool canPaste;
+
+    wxTheClipboard->Open();
+    canPaste = wxTheClipboard->GetData(data);
+    wxTheClipboard->Close();
+
+    return canPaste;
+}
+
+void ScintillaWX::CreateCallTipWindow(PRectangle) {
+    ct.wCallTip = new wxWindow(wDraw.GetID(), -1);
+    ct.wDraw = ct.wCallTip;
+}
+
+
+void ScintillaWX::AddToPopUp(const char *label, int cmd, bool enabled) {
+    if (!label[0])
+        popup.GetID()->AppendSeparator();
+    else
+        popup.GetID()->Append(cmd, label);
+
+    if (!enabled)
+        popup.GetID()->Enable(cmd, enabled);
+
+    // TODO:  need to create event handler mappings for the cmd ID
+}
+
+
+void ScintillaWX::ClaimSelection() {
+
+}
+
+
+LRESULT ScintillaWX::DefWndProc(UINT /*iMessage*/, WPARAM /*wParam*/, LPARAM /*lParam*/) {
+    return 0;
+}
+
+LRESULT ScintillaWX::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+    switch (iMessage) {
+    case EM_CANPASTE:
+        return CanPaste();
+    default:
+        return ScintillaBase::WndProc(iMessage, wParam, lParam);
+    }
+    return 0;
+}
+
+
+
+//----------------------------------------------------------------------
+// Event delegates
+
+void ScintillaWX::DoPaint(wxDC* dc, wxRect rect) {
+
+    paintState = painting;
+    Surface surfaceWindow;
+    surfaceWindow.Init(dc);
+    PRectangle rcPaint = PRectangleFromwxRect(rect);
+    dc->BeginDrawing();
+    Paint(&surfaceWindow, rcPaint);
+    dc->EndDrawing();
+    surfaceWindow.Release();
+    if (paintState == paintAbandoned) {
+        // Painting area was insufficient to cover new styling or brace highlight positions
+        FullPaint();
+    }
+    paintState = notPainting;
+}
+
+
+void ScintillaWX::DoHScroll(int type, int pos) {
+    int xPos = xOffset;
+    switch (type) {
+    case wxEVT_SCROLLWIN_LINEUP:
+        xPos -= H_SCROLL_STEP;
+        break;
+    case wxEVT_SCROLLWIN_LINEDOWN:
+        xPos += H_SCROLL_STEP;
+        break;
+    case wxEVT_SCROLLWIN_PAGEUP:
+        xPos -= H_SCROLL_PAGE;
+        break;
+    case wxEVT_SCROLLWIN_PAGEDOWN:
+        xPos += H_SCROLL_PAGE;
+        break;
+    case wxEVT_SCROLLWIN_TOP:
+        xPos = 0;
+        break;
+    case wxEVT_SCROLLWIN_BOTTOM:
+        xPos = H_SCROLL_MAX;
+        break;
+    case wxEVT_SCROLLWIN_THUMBTRACK:
+        xPos = pos;
+        break;
+    }
+    HorizontalScrollTo(xPos);
+}
+
+void ScintillaWX::DoVScroll(int type, int pos) {
+    int topLineNew = topLine;
+    switch (type) {
+    case wxEVT_SCROLLWIN_LINEUP:
+        topLineNew -= 1;
+        break;
+    case wxEVT_SCROLLWIN_LINEDOWN:
+        topLineNew += 1;
+        break;
+    case wxEVT_SCROLLWIN_PAGEUP:
+        topLineNew -= LinesToScroll();
+        break;
+    case wxEVT_SCROLLWIN_PAGEDOWN:
+        topLineNew += LinesToScroll();
+        break;
+    case wxEVT_SCROLLWIN_TOP:
+        topLineNew = 0;
+        break;
+    case wxEVT_SCROLLWIN_BOTTOM:
+        topLineNew = MaxScrollPos();
+        break;
+    case wxEVT_SCROLLWIN_THUMBTRACK:
+        topLineNew = pos;
+        break;
+    }
+    ScrollTo(topLineNew);
+}
+
+void ScintillaWX::DoSize(int width, int height) {
+    PRectangle rcClient(0,0,width,height);
+    SetScrollBarsTo(rcClient);
+    DropGraphics();
+}
+
+void ScintillaWX::DoLoseFocus(){
+    DropCaret();
+}
+
+void ScintillaWX::DoGainFocus(){
+    ShowCaretAtCurrentPosition();
+}
+
+void ScintillaWX::DoSysColourChange() {
+    InvalidateStyleData();
+}
+
+void ScintillaWX::DoButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+    ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+void ScintillaWX::DoButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+    ButtonUp(pt, curTime, ctrl);
+}
+
+void ScintillaWX::DoButtonMove(Point pt) {
+    ButtonMove(pt);
+}
+
+
+void ScintillaWX::DoAddChar(char ch) {
+    AddChar(ch);
+}
+
+int  ScintillaWX::DoKeyDown(int key, bool shift, bool ctrl, bool alt) {
+    return KeyDown(key, shift, ctrl, alt);
+}
+
+
+void ScintillaWX::DoCommand(int ID) {
+    Command(ID);
+}
+
+
+void ScintillaWX::DoContextMenu(Point pt) {
+    ContextMenu(pt);
+}
+
+
+//----------------------------------------------------------------------
+
+bool ScintillaWX::DoDropText(long x, long y, const wxString& data) {
+    SetDragPosition(invalidPosition);
+    int movePos = PositionFromLocation(Point(x,y));
+    DropAt(movePos, data, dragResult == wxDragMove, FALSE); // TODO: rectangular?
+    return TRUE;
+}
+
+
+wxDragResult ScintillaWX::DoDragEnter(wxCoord x, wxCoord y, wxDragResult def) {
+    return def;
+}
+
+
+wxDragResult ScintillaWX::DoDragOver(wxCoord x, wxCoord y, wxDragResult def) {
+    SetDragPosition(PositionFromLocation(Point(x, y)));
+    dragResult = def;
+    return def;
+}
+
+
+void ScintillaWX::DoDragLeave() {
+    SetDragPosition(invalidPosition);
+}
+
+//----------------------------------------------------------------------
+
+// Redraw all of text area. This paint will not be abandoned.
+void ScintillaWX::FullPaint() {
+    paintState = painting;
+    rcPaint = GetTextRectangle();
+    wxClientDC dc(wMain.GetID());
+    Surface surfaceWindow;
+    surfaceWindow.Init(&dc);
+    Paint(&surfaceWindow, rcPaint);
+    surfaceWindow.Release();
+    paintState = notPainting;
+}
+
+
+void ScintillaWX::DoScrollToLine(int line) {
+    ScrollTo(line);
+}
+
+
+void ScintillaWX::DoScrollToColumn(int column) {
+    HorizontalScrollTo(column * vs.spaceWidth);
+}
+
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
diff --git a/src/stc/ScintillaWX.h b/src/stc/ScintillaWX.h
new file mode 100644 (file)
index 0000000..d25eb18
--- /dev/null
@@ -0,0 +1,148 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        ScintillaWX.h
+// Purpose:     A wxWindows implementation of Scintilla.  A class derived
+//              from ScintillaBase that uses the "wx platform" defined in
+//              PlatWX.cpp.  This class is one end of a bridge between
+//              the wx world and the Scintilla world.  It needs a peer
+//              object of type wxStyledTextCtrl to function.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ScintillaWX_h__
+#define __ScintillaWX_h__
+
+//----------------------------------------------------------------------
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+#include <wx/wx.h>
+#include <wx/dataobj.h>
+#include <wx/clipbrd.h>
+#include <wx/dnd.h>
+
+//----------------------------------------------------------------------
+
+class wxStyledTextCtrl;           // forward
+class ScintillaWX;
+
+
+//----------------------------------------------------------------------
+// Helper classes
+
+class wxSTCDropTarget : public wxTextDropTarget {
+public:
+    void SetScintilla(ScintillaWX* swx) {
+        this->swx = swx;
+    }
+
+    bool OnDropText(wxCoord x, wxCoord y, const wxString& data);
+    wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def);
+    wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def);
+    void OnLeave();
+
+private:
+    ScintillaWX* swx;
+};
+
+
+//----------------------------------------------------------------------
+
+class ScintillaWX : public ScintillaBase {
+public:
+
+    ScintillaWX(wxStyledTextCtrl* win);
+    ~ScintillaWX();
+
+    // base class virtuals
+    virtual void Initialise();
+    virtual void Finalise();
+    virtual void StartDrag();
+    virtual void SetTicking(bool on);
+    virtual void SetMouseCapture(bool on);
+    virtual bool HaveMouseCapture();
+    virtual void ScrollText(int linesToMove);
+    virtual void SetVerticalScrollPos();
+    virtual void SetHorizontalScrollPos();
+    virtual bool ModifyScrollBars(int nMax, int nPage);
+    virtual void Copy();
+    virtual void Paste();
+    virtual void CreateCallTipWindow(PRectangle rc);
+    virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
+    virtual void ClaimSelection();
+
+    virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+    virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+
+    virtual void NotifyChange();
+    virtual void NotifyParent(SCNotification scn);
+
+
+    // Event delegates
+    void DoPaint(wxDC* dc, wxRect rect);
+    void DoHScroll(int type, int pos);
+    void DoVScroll(int type, int pos);
+    void DoSize(int width, int height);
+    void DoLoseFocus();
+    void DoGainFocus();
+    void DoSysColourChange();
+    void DoButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
+    void DoButtonUp(Point pt, unsigned int curTime, bool ctrl);
+    void DoButtonMove(Point pt);
+    void DoAddChar(char ch);
+    int  DoKeyDown(int key, bool shift, bool ctrl, bool alt);
+    void DoTick() { Tick(); }
+
+    bool DoDropText(long x, long y, const wxString& data);
+    wxDragResult DoDragEnter(wxCoord x, wxCoord y, wxDragResult def);
+    wxDragResult DoDragOver(wxCoord x, wxCoord y, wxDragResult def);
+    void DoDragLeave();
+
+    void DoCommand(int ID);
+    void DoContextMenu(Point pt);
+
+
+    // helpers
+    void FullPaint();
+    bool CanPaste();
+    bool GetHideSelection() { return hideSelection; }
+    void DoScrollToLine(int line);
+    void DoScrollToColumn(int column);
+
+private:
+    bool                capturedMouse;
+    wxStyledTextCtrl*   stc;
+
+    wxTextDataObject    textDO;
+    wxSTCDropTarget     dropTarget;
+    wxDragResult        dragResult;
+};
+
+//----------------------------------------------------------------------
+#endif
diff --git a/src/stc/makefile.vc b/src/stc/makefile.vc
new file mode 100644 (file)
index 0000000..8e91828
--- /dev/null
@@ -0,0 +1,106 @@
+# File:                makefile.vc  For stectrl
+# Author:      Robin Dunn
+# Created:     1-Feb-2000
+# Updated:
+
+
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+SCINTILLA=.\scintilla
+S=$(SCINTILLA)\src
+EXTRAINC=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)\contrib\include
+NOPCH=1
+
+!include $(WXDIR)\src\makevc.env
+
+OBJECTS = \
+       $(D)\Accessor.obj       \
+       $(D)\AutoComplete.obj   \
+       $(D)\CallTip.obj        \
+       $(D)\CellBuffer.obj     \
+       $(D)\ContractionState.obj\
+       $(D)\Document.obj       \
+       $(D)\Editor.obj         \
+       $(D)\Indicator.obj      \
+       $(D)\KeyMap.obj         \
+       $(D)\KeyWords.obj       \
+       $(D)\LineMarker.obj     \
+       $(D)\PropSet.obj        \
+       $(D)\ScintillaBase.obj  \
+       $(D)\Style.obj          \
+       $(D)\ViewStyle.obj      \
+                               \
+       $(D)\PlatWX.obj         \
+       $(D)\ScintillaWX.obj    \
+       $(D)\stc.obj            \
+
+
+
+
+LIBTARGET = $(WXDIR)\contrib\lib\stc$(LIBEXT).lib
+
+all:    $(D) $(LIBTARGET)
+
+$(D) :
+       mkdir $(D)
+
+wx:
+        cd $(WXDIR)\src\msw
+        nmake -f makefile.vc FINAL=$(FINAL)
+        cd $(THISDIR)
+
+wxclean:
+        cd $(WXDIR)\src\msw
+        nmake -f makefile.vc clean
+        cd $(THISDIR)
+
+
+
+
+$(LIBTARGET): $(OBJECTS)
+       -erase $(LIBTARGET)
+       $(implib) @<<
+-out:$(LIBTARGET)
+-machine:$(CPU)
+$(OBJECTS)
+<<
+
+
+$(PROGRAM).exe: $(D)\$(PROGRAM).obj  $(DUMMYOBJ) $(WXLIB) $(LIBTARGET) $(PROGRAM).res
+       $(link) @<<
+-out:$(PROGRAM).exe
+$(LINKFLAGS)
+$(DUMMYOBJ) $(D)\$(PROGRAM).obj $(LIBTARGET) $(PROGRAM).res
+$(LIBS)
+<<
+
+$(PROGRAM).res :      $(PROGRAM).rc $(WXDIR)\include\wx\msw\wx.rc
+    $(rc) -r /i$(WXDIR)\include -fo$@ $(PROGRAM).rc
+
+
+
+{$(S)}.cxx{$(D)}.obj:
+       $(cc) @<<
+$(CPPFLAGS) /c /Fo$@ /Tp $<
+<<
+
+{}.cpp{$(D)}.obj:
+       $(cc) @<<
+$(CPPFLAGS) /c /Fo$@ /Tp $<
+<<
+
+
+show:
+       @echo $(CPPFLAGS)
+
+
+clean:
+        -erase $(D)\*.obj
+        -erase *.sbr
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.pdb
+        -erase $(LIBTARGET)
+
diff --git a/src/stc/scintilla/README.txt b/src/stc/scintilla/README.txt
new file mode 100644 (file)
index 0000000..705fb99
--- /dev/null
@@ -0,0 +1,7 @@
+This directory contains copies of the scintilla/src and
+scintilla/include directories from the Scintilla/SCiTE source
+distribution.  All other code needed to implement Scintilla on top of
+wxWindows is located in the directory above this one.
+
+The current version of the Scintilla code is somewhere between 1.22
+and 1.23, (from their CVS.)
diff --git a/src/stc/scintilla/include/Accessor.h b/src/stc/scintilla/include/Accessor.h
new file mode 100644 (file)
index 0000000..1bba4af
--- /dev/null
@@ -0,0 +1,76 @@
+// SciTE - Scintilla based Text Editor
+// Accessor.h - rapid easy access to contents of a Scintilla
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+class Accessor {
+protected:
+       // bufferSize is a trade off between time taken to copy the characters and SendMessage overhead
+       // slopSize positions the buffer before the desired position in case there is some backtracking
+       enum {bufferSize=4000, slopSize=bufferSize/8};
+       char buf[bufferSize+1];
+       WindowID id;
+       PropSet &props;
+       int startPos;
+       int endPos;
+       int lenDoc;
+       int offset;     // Optional but including an offset makes GCC generate better code 
+       void Fill(int position);
+public:
+       Accessor(WindowID id_, PropSet &props_, int offset_=0) : 
+                       id(id_), props(props_), startPos(0x7FFFFFFF), endPos(0), 
+                       lenDoc(-1), offset(offset_) {
+       }
+       char operator[](int position) {
+               position += offset;
+               if (position < startPos || position >= endPos) {
+                       Fill(position);
+               }
+               return buf[position - startPos];
+       }
+       char SafeGetCharAt(int position, char chDefault=' ') {
+               // Safe version of operator[], returning a defined value for invalid position 
+               position += offset;
+               if (position < startPos || position >= endPos) {
+                       Fill(position);
+                       if (position < startPos || position >= endPos) {
+                               // Position is outside range of document 
+                               return chDefault;
+                       }
+               }
+               return buf[position - startPos];
+       }
+       char StyleAt(int position);
+       int GetLine(int position);
+       int LineStart(int line);
+       int LevelAt(int line);
+       int Length();
+       void Flush() {
+               startPos = 0x7FFFFFFF;
+               lenDoc = -1;
+       }
+       int GetLineState(int line);
+       int SetLineState(int line, int state);
+       PropSet &GetPropSet() { return props; }
+};
+
+class StylingContext : public Accessor {
+       char styleBuf[bufferSize];
+       int validLen;
+       char chFlags;
+       char chWhile;
+       unsigned int startSeg;
+public:
+       StylingContext(WindowID id_, PropSet &props_, int offset_=0) : 
+               Accessor(id_,props_,offset_), validLen(0), chFlags(0) {}
+       void StartAt(unsigned int start, char chMask=31);
+       void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; };
+       void ColourSegment(unsigned int start, unsigned int end, int chAttr);
+       unsigned int GetStartSegment() { return startSeg; }
+       void StartSegment(unsigned int pos);
+       void ColourTo(unsigned int pos, int chAttr);
+       int GetLine(int position);
+       void SetLevel(int line, int level);
+       void Flush();
+};
+
diff --git a/src/stc/scintilla/include/KeyWords.h b/src/stc/scintilla/include/KeyWords.h
new file mode 100644 (file)
index 0000000..2cc03b7
--- /dev/null
@@ -0,0 +1,8 @@
+// SciTE - Scintilla based Text Editor
+// KeyWords.h - colourise for particular languages
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle, 
+       int language, WordList *keywordlists[], StylingContext &styler);
+
diff --git a/src/stc/scintilla/include/Platform.h b/src/stc/scintilla/include/Platform.h
new file mode 100644 (file)
index 0000000..3a5e981
--- /dev/null
@@ -0,0 +1,392 @@
+// Scintilla source code edit control
+// Platform.h - interface to platform facilities
+// Also includes some basic utilities
+// Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+// PLAT_GTK = GTK+ on Linux, PLAT_WIN = Win32 API on Win32 OS
+// PLAT_WX is wxWindows on any supported platform
+// Could also have PLAT_GTKWIN = GTK+ on Win32 OS in future
+
+#define PLAT_GTK 0
+#define PLAT_WIN 0
+#define PLAT_WX  0
+
+#if defined(__WX__)
+#undef PLAT_WX
+#define PLAT_WX  1
+
+#elif defined(GTK)
+#undef PLAT_GTK
+#define PLAT_GTK 1
+
+#else
+#undef PLAT_WIN
+#define PLAT_WIN 1
+
+#endif
+
+
+// Include the main header for each platform
+
+#if PLAT_GTK
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#endif
+
+#if PLAT_WIN
+#define _WIN32_WINNT  0x0400 // Otherwise some required stuff gets ifdef'd out
+// Vassili Bourdo: shut up annoying Visual C++ warnings:
+#ifdef _MSC_VER
+#pragma warning(disable: 4800 4244 4309)
+#endif
+#include <windows.h>
+#include <richedit.h>
+#endif
+
+#if PLAT_WX
+#include <wx/wx.h>
+#endif
+
+// Underlying the implementation of the platform classes are platform specific types.
+// Sometimes these need to be passed around by client code so they are defined here
+
+#if PLAT_GTK
+typedef GdkColor ColourID;
+typedef GdkFont* FontID;
+typedef GdkDrawable* SurfaceID;
+typedef GtkWidget* WindowID;
+typedef GtkItemFactory* MenuID;
+#endif
+
+#if PLAT_WIN
+typedef COLORREF ColourID;
+typedef HFONT FontID;
+typedef HDC SurfaceID;
+typedef HWND WindowID;
+typedef HMENU MenuID;
+#endif
+
+#if PLAT_WX
+typedef wxColour ColourID;
+typedef wxFont* FontID;
+typedef wxDC* SurfaceID;
+typedef wxWindow* WindowID;
+typedef wxMenu* MenuID;
+#endif
+
+#if PLAT_GTK || PLAT_WX
+#define SHIFT_PRESSED 1
+#define LEFT_CTRL_PRESSED 2
+#define LEFT_ALT_PRESSED 4
+#endif
+
+// Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably
+
+class Point {
+public:
+       int x;
+       int y;
+       
+       Point(int x_=0, int y_=0) : x(x_), y(y_) {
+       }
+
+       // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+       
+       static Point FromLong(long lpoint);
+};
+
+// PRectangle is exactly the same as the Win32 RECT so can be used interchangeably
+// PRectangles contain their top and left sides, but not their right and bottom sides
+class PRectangle {
+public:
+       int left;
+       int top;
+       int right;
+       int bottom;
+
+       PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) :
+               left(left_), top(top_), right(right_), bottom(bottom_) {
+       }
+
+       // Other automatically defined methods (assignment, copy constructor, destructor) are fine
+
+       bool Contains(Point pt) {
+               return (pt.x >= left) && (pt.x <= right) &&
+                       (pt.y >= top) && (pt.y <= bottom);
+       }
+       bool Contains(PRectangle rc) {
+               return (rc.left >= left) && (rc.right <= right) &&
+                       (rc.top >= top) && (rc.bottom <= bottom);
+       }
+       bool Intersects(PRectangle other) {
+               return (right >= other.left) && (left <= other.right) &&
+                       (bottom >= other.top) && (top <= other.bottom);
+       }
+       int Width() { return right - left; }
+       int Height() { return bottom - top; }
+};
+
+#if PLAT_WX
+wxRect wxRectFromPRectangle(PRectangle prc);
+PRectangle PRectangleFromwxRect(wxRect rc);
+#endif
+
+class Colour {
+       ColourID co;
+public:
+       Colour(long lcol=0);
+       Colour(unsigned int red, unsigned int green, unsigned int blue);
+       bool operator==(const Colour &other) const;
+       long AsLong() const;
+       unsigned int GetRed();
+       unsigned int GetGreen();
+       unsigned int GetBlue();
+       
+       friend class Surface;
+       friend class Palette;
+};
+
+// Colour pairs hold a desired colour and the colour that the graphics engine
+// allocates to approximate the desired colour.
+// To make palette management more automatic, ColourPairs could register at 
+// construction time with a palette management object.
+struct ColourPair {
+       Colour desired;
+       Colour allocated;
+
+       ColourPair(Colour desired_=Colour(0,0,0)) {
+               desired = desired_;
+               allocated = desired;
+       }
+};
+
+class Window;  // Forward declaration for Palette
+
+class Palette {
+       int used;
+       enum {numEntries = 100};
+       ColourPair entries[numEntries];
+#if PLAT_GTK
+       GdkColor *allocatedPalette;
+       int allocatedLen;
+#elif PLAT_WIN
+       HPALETTE hpal;
+#elif PLAT_WX
+       // wxPalette* pal;  // **** Is this needed?
+#endif
+public:
+       bool allowRealization;
+       
+       Palette();
+       ~Palette();
+
+       void Release();
+       
+       // This method either adds a colour to the list of wanted colours (want==true)
+       // or retrieves the allocated colour back to the ColourPair.
+       // This is one method to make it easier to keep the code for wanting and retrieving in sync.
+       void WantFind(ColourPair &cp, bool want);
+
+       void Allocate(Window &w);
+       
+       friend class Surface;
+};
+
+class Font {
+       FontID id;
+#if PLAT_WX
+       int ascent;
+#endif
+       // Private so Font objects can not be copied
+       Font(const Font &) {}
+       Font &operator=(const Font &) { id=0; return *this; }
+public:
+       Font();
+       ~Font();
+
+       void Create(const char *faceName, int size, bool bold=false, bool italic=false);
+       void Release();
+
+       FontID GetID() { return id; }
+       friend class Surface;
+};
+
+// A surface abstracts a place to draw
+class Surface {
+private:
+#if PLAT_GTK
+       GdkDrawable *drawable;
+       GdkGC *gc;
+       GdkPixmap *ppixmap;
+       int x;
+       int y;
+       bool inited;
+       bool createdGC;
+#elif PLAT_WIN
+       HDC hdc;
+       bool hdcOwned;
+       HPEN pen;
+       HPEN penOld;
+       HBRUSH brush;
+       HBRUSH brushOld;
+       HFONT font;
+       HFONT fontOld;
+       HBITMAP bitmap;
+       HBITMAP bitmapOld;
+       HPALETTE paletteOld;
+#elif PLAT_WX
+       wxDC* hdc;
+       bool hdcOwned;
+       wxBitmap* bitmap;
+       int x;
+       int y;
+#endif
+
+       // Private so Surface objects can not be copied
+       Surface(const Surface &) {}
+       Surface &operator=(const Surface &) { return *this; }
+#if PLAT_WIN || PLAT_WX
+       void BrushColor(Colour back);
+       void SetFont(Font &font_);
+#endif
+public:
+       Surface();
+       ~Surface();
+       
+       void Init();
+       void Init(SurfaceID hdc_);
+       void InitPixMap(int width, int height, Surface *surface_);
+
+       void Release();
+       bool Initialised();
+       void PenColour(Colour fore);
+       int LogPixelsY();
+       void MoveTo(int x_, int y_);
+       void LineTo(int x_, int y_);
+       void Polygon(Point *pts, int npts, Colour fore, Colour back);
+       void RectangleDraw(PRectangle rc, Colour fore, Colour back);
+       void FillRectangle(PRectangle rc, Colour back);
+       void FillRectangle(PRectangle rc, Surface &surfacePattern);
+       void RoundedRectangle(PRectangle rc, Colour fore, Colour back);
+       void Ellipse(PRectangle rc, Colour fore, Colour back);
+       void Copy(PRectangle rc, Point from, Surface &surfaceSource);
+
+       void DrawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back);
+       void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back);
+       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);
+};
+
+// Class to hide the details of window manipulation
+// Does not own the window which will normally have a longer life than this object
+class Window {
+       friend class ListBox;
+protected:
+       WindowID id;
+public:
+       Window() : id(0) {}
+       virtual ~Window();
+       Window &operator=(WindowID id_) {
+               id = id_;
+               return *this;
+       }
+       WindowID GetID() { return id; }
+       bool Created() { return id != 0; }
+       void Destroy();
+       bool HasFocus();
+       PRectangle GetPosition();
+       void SetPosition(PRectangle rc);
+       void SetPositionRelative(PRectangle rc, Window relativeTo);
+       PRectangle GetClientPosition();
+       void Show(bool show=true);
+       void InvalidateAll();
+       void InvalidateRectangle(PRectangle rc);
+       void SetFont(Font &font);
+       enum Cursor { cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow };
+       void SetCursor(Cursor curs);
+       void SetTitle(const char *s);
+#if PLAT_WIN
+       LRESULT SendMessage(UINT msg, WPARAM wParam=0, LPARAM lParam=0);
+       int GetDlgCtrlID();
+       HINSTANCE GetInstance();
+#endif
+};
+
+class ListBox : public Window {
+#if PLAT_GTK
+       WindowID list;
+       WindowID scroller;
+       int current;
+#endif
+public:
+       ListBox();
+       virtual ~ListBox();
+       ListBox &operator=(WindowID id_) {
+               id = id_;
+               return *this;
+       }
+       void Create(Window &parent, int ctrlID);
+       void Clear();
+       void Append(char *s);
+       int Length();
+       void Select(int n);
+       int GetSelection();
+       int Find(const char *prefix);
+       void GetValue(int n, char *value, int len);
+       void Sort();
+};
+
+class Menu {
+       MenuID id;
+public:
+       Menu();
+       MenuID GetID() { return id; }
+       void CreatePopUp();
+       void Destroy();
+       void Show(Point pt, Window &w);
+};
+
+// Platform class used to retrieve system wide parameters such as double click speed
+// and chrome colour. Not a creatable object, more of a module with several functions.
+class Platform {
+       // Private so Platform objects can not be copied
+       Platform(const Platform &) {}
+       Platform &operator=(const Platform &) { return *this; }
+public:
+       // Should be private because no new Platforms are ever created
+       // but gcc warns about this
+       Platform() {}
+       ~Platform() {}
+       static Colour Chrome();
+       static Colour ChromeHighlight();
+       static const char *DefaultFont();
+       static int DefaultFontSize();
+       static unsigned int DoubleClickTime();
+       static void DebugDisplay(const char *s);
+       static bool IsKeyDown(int key);
+       static long SendScintilla(
+               WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
+       
+       // These are utility functions not really tied to a platform
+       static int Minimum(int a, int b);
+       static int Maximum(int a, int b);
+       static void DebugPrintf(const char *format, ...);
+       static int Clamp(int val, int minVal, int maxVal);
+};
+
+#endif
diff --git a/src/stc/scintilla/include/PropSet.h b/src/stc/scintilla/include/PropSet.h
new file mode 100644 (file)
index 0000000..31da01f
--- /dev/null
@@ -0,0 +1,180 @@
+// SciTE - Scintilla based Text Editor
+// PropSet.h - a java style properties file module
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef PROPSET_H
+#define PROPSET_H
+
+bool EqualCaseInsensitive(const char *a, const char *b);
+
+// Define another string class.
+// While it would be 'better' to use std::string, that doubles the executable size.
+
+inline char *StringDup(const char *s) {
+       if (!s)
+               return 0;
+       char *sNew = new char[strlen(s) + 1];
+       if (sNew)
+               strcpy(sNew, s);
+       return sNew;
+}
+
+class SString {
+       char *s;
+public:
+       SString() {
+               s = 0;
+       }
+       SString(const SString &source) {
+               s = StringDup(source.s);
+       }
+       SString(const char *s_) {
+               s = StringDup(s_);
+       }
+       SString(int i) {
+               char number[100];
+               sprintf(number, "%0d", i);
+               //itoa(i, number, 10);
+               s = StringDup(number);
+       }
+       ~SString() {
+               delete []s;
+               s = 0;
+       }
+       SString &operator=(const SString &source) {
+               if (this != &source) {
+                       delete []s;
+                       s = StringDup(source.s);
+               }
+               return *this;
+       }
+       bool operator==(const SString &other) const {
+               if ((s == 0) && (other.s == 0))
+                       return true;
+               if ((s == 0) || (other.s == 0))
+                       return false;
+               return strcmp(s, other.s) == 0;
+       }
+       bool operator==(const char *sother) const {
+               if ((s == 0) && (sother == 0))
+                       return true;
+               if ((s == 0) || (sother == 0))
+                       return false;
+               return strcmp(s, sother) == 0;
+       }
+       const char *c_str() const {
+               if (s)
+                       return s;
+               else
+                       return "";
+       }
+       int length() const {
+               if (s)
+                       return strlen(s);
+               else
+                       return 0;
+       }
+       char operator[](int i) {
+               if (s)
+                       return s[i];
+               else
+                       return '\0';
+       }
+       SString &operator +=(const char *sother) {
+               int len = length();
+               int lenOther = strlen(sother);
+               char *sNew = new char[len + lenOther + 1];
+               if (sNew) {
+                       if (s)
+                               memcpy(sNew, s, len);
+                       memcpy(sNew + len, sother, lenOther);
+                       sNew[len + lenOther] = '\0';
+                       delete []s;
+                       s = sNew;
+               }
+               return *this;
+       }
+       int value() {
+               if (s)
+                       return atoi(s);
+               else 
+                       return 0;
+       }
+};
+
+class PropSet {
+private:
+       char **vals;
+       int size;
+       int used;
+public:
+       PropSet *superPS;
+       PropSet();
+       ~PropSet();
+       void EnsureCanAddEntry();
+       void Set(const char *key, const char *val);
+       void Set(char *keyval);
+       SString Get(const char *key);
+       int GetInt(const char *key, int defaultValue=0);
+       SString GetWild(const char *keybase, const char *filename);
+       SString GetNewExpand(const char *keybase, const char *filename);
+       void Clear();
+       void ReadFromMemory(const char *data, int len);
+       void Read(const char *filename);
+};
+
+// This is a fixed length list of strings suitable for display  in combo boxes
+// as a memory of user entries
+template<int sz>
+class EntryMemory {
+       SString entries[sz];
+public:
+       void Insert(SString s) {
+               for (int i=0;i<sz;i++) {
+                       if (entries[i] == s) {
+                               for (int j=i;j>0;j--) {
+                                       entries[j] = entries[j-1];
+                               }
+                               entries[0] = s;
+                               return;
+                       }
+               }
+               for (int k=sz-1;k>0;k--) {
+                       entries[k] = entries[k-1];
+               }
+               entries[0] = s;
+       }
+       int Length() const {
+               int len = 0;
+               for (int i=0;i<sz;i++)
+                       if (entries[i].length())
+                               len++;
+               return len;
+       }
+       SString At(int n) const {
+               return entries[n];
+       }
+};
+
+class WordList {
+public:
+       // Each word contains at least one character - a empty word acts as sentinal at the end.
+       char **words;
+       char *list;
+       int len;
+       bool onlyLineEnds;      // Delimited by any white space or only line ends
+       int starts[256];
+       WordList(bool onlyLineEnds_ = false) : 
+               words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {}
+       ~WordList() { Clear(); }
+       operator bool() { return list; }
+       const char *operator[](int ind) { return words[ind]; }
+       void Clear();
+       void Set(const char *s);
+       char *Allocate(int size);
+       void SetFromAllocated();
+       bool InList(const char *s);
+};
+
+#endif
diff --git a/src/stc/scintilla/include/SciLexer.h b/src/stc/scintilla/include/SciLexer.h
new file mode 100644 (file)
index 0000000..d6667e4
--- /dev/null
@@ -0,0 +1,134 @@
+// Scintilla source code edit control
+// SciLexer - interface to the added lexer functions in the SciLexer version of the edit control
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCILEXER_H
+#define SCILEXER_H
+
+// SciLexer features - not in standard Scintilla
+
+#define SCLEX_CONTAINER 0
+#define SCLEX_NULL 1
+#define SCLEX_PYTHON 2
+#define SCLEX_CPP 3
+#define SCLEX_HTML 4
+#define SCLEX_XML 5
+#define SCLEX_PERL 6
+#define SCLEX_SQL 7
+#define SCLEX_VB 8
+#define SCLEX_PROPERTIES 9
+#define SCLEX_ERRORLIST 10
+#define SCLEX_MAKEFILE 11
+#define SCLEX_BATCH 12
+
+// Lexical states for SCLEX_PYTHON
+#define SCE_P_DEFAULT 0
+#define SCE_P_COMMENTLINE 1
+#define SCE_P_NUMBER 2
+#define SCE_P_STRING 3
+#define SCE_P_CHARACTER 4
+#define SCE_P_WORD 5
+#define SCE_P_TRIPLE 6
+#define SCE_P_TRIPLEDOUBLE 7
+#define SCE_P_CLASSNAME 8
+#define SCE_P_DEFNAME 9
+#define SCE_P_OPERATOR 10
+#define SCE_P_IDENTIFIER 11
+
+// Lexical states for SCLEX_CPP, SCLEX_VB
+#define SCE_C_DEFAULT 0
+#define SCE_C_COMMENT 1
+#define SCE_C_COMMENTLINE 2
+#define SCE_C_COMMENTDOC 3
+#define SCE_C_NUMBER 4
+#define SCE_C_WORD 5
+#define SCE_C_STRING 6
+#define SCE_C_CHARACTER 7
+#define SCE_C_PUNTUATION 8
+#define SCE_C_PREPROCESSOR 9
+#define SCE_C_OPERATOR 10
+#define SCE_C_IDENTIFIER 11
+#define SCE_C_STRINGEOL 12
+
+// Lexical states for SCLEX_HTML, SCLEX_xML
+#define SCE_H_DEFAULT 0
+#define SCE_H_TAG 1
+#define SCE_H_TAGUNKNOWN 2
+#define SCE_H_ATTRIBUTE 3
+#define SCE_H_ATTRIBUTEUNKNOWN 4
+#define SCE_H_NUMBER 5
+#define SCE_H_DOUBLESTRING 6
+#define SCE_H_SINGLESTRING 7
+#define SCE_H_OTHER 8
+#define SCE_H_COMMENT 9
+#define SCE_H_ENTITY 10
+// Embedded Javascript
+#define SCE_HJ_START 11
+#define SCE_HJ_DEFAULT 12
+#define SCE_HJ_COMMENT 13
+#define SCE_HJ_COMMENTLINE 14
+#define SCE_HJ_COMMENTDOC 15
+#define SCE_HJ_NUMBER 16
+#define SCE_HJ_WORD 17
+#define SCE_HJ_KEYWORD 18
+#define SCE_HJ_DOUBLESTRING 19
+#define SCE_HJ_SINGLESTRING 20
+#define SCE_HJ_SYMBOLS 21
+#define SCE_HJ_STRINGEOL 28
+// XML and ASP
+#define SCE_H_TAGEND 22
+#define SCE_H_XMLSTART 23
+#define SCE_H_XMLEND 24
+#define SCE_H_SCRIPT 25
+#define SCE_H_ASP 26
+#define SCE_H_ASPAT 27
+// Embedded VBScript
+#define SCE_HB_START 40
+#define SCE_HB_DEFAULT 41
+#define SCE_HB_COMMENTLINE 42
+#define SCE_HB_NUMBER 43
+#define SCE_HB_WORD 44
+#define SCE_HB_STRING 45
+#define SCE_HB_IDENTIFIER 46
+#define SCE_HB_STRINGEOL 47
+// Embedded Python
+#define SCE_HP_START 50
+#define SCE_HP_DEFAULT 51
+#define SCE_HP_COMMENTLINE 52
+#define SCE_HP_NUMBER 53
+#define SCE_HP_STRING 54
+#define SCE_HP_CHARACTER 55
+#define SCE_HP_WORD 56
+#define SCE_HP_TRIPLE 57
+#define SCE_HP_TRIPLEDOUBLE 58
+#define SCE_HP_CLASSNAME 59
+#define SCE_HP_DEFNAME 60
+#define SCE_HP_OPERATOR 61
+#define SCE_HP_IDENTIFIER 62
+
+// Lexical states for SCLEX_PERL
+#define SCE_PL_DEFAULT 0
+#define SCE_PL_HERE 1
+#define SCE_PL_COMMENTLINE 2
+#define SCE_PL_POD 3
+#define SCE_PL_NUMBER 4
+#define SCE_PL_WORD 5
+#define SCE_PL_STRING 6
+#define SCE_PL_CHARACTER 7
+#define SCE_PL_PUNCTUATION 8
+#define SCE_PL_PREPROCESSOR 9
+#define SCE_PL_OPERATOR 10
+#define SCE_PL_IDENTIFIER 11
+#define SCE_PL_SCALAR 12
+#define SCE_PL_ARRAY 13
+#define SCE_PL_HASH 14
+#define SCE_PL_SYMBOLTABLE 15
+#define SCE_PL_REF 16
+#define SCE_PL_REGEX 17
+#define SCE_PL_REGSUBST 18
+#define SCE_PL_LONGQUOTE 19
+#define SCE_PL_BACKTICKS 20
+#define SCE_PL_DATASECTION 21
+    
+#endif
diff --git a/src/stc/scintilla/include/Scintilla.h b/src/stc/scintilla/include/Scintilla.h
new file mode 100644 (file)
index 0000000..0757216
--- /dev/null
@@ -0,0 +1,415 @@
+// Scintilla source code edit control
+// Scintilla.h - interface to the edit control
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef SCINTILLA_H
+#define SCINTILLA_H
+
+// Compile-time configuration options
+#define MACRO_SUPPORT 1  // Comment out to remove macro hooks
+
+#if PLAT_GTK
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SCINTILLA(obj)          GTK_CHECK_CAST (obj, scintilla_get_type (), ScintillaObject)
+#define SCINTILLA_CLASS(klass)  GTK_CHECK_CLASS_CAS    T (klass, scintilla_get_type (), ScintillaClass)
+#define IS_SCINTILLA(obj)       GTK_CHECK_TYPE (obj, scintilla_get_type ())
+
+       typedef struct _ScintillaObject ScintillaObject;
+       typedef struct _ScintillaClass  ScintillaClass;
+
+       struct _ScintillaObject
+       {
+               GtkFixed vbox;
+               void *pscin;
+       };
+
+       struct _ScintillaClass
+       {
+               GtkFixedClass parent_class;
+
+               void (* command) (ScintillaObject *ttt);
+               void (* notify) (ScintillaObject *ttt);
+       };
+
+       guint           scintilla_get_type      (void);
+       GtkWidget*      scintilla_new           (void);
+       void            scintilla_set_id        (ScintillaObject *sci,int id);
+       long            scintilla_send_message  (ScintillaObject *sci,int iMessage,int wParam,int lParam);
+
+#include "WinDefs.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#if PLAT_WX
+#include "WinDefs.h"
+#endif
+
+// Both GTK and Windows
+
+#define INVALID_POSITION -1 
+
+// Define start of Scintilla messages to be greater than all edit (EM_*) messages
+// as many EM_ messages can be used.
+#define SCI_START 2000
+#define SCI_OPTIONAL_START 3000
+#define SCI_LEXER_START 4000
+
+#define SCI_ADDTEXT SCI_START + 1
+#define SCI_ADDSTYLEDTEXT SCI_START + 2
+#define SCI_INSERTTEXT SCI_START + 3
+#define SCI_CLEARALL SCI_START + 4
+#define SCI_GETLENGTH SCI_START + 6
+#define SCI_GETCHARAT SCI_START + 7
+#define SCI_GETCURRENTPOS SCI_START + 8
+#define SCI_GETANCHOR SCI_START + 9
+#define SCI_GETSTYLEAT SCI_START + 10
+
+#define SCI_REDO SCI_START + 11
+#define SCI_SETUNDOCOLLECTION SCI_START + 12
+#define SCI_SELECTALL SCI_START + 13
+#define SCI_SETSAVEPOINT SCI_START + 14
+#define SCI_GETSTYLEDTEXT SCI_START + 15
+#define SCI_CANREDO SCI_START + 16
+#define SCI_MARKERLINEFROMHANDLE SCI_START + 17
+#define SCI_MARKERDELETEHANDLE SCI_START + 18
+
+#define SC_UNDOCOLLECT_NONE 0
+#define SC_UNDOCOLLECT_AUTOSTART 1
+
+#define SCI_GETVIEWWS SCI_START + 20
+#define SCI_SETVIEWWS SCI_START + 21
+#define SCI_CHANGEPOSITION SCI_START + 22
+#define SCI_GOTOLINE SCI_START + 24
+#define SCI_GOTOPOS SCI_START + 25
+#define SCI_SETANCHOR SCI_START + 26
+#define SCI_GETCURLINE SCI_START + 27
+#define SCI_GETENDSTYLED SCI_START + 28
+#define SCI_CONVERTEOLS SCI_START + 29
+
+#define SCI_GETEOLMODE SCI_START + 30
+#define SCI_SETEOLMODE SCI_START + 31
+
+#define SC_EOL_CRLF 0
+#define SC_EOL_CR 1
+#define SC_EOL_LF 2
+
+#define SCI_STARTSTYLING SCI_START + 32
+#define SCI_SETSTYLING SCI_START + 33
+
+#define SCI_SETBUFFEREDDRAW SCI_START + 35
+#define SCI_SETTABWIDTH SCI_START + 36
+#define SCI_SETCODEPAGE SCI_START + 37
+#define SCI_SETUSEPALETTE SCI_START + 39
+
+#define MARKER_MAX 31
+
+#define SC_MARK_CIRCLE 0
+#define SC_MARK_ROUNDRECT 1
+#define SC_MARK_ARROW 2
+#define SC_MARK_SMALLRECT 3
+#define SC_MARK_SHORTARROW 4
+#define SC_MARK_EMPTY 5
+#define SC_MARK_ARROWDOWN 6
+#define SC_MARK_MINUS 7
+#define SC_MARK_PLUS 8
+
+#define SCI_MARKERDEFINE SCI_START + 40
+#define SCI_MARKERSETFORE SCI_START + 41
+#define SCI_MARKERSETBACK SCI_START + 42
+#define SCI_MARKERADD SCI_START + 43
+#define SCI_MARKERDELETE SCI_START + 44
+#define SCI_MARKERDELETEALL SCI_START + 45
+#define SCI_MARKERGET SCI_START + 46
+#define SCI_MARKERNEXT SCI_START + 47
+#define SCI_MARKERPREVIOUS SCI_START + 48
+
+#define SC_MARKNUM_FOLDER 30
+#define SC_MARKNUM_FOLDEROPEN 31
+
+#define SC_MASK_FOLDERS ((1<<SC_MARKNUM_FOLDER) | (1<<SC_MARKNUM_FOLDEROPEN))
+
+#define SC_MARGIN_SYMBOL 0
+#define SC_MARGIN_NUMBER 1
+
+#define SCI_SETMARGINTYPEN SCI_START + 240
+#define SCI_GETMARGINTYPEN SCI_START + 241
+#define SCI_SETMARGINWIDTHN SCI_START + 242
+#define SCI_GETMARGINWIDTHN SCI_START + 243
+#define SCI_SETMARGINMASKN SCI_START + 244
+#define SCI_GETMARGINMASKN SCI_START + 245
+#define SCI_SETMARGINSENSITIVEN SCI_START + 246
+#define SCI_GETMARGINSENSITIVEN SCI_START + 247
+
+#define STYLE_DEFAULT 32
+#define STYLE_LINENUMBER 33
+#define STYLE_BRACELIGHT 34
+#define STYLE_BRACEBAD 35
+#define STYLE_CONTROLCHAR 36
+#define STYLE_MAX 63
+
+#define SCI_STYLECLEARALL SCI_START + 50
+#define SCI_STYLESETFORE SCI_START + 51
+#define SCI_STYLESETBACK SCI_START + 52
+#define SCI_STYLESETBOLD SCI_START + 53
+#define SCI_STYLESETITALIC SCI_START + 54
+#define SCI_STYLESETSIZE SCI_START + 55
+#define SCI_STYLESETFONT SCI_START + 56
+#define SCI_STYLESETEOLFILLED SCI_START + 57
+#define SCI_STYLERESETDEFAULT SCI_START + 58
+
+#define SCI_SETSELFORE SCI_START + 67
+#define SCI_SETSELBACK SCI_START + 68
+#define SCI_SETCARETFORE SCI_START + 69
+
+#define SCI_ASSIGNCMDKEY SCI_START + 70
+#define SCI_CLEARCMDKEY SCI_START + 71
+#define SCI_CLEARALLCMDKEYS SCI_START + 72
+
+#define SCI_SETSTYLINGEX SCI_START + 73
+
+#define SCI_GETCARETPERIOD SCI_START + 75
+#define SCI_SETCARETPERIOD SCI_START + 76
+#define SCI_SETWORDCHARS SCI_START + 77
+
+#define SCI_BEGINUNDOACTION SCI_START + 78
+#define SCI_ENDUNDOACTION SCI_START + 79
+
+#define INDIC_MAX 7
+
+#define INDIC_PLAIN 0
+#define INDIC_SQUIGGLE 1
+#define INDIC_TT 2
+
+#define INDIC0_MASK 32
+#define INDIC1_MASK 64
+#define INDIC2_MASK 128
+#define INDICS_MASK (INDIC0_MASK | INDIC1_MASK | INDIC2_MASK)
+
+#define SCI_INDICSETSTYLE SCI_START + 80
+#define SCI_INDICGETSTYLE SCI_START + 81
+#define SCI_INDICSETFORE SCI_START + 82
+#define SCI_INDICGETFORE SCI_START + 83
+
+#define SCI_SETSTYLEBITS SCI_START + 90
+#define SCI_GETSTYLEBITS SCI_START + 91
+#define SCI_SETLINESTATE SCI_START + 92
+#define SCI_GETLINESTATE SCI_START + 93
+#define SCI_GETMAXLINESTATE SCI_START + 94
+
+#define SCI_AUTOCSHOW SCI_START + 100
+#define SCI_AUTOCCANCEL SCI_START + 101
+#define SCI_AUTOCACTIVE SCI_START + 102
+#define SCI_AUTOCPOSSTART SCI_START + 103
+#define SCI_AUTOCCOMPLETE SCI_START + 104
+#define SCI_AUTOCSTOPS SCI_START + 105
+
+#define SCI_CALLTIPSHOW SCI_START + 200
+#define SCI_CALLTIPCANCEL SCI_START + 201
+#define SCI_CALLTIPACTIVE SCI_START + 202
+#define SCI_CALLTIPPOSSTART SCI_START + 203
+#define SCI_CALLTIPSETHLT SCI_START + 204
+#define SCI_CALLTIPSETBACK SCI_START + 205
+
+#define SC_FOLDLEVELBASE 0x400
+#define SC_FOLDLEVELWHITEFLAG 0x1000
+#define SC_FOLDLEVELHEADERFLAG 0x2000
+#define SC_FOLDLEVELNUMBERMASK 0x0FFF
+
+#define SCI_VISIBLEFROMDOCLINE SCI_START + 220
+#define SCI_DOCLINEFROMVISIBLE SCI_START + 221
+#define SCI_SETFOLDLEVEL SCI_START + 222
+#define SCI_GETFOLDLEVEL SCI_START + 223
+#define SCI_GETLASTCHILD SCI_START + 224
+#define SCI_GETFOLDPARENT SCI_START + 225
+#define SCI_SHOWLINES SCI_START + 226
+#define SCI_HIDELINES SCI_START + 227
+#define SCI_GETLINEVISIBLE SCI_START + 228
+#define SCI_SETFOLDEXPANDED SCI_START + 229
+#define SCI_GETFOLDEXPANDED SCI_START + 230
+#define SCI_TOGGLEFOLD SCI_START + 231
+#define SCI_ENSUREVISIBLE SCI_START + 232
+#define SCI_SETFOLDFLAGS SCI_START + 233
+
+// Key messages
+#define SCI_LINEDOWN SCI_START + 300
+#define SCI_LINEDOWNEXTEND SCI_START + 301
+#define SCI_LINEUP SCI_START + 302
+#define SCI_LINEUPEXTEND SCI_START + 303
+#define SCI_CHARLEFT SCI_START + 304
+#define SCI_CHARLEFTEXTEND SCI_START + 305
+#define SCI_CHARRIGHT SCI_START + 306
+#define SCI_CHARRIGHTEXTEND SCI_START + 307
+#define SCI_WORDLEFT SCI_START + 308
+#define SCI_WORDLEFTEXTEND SCI_START + 309
+#define SCI_WORDRIGHT SCI_START + 310
+#define SCI_WORDRIGHTEXTEND SCI_START + 311
+#define SCI_HOME SCI_START + 312
+#define SCI_HOMEEXTEND SCI_START + 313
+#define SCI_LINEEND SCI_START + 314
+#define SCI_LINEENDEXTEND SCI_START + 315
+#define SCI_DOCUMENTSTART SCI_START + 316
+#define SCI_DOCUMENTSTARTEXTEND SCI_START + 317
+#define SCI_DOCUMENTEND SCI_START + 318
+#define SCI_DOCUMENTENDEXTEND SCI_START + 319
+#define SCI_PAGEUP SCI_START + 320
+#define SCI_PAGEUPEXTEND SCI_START + 321
+#define SCI_PAGEDOWN SCI_START + 322
+#define SCI_PAGEDOWNEXTEND SCI_START + 323
+#define SCI_EDITTOGGLEOVERTYPE SCI_START + 324
+#define SCI_CANCEL SCI_START + 325
+#define SCI_DELETEBACK SCI_START + 326
+#define SCI_TAB SCI_START + 327
+#define SCI_BACKTAB SCI_START + 328
+#define SCI_NEWLINE SCI_START + 329
+#define SCI_FORMFEED SCI_START + 330
+#define SCI_VCHOME SCI_START + 331
+#define SCI_VCHOMEEXTEND SCI_START + 332
+#define SCI_ZOOMIN SCI_START + 333
+#define SCI_ZOOMOUT SCI_START + 334
+#define SCI_DELWORDLEFT SCI_START + 335
+#define SCI_DELWORDRIGHT SCI_START + 336
+
+#define SCI_LINELENGTH SCI_START + 350
+#define SCI_BRACEHIGHLIGHT SCI_START + 351
+#define SCI_BRACEBADLIGHT SCI_START + 352
+#define SCI_BRACEMATCH SCI_START + 353
+#define SCI_GETVIEWEOL SCI_START + 355
+#define SCI_SETVIEWEOL SCI_START + 356
+#define SCI_GETDOCPOINTER SCI_START + 357
+#define SCI_SETDOCPOINTER SCI_START + 358
+#define SCI_SETMODEVENTMASK SCI_START + 359
+
+#define EDGE_NONE 0
+#define EDGE_LINE 1
+#define EDGE_BACKGROUND 2
+
+#define SCI_GETEDGECOLUMN SCI_START + 360
+#define SCI_SETEDGECOLUMN SCI_START + 361
+#define SCI_GETEDGEMODE SCI_START + 362
+#define SCI_SETEDGEMODE SCI_START + 363
+#define SCI_GETEDGECOLOUR SCI_START + 364
+#define SCI_SETEDGECOLOUR SCI_START + 365
+
+#define SCI_SEARCHANCHOR SCI_START + 366
+#define SCI_SEARCHNEXT SCI_START + 367
+#define SCI_SEARCHPREV SCI_START + 368
+
+#define CARET_SLOP 0x01    // Show caret within N lines of edge when it's scrolled to view
+#define CARET_CENTER 0x02  // Center caret on screen when it's scrolled to view
+#define CARET_STRICT 0x04  // OR this with CARET_CENTER to reposition even when visible, or
+                           // OR this with CARET_SLOP to reposition whenever outside slop border
+
+#define SCI_SETCARETPOLICY SCI_START + 369
+
+// GTK+ Specific
+#define SCI_GRABFOCUS SCI_START + 400
+
+// Optional module for macro recording
+#ifdef MACRO_SUPPORT
+typedef void (tMacroRecorder)(UINT iMessage, WPARAM wParam, LPARAM lParam, 
+                              void *userData);
+#define SCI_STARTRECORD SCI_OPTIONAL_START + 1
+#define SCI_STOPRECORD SCI_OPTIONAL_START + 2
+#endif
+
+#define SCI_SETLEXER SCI_LEXER_START + 1
+#define SCI_GETLEXER SCI_LEXER_START + 2
+#define SCI_COLOURISE SCI_LEXER_START + 3
+#define SCI_SETPROPERTY SCI_LEXER_START + 4
+#define SCI_SETKEYWORDS SCI_LEXER_START + 5
+
+// Notifications
+
+// Type of modification and the action which caused the modification
+// These are defined as a bit mask to make it easy to specify which notifications are wanted.
+// One bit is set from each of SC_MOD_* and SC_PERFORMED_*.
+#define SC_MOD_INSERTTEXT 0x1
+#define SC_MOD_DELETETEXT 0x2
+#define SC_MOD_CHANGESTYLE 0x4
+#define SC_MOD_CHANGEFOLD 0x8
+#define SC_PERFORMED_USER 0x10
+#define SC_PERFORMED_UNDO 0x20
+#define SC_PERFORMED_REDO 0x40
+#define SC_LASTSTEPINUNDOREDO 0x100
+
+#define SC_MODEVENTMASKALL 0x377
+
+struct SCNotification {
+       NMHDR nmhdr;
+       int position;                   // SCN_STYLENEEDED, SCN_MODIFIED
+       int ch;                                 // SCN_CHARADDED, SCN_KEY
+       int modifiers;                  // SCN_KEY
+       int modificationType;   // SCN_MODIFIED
+       const char *text;               // SCN_MODIFIED
+       int length;                             // SCN_MODIFIED
+       int linesAdded; // SCN_MODIFIED
+#ifdef MACRO_SUPPORT
+       int message;    // SCN_MACRORECORD
+       int wParam;     // SCN_MACRORECORD
+       int lParam;     // SCN_MACRORECORD
+#endif
+       int line;                       // SCN_MODIFIED
+       int foldLevelNow;       // SCN_MODIFIED
+       int foldLevelPrev;      // SCN_MODIFIED
+       int margin;     // SCN_MARGINCLICK
+};
+
+#define SCN_STYLENEEDED 2000
+#define SCN_CHARADDED 2001
+#define SCN_SAVEPOINTREACHED 2002
+#define SCN_SAVEPOINTLEFT 2003
+#define SCN_MODIFYATTEMPTRO 2004
+// GTK+ Specific to work around focus and accelerator problems:
+#define SCN_KEY 2005
+#define SCN_DOUBLECLICK 2006
+#define SCN_UPDATEUI 2007
+// The old name for SCN_UPDATEUI:
+#define SCN_CHECKBRACE 2007
+#define SCN_MODIFIED 2008
+// Optional module for macro recording
+#ifdef MACRO_SUPPORT
+#define SCN_MACRORECORD 2009
+#endif
+#define SCN_MARGINCLICK 2010
+#define SCN_NEEDSHOWN 2011
+
+#ifdef STATIC_BUILD
+void Scintilla_RegisterClasses(HINSTANCE hInstance);
+#endif
+
+// Deprecation section listing all API features that are deprecated and will
+// will be removed completely in a future version.
+// To enable these features define INCLUDE_DEPRECATED_FEATURES
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+
+// Default style settings. These are deprecated and will be removed in a future version.
+#define SCI_SETFORE SCI_START + 60
+#define SCI_SETBACK SCI_START + 61
+#define SCI_SETBOLD SCI_START + 62
+#define SCI_SETITALIC SCI_START + 63
+#define SCI_SETSIZE SCI_START + 64
+#define SCI_SETFONT SCI_START + 65
+
+#define SCI_APPENDUNDOSTARTACTION SCI_START + 74
+
+#define SC_UNDOCOLLECT_MANUALSTART 2
+
+// Deprecated in release 1.22
+#define SCI_SETMARGINWIDTH SCI_START + 34
+#define SCI_SETLINENUMBERWIDTH SCI_START + 38
+
+#endif
+
+#endif
diff --git a/src/stc/scintilla/include/WinDefs.h b/src/stc/scintilla/include/WinDefs.h
new file mode 100644 (file)
index 0000000..0b125e7
--- /dev/null
@@ -0,0 +1,218 @@
+// Scintilla source code edit control
+// WinDefs.h - the subset of definitions from Windows needed by Scintilla for GTK+
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef WINDEFS_H
+#define WINDEFS_H
+
+#define WORD short
+#define WPARAM unsigned long
+#define LPARAM long
+#define LRESULT long
+#define DWORD long
+
+#define UINT unsigned int
+#define LPSTR char *
+#define LONG long
+
+/* RTF control */
+#define EM_CANPASTE    (1074)
+#define EM_CANUNDO     (198)
+#define EM_CHARFROMPOS (215)
+#define EM_DISPLAYBAND (1075)
+#define EM_EMPTYUNDOBUFFER     (205)
+#define EM_EXGETSEL    (1076)
+#define EM_EXLIMITTEXT (1077)
+#define EM_EXLINEFROMCHAR      (1078)
+#define EM_EXSETSEL    (1079)
+#define EM_FINDTEXT    (1080)
+#define EM_FINDTEXTEX  (1103)
+#define EM_FINDWORDBREAK       (1100)
+#define EM_FMTLINES    (200)
+#define EM_FORMATRANGE (1081)
+#define EM_GETCHARFORMAT       (1082)
+#define EM_GETEVENTMASK        (1083)
+#define EM_GETFIRSTVISIBLELINE (206)
+#define EM_GETHANDLE   (189)
+#define EM_GETLIMITTEXT        (213)
+#define EM_GETLINE     (196)
+#define EM_GETLINECOUNT        (186)
+#define EM_GETMARGINS  (212)
+#define EM_GETMODIFY   (184)
+#define EM_GETIMECOLOR (1129)
+#define EM_GETIMEOPTIONS       (1131)
+#define EM_GETOPTIONS  (1102)
+#define EM_GETOLEINTERFACE     (1084)
+#define EM_GETPARAFORMAT       (1085)
+#define EM_GETPASSWORDCHAR     (210)
+#define EM_GETPUNCTUATION      (1125)
+#define EM_GETRECT     (178)
+#define EM_GETSEL      (176)
+#define EM_GETSELTEXT  (1086)
+#define EM_GETTEXTRANGE        (1099)
+#define EM_GETTHUMB    (190)
+#define EM_GETWORDBREAKPROC    (209)
+#define EM_GETWORDBREAKPROCEX  (1104)
+#define EM_GETWORDWRAPMODE     (1127)
+#define EM_HIDESELECTION       (1087)
+#define EM_LIMITTEXT   (197)
+#define EM_LINEFROMCHAR        (201)
+#define EM_LINEINDEX   (187)
+#define EM_LINELENGTH  (193)
+#define EM_LINESCROLL  (182)
+#define EM_PASTESPECIAL        (1088)
+#define EM_POSFROMCHAR (214)
+#define EM_REPLACESEL  (194)
+#define EM_REQUESTRESIZE       (1089)
+#define EM_SCROLL      (181)
+#define EM_SCROLLCARET (183)
+#define EM_SELECTIONTYPE       (1090)
+#define EM_SETBKGNDCOLOR       (1091)
+#define EM_SETCHARFORMAT       (1092)
+#define EM_SETEVENTMASK        (1093)
+#define EM_SETHANDLE   (188)
+#define EM_SETIMECOLOR (1128)
+#define EM_SETIMEOPTIONS       (1130)
+#define EM_SETLIMITTEXT        (197)
+#define EM_SETMARGINS  (211)
+#define EM_SETMODIFY   (185)
+#define EM_SETOLECALLBACK      (1094)
+#define EM_SETOPTIONS  (1101)
+#define EM_SETPARAFORMAT       (1095)
+#define EM_SETPASSWORDCHAR     (204)
+#define EM_SETPUNCTUATION      (1124)
+#define EM_SETREADONLY (207)
+#define EM_SETRECT     (179)
+#define EM_SETRECTNP   (180)
+#define EM_SETSEL      (177)
+#define EM_SETTABSTOPS (203)
+#define EM_SETTARGETDEVICE     (1096)
+#define EM_SETWORDBREAKPROC    (208)
+#define EM_SETWORDBREAKPROCEX  (1105)
+#define EM_SETWORDWRAPMODE     (1126)
+#define EM_STREAMIN    (1097)
+#define EM_STREAMOUT   (1098)
+#define EM_UNDO        (199)
+
+#define WM_NULL                (0)
+#define WM_CLEAR       (771)
+#define WM_COMMAND     (273)
+#define WM_COPY        (769)
+#define WM_CUT (768)
+#define WM_GETTEXT     (13)
+#define WM_GETTEXTLENGTH       (14)
+#define WM_NOTIFY      (78)
+#define WM_PASTE       (770)
+#define WM_SETTEXT     (12)
+#define WM_UNDO        (772)
+
+#define EN_CHANGE      (768)
+#define EN_KILLFOCUS (512)
+#define EN_SETFOCUS (256)
+
+#define EC_LEFTMARGIN 1
+#define EC_RIGHTMARGIN 2
+#define EC_USEFONTINFO 0xffff
+
+#if PLAT_GTK
+#define VK_DOWN GDK_Down
+#define VK_UP GDK_Up
+#define VK_LEFT GDK_Left
+#define VK_RIGHT GDK_Right
+#define VK_HOME GDK_Home
+#define VK_END GDK_End
+#define VK_PRIOR GDK_Page_Up
+#define VK_NEXT GDK_Page_Down
+#define VK_DELETE GDK_Delete
+#define VK_INSERT GDK_Insert
+#define VK_ESCAPE GDK_Escape
+#define VK_BACK GDK_BackSpace
+#define VK_TAB GDK_Tab
+#define VK_RETURN GDK_Return
+#define VK_ADD GDK_KP_Add
+#define VK_SUBTRACT GDK_KP_Subtract
+#endif
+
+#if PLAT_WX
+#define VK_DOWN         WXK_DOWN
+#define VK_UP           WXK_UP
+#define VK_LEFT         WXK_LEFT
+#define VK_RIGHT        WXK_RIGHT
+#define VK_HOME         WXK_HOME
+#define VK_END          WXK_END
+#define VK_PRIOR        WXK_PRIOR
+#define VK_NEXT         WXK_NEXT
+#define VK_DELETE       WXK_DELETE
+#define VK_INSERT       WXK_INSERT
+#define VK_ESCAPE       WXK_ESCAPE
+#define VK_BACK         WXK_BACK
+#define VK_TAB          WXK_TAB
+#define VK_RETURN       WXK_RETURN
+#define VK_ADD          WXK_ADD
+#define VK_SUBTRACT     WXK_SUBTRACT
+
+// Are these needed any more
+#define LPSTR char *
+#define LONG long
+#define LPDWORD (long *)
+#endif
+
+/* SELCHANGE structure */
+#define SEL_EMPTY      (0)
+#define SEL_TEXT       (1)
+#define SEL_OBJECT     (2)
+#define SEL_MULTICHAR  (4)
+#define SEL_MULTIOBJECT        (8)
+
+/* FINDREPLACE structure */
+#define FR_MATCHCASE   (0x4)
+#define FR_WHOLEWORD   (0x2)
+#define FR_DOWN                (0x1)
+
+#define SHIFT_PRESSED 1
+#define LEFT_CTRL_PRESSED 2
+#define LEFT_ALT_PRESSED 4
+
+struct RECT {
+       LONG left;
+       LONG top;
+       LONG right;
+       LONG bottom;
+};
+
+struct CHARRANGE {
+       LONG cpMin;
+       LONG cpMax;
+};
+
+struct TEXTRANGE {
+       CHARRANGE chrg;
+       LPSTR lpstrText;
+};
+
+struct FINDTEXTEX {
+       CHARRANGE chrg;
+       LPSTR lpstrText;
+       CHARRANGE chrgText;
+};
+
+struct NMHDR {
+       WindowID hwndFrom;
+       UINT idFrom;
+       UINT code;
+};
+
+struct FORMATRANGE {
+       SurfaceID hdc;
+       SurfaceID hdcTarget;
+       RECT rc;
+       RECT rcPage;
+       CHARRANGE chrg;
+};
+
+#define MAKELONG(a, b) ((a) | ((b) << 16))
+#define LOWORD(x) (x & 0xffff)
+#define HIWORD(x) (x >> 16)
+
+#endif
diff --git a/src/stc/scintilla/src/Accessor.cxx b/src/stc/scintilla/src/Accessor.cxx
new file mode 100644 (file)
index 0000000..57b7e4d
--- /dev/null
@@ -0,0 +1,112 @@
+// SciTE - Scintilla based Text Editor
+// Accessor.cxx - rapid easy access to contents of a Scintilla
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "Scintilla.h"
+
+void Accessor::Fill(int position) {
+       if (lenDoc == -1)
+               lenDoc = Platform::SendScintilla(id, WM_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::SendScintilla(id, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr));
+}
+
+char Accessor::StyleAt(int position) {
+       return static_cast<char>(Platform::SendScintilla(
+               id, SCI_GETSTYLEAT, position, 0));
+}
+
+int Accessor::GetLine(int position) {
+       return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0);
+}
+
+int Accessor::LineStart(int line) {
+       return Platform::SendScintilla(id, EM_LINEINDEX, line, 0);
+}
+
+int Accessor::LevelAt(int line) {
+       return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0);
+}
+
+int Accessor::Length() { 
+       if (lenDoc == -1) 
+               lenDoc = Platform::SendScintilla(id, WM_GETTEXTLENGTH, 0, 0);
+       return lenDoc; 
+}
+
+int Accessor::GetLineState(int line) {
+       return Platform::SendScintilla(id, SCI_GETLINESTATE, line);
+}
+
+int Accessor::SetLineState(int line, int state) {
+       return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state);
+}
+
+void StylingContext::StartAt(unsigned int start, char chMask) {
+       Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask);
+}
+
+void StylingContext::ColourSegment(unsigned int start, unsigned int end, int chAttr) {
+       // Only perform styling if non empty range
+       if (end != start - 1) {
+               if (end < start) {
+                       Platform::DebugPrintf("Bad colour positions %d - %d\n", start, end);
+               }
+
+               if (validLen + (end - start + 1) >= bufferSize)
+                       Flush();
+               if (validLen + (end - start + 1) >= bufferSize) {
+                       // Too big for buffer so send directly
+                       Platform::SendScintilla(id, SCI_SETSTYLING, end - start + 1, chAttr);
+               } else {
+                       if (chAttr != chWhile)
+                               chFlags = 0;
+                       chAttr |= chFlags;
+                       for (unsigned int i = start; i <= end; i++) {
+                               styleBuf[validLen++] = chAttr;
+                       }
+               }
+       }
+}
+
+void StylingContext::StartSegment(unsigned int pos) {
+       startSeg = pos;
+}
+
+void StylingContext::ColourTo(unsigned int pos, int chAttr) {
+       ColourSegment(startSeg, pos, chAttr);
+       startSeg = pos+1;
+}
+
+int StylingContext::GetLine(int position) {
+       return Platform::SendScintilla(id, EM_LINEFROMCHAR, position, 0);
+}
+
+void StylingContext::SetLevel(int line, int level) {
+       Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level);
+}
+
+void StylingContext::Flush() {
+       if (validLen > 0) {
+               Platform::SendScintilla(id, SCI_SETSTYLINGEX, validLen, 
+                       reinterpret_cast<LPARAM>(styleBuf));
+               validLen = 0;
+       }
+}
diff --git a/src/stc/scintilla/src/AutoComplete.cxx b/src/stc/scintilla/src/AutoComplete.cxx
new file mode 100644 (file)
index 0000000..c3ec29c
--- /dev/null
@@ -0,0 +1,104 @@
+// Scintilla source code edit control
+// AutoComplete.cxx - defines the auto completion list box
+// Copyright 1998-2000 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 "AutoComplete.h"
+
+AutoComplete::AutoComplete() {
+       lb = 0;
+       active = false;
+       posStart = 0;
+       strcpy(stopChars, "");
+}
+
+AutoComplete::~AutoComplete() {
+       lb.Destroy();
+}
+
+bool AutoComplete::Active() {
+       return active;
+}
+
+void AutoComplete::Start(Window &parent, int ctrlID, int position, int startLen_) {
+       if (!lb.Created()) {
+               lb.Create(parent, ctrlID);
+       }
+       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);
+}
+
+int AutoComplete::SetList(const char *list) {
+       int maxStrLen = 12;
+       lb.Clear();
+       char *words = new char[strlen(list) + 1];
+       if (words) {
+               strcpy(words, list);
+               char *startword = words;
+               int i = 0;
+               for (; words && words[i]; i++) {
+                       if (words[i] == ' ') {
+                               words[i] = '\0';
+                               lb.Append(startword);
+                               maxStrLen = Platform::Maximum(maxStrLen, strlen(startword));
+                               startword = words + i + 1;
+                       }
+               }
+               if (startword) {
+                       lb.Append(startword);
+                       maxStrLen = Platform::Maximum(maxStrLen, strlen(startword));
+               }
+               delete []words;
+       }
+       lb.Sort();
+       return maxStrLen;
+}
+
+void AutoComplete::Show() {
+       lb.Show();
+       lb.Select(0);
+}
+
+void AutoComplete::Cancel() {
+       if (lb.Created()) {
+               lb.Destroy();
+               lb = 0;
+               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) {
+       int pos = lb.Find(word);
+       //Platform::DebugPrintf("Autocompleting at <%s> %d\n", wordCurrent, pos);
+       if (pos != -1)
+               lb.Select(pos);
+}
+
diff --git a/src/stc/scintilla/src/AutoComplete.h b/src/stc/scintilla/src/AutoComplete.h
new file mode 100644 (file)
index 0000000..1021602
--- /dev/null
@@ -0,0 +1,43 @@
+// Scintilla source code edit control
+// AutoComplete.h - defines the auto completion list box
+// Copyright 1998-2000 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
+
+class AutoComplete {
+       bool active;
+       char stopChars[256];
+public:
+       ListBox lb;
+       int posStart;
+       int startLen;
+       
+       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, int startLen_);
+       
+       // 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 list string contains a sequence of words separated by spaces
+       int SetList(const char *list);
+       
+       void 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);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/CallTip.cxx b/src/stc/scintilla/src/CallTip.cxx
new file mode 100644 (file)
index 0000000..ad67402
--- /dev/null
@@ -0,0 +1,168 @@
+// Scintilla source code edit control
+// CallTip.cxx - code for displaying call tips
+// Copyright 1998-2000 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 "CallTip.h"
+
+CallTip::CallTip() {
+       wCallTip = 0;
+       inCallTipMode = false;
+       posStartCallTip = 0;
+       val = 0;
+       startHighlight = 0;
+       endHighlight = 0;
+
+       colourBG.desired = Colour(0xff, 0xff, 0xff);
+       colourUnSel.desired = Colour(0x80, 0x80, 0x80);
+       colourSel.desired = Colour(0, 0, 0x80);
+       colourShade.desired = Colour(0, 0, 0);
+       colourLight.desired = Colour(0xc0, 0xc0, 0xc0);
+}
+
+CallTip::~CallTip() {
+       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);
+}
+
+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);
+       // To make a nice small call tip window, it is only sized to fit most normal characters without accents
+       int lineHeight = surfaceWindow->Height(font);
+       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;
+       char *chunkVal = val;
+       bool moreChunks = true;
+       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;
+               int x = 5;
+               int xEnd = x + surfaceWindow->WidthText(font, chunkVal, thisStartHighlight);
+               rcClient.left = x;
+               rcClient.top = ytext - ascent - 1;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal, thisStartHighlight,
+                                       colourUnSel.allocated, colourBG.allocated);
+               x = xEnd;
+
+               xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisStartHighlight,
+                                                   thisEndHighlight - thisStartHighlight);
+               rcClient.top = ytext;
+               rcClient.left = x;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal + thisStartHighlight, thisEndHighlight - thisStartHighlight,
+                                       colourSel.allocated, colourBG.allocated);
+               x = xEnd;
+
+               xEnd = x + surfaceWindow->WidthText(font, chunkVal + thisEndHighlight,
+                                                   chunkLength - thisEndHighlight);
+               rcClient.left = x;
+               rcClient.right = xEnd;
+               surfaceWindow->DrawText(rcClient, font, ytext,
+                                       chunkVal + thisEndHighlight, chunkLength - thisEndHighlight,
+                                       colourUnSel.allocated, colourBG.allocated);
+               chunkVal = chunkEnd + 1;
+               ytext += lineHeight;
+       }
+       // 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);
+}
+
+PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
+                                 const char *faceName, int size) {
+       Surface surfaceMeasure;
+       surfaceMeasure.Init();
+       int deviceHeight = (size * surfaceMeasure.LogPixelsY()) / 72;
+       font.Create(faceName, deviceHeight);
+       if (val)
+               delete []val;
+       val = new char[strlen(defn) + 1];
+       if (!val)
+               return PRectangle();
+       strcpy(val, defn);
+       startHighlight = 0;
+       endHighlight = 0;
+       inCallTipMode = true;
+       posStartCallTip = pos;
+       // Look for multiple lines in the text
+       // Only support \n here - simply means container must avoid \r!
+       int width = 0;
+       int numLines = 1;
+       const char *newline;
+       const char *look = val;
+       while ((newline = strchr(look, '\n')) != NULL) {
+               int thisWidth = surfaceMeasure.WidthText(font, look, newline - look);
+               width = Platform::Maximum(width, thisWidth);
+               look = newline + 1;
+               numLines++;
+       }
+       int lastWidth = surfaceMeasure.WidthText(font, look, strlen(look));
+       width = Platform::Maximum(width, lastWidth) + 10;
+       int lineHeight = surfaceMeasure.Height(font);
+       // Extra line for border and an empty line at top and bottom
+       int height = lineHeight * numLines - surfaceMeasure.InternalLeading(font) + 2 + 2;
+       return PRectangle(pt.x -5, pt.y + lineHeight + 1, pt.x + width - 5, pt.y + lineHeight + 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();
+               }
+       }
+}
diff --git a/src/stc/scintilla/src/CallTip.h b/src/stc/scintilla/src/CallTip.h
new file mode 100644 (file)
index 0000000..cd5b093
--- /dev/null
@@ -0,0 +1,46 @@
+// Scintilla source code edit control
+// CallTip.h - interface to the call tip control
+// Copyright 1998-2000 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
+
+const char callClassName[] = "CallTip";
+
+class CallTip {
+       int startHighlight;
+       int endHighlight;
+       char *val;
+       Font font;
+public:
+       Window wCallTip;
+       Window wDraw;
+       bool inCallTipMode;
+       int posStartCallTip;
+       ColourPair colourBG;
+       ColourPair colourUnSel;
+       ColourPair colourSel;
+       ColourPair colourShade;
+       ColourPair colourLight;
+       
+       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);
+       
+       // 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);
+               
+       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);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/CellBuffer.cxx b/src/stc/scintilla/src/CellBuffer.cxx
new file mode 100644 (file)
index 0000000..7776885
--- /dev/null
@@ -0,0 +1,950 @@
+// Scintilla source code edit control
+// CellBuffer.cxx - manages a buffer of cells
+// Copyright 1998-2000 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 "SVector.h"
+#include "CellBuffer.h"
+
+MarkerHandleSet::MarkerHandleSet() {
+       root = 0;
+}
+
+MarkerHandleSet::~MarkerHandleSet() {
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               MarkerHandleNumber *mhnToFree = mhn;
+               mhn = mhn->next;
+               delete mhnToFree;
+       }
+       root = 0;
+}
+
+int MarkerHandleSet::Length() {
+       int c = 0;
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               c++;
+               mhn = mhn->next;
+       }
+       return c;
+}
+
+int MarkerHandleSet::NumberFromHandle(int handle) {
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               if (mhn->handle == handle) {
+                       return mhn->number;
+               }
+               mhn = mhn->next;
+       }
+       return - 1;
+}
+
+int MarkerHandleSet::MarkValue() {
+       unsigned int m = 0;
+       MarkerHandleNumber *mhn = root;
+       while (mhn) {
+               m |= (1 << mhn->number);
+               mhn = mhn->next;
+       }
+       return m;
+}
+
+bool MarkerHandleSet::Contains(int handle) {
+       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);
+       }
+}
+
+void MarkerHandleSet::RemoveNumber(int markerNum) {
+       MarkerHandleNumber **pmhn = &root;
+       while (*pmhn) {
+               MarkerHandleNumber *mhn = *pmhn;
+               if (mhn->number == markerNum) {
+                       *pmhn = mhn->next;
+                       delete mhn;
+                       return;
+               }
+               pmhn = &((*pmhn)->next);
+       }
+}
+
+void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
+       MarkerHandleNumber **pmhn = &root;
+       while (*pmhn) {
+               pmhn = &((*pmhn)->next);
+       }
+       *pmhn = other->root;
+       other->root = 0;
+}
+
+LineVector::LineVector() {
+       linesData = 0;
+       lines = 0;
+       levels = 0;
+       Init();
+}
+
+LineVector::~LineVector() {
+       for (int line = 0; line < lines; line++) {
+               delete linesData[line].handleSet;
+               linesData[line].handleSet = 0;
+       }
+       delete []linesData;
+       linesData = 0;
+       delete []levels;
+       levels = 0;
+}
+
+void LineVector::Init() {
+       for (int line = 0; line < lines; line++) {
+               delete linesData[line].handleSet;
+               linesData[line].handleSet = 0;
+       }
+       delete []linesData;
+       linesData = new LineData[static_cast<int>(growSize)];
+       size = growSize;
+       lines = 1;
+       delete []levels;
+       levels = 0;
+       sizeLevels = 0;
+}
+
+void LineVector::Expand(int sizeNew) {
+       LineData *linesDataNew = new LineData[sizeNew];
+       if (linesDataNew) {
+               for (int i = 0; i < size; i++)
+                       linesDataNew[i] = linesData[i];
+               // Do not delete handleSets here as they are transferred to new linesData
+               delete []linesData;
+               linesData = linesDataNew;
+               size = sizeNew;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void LineVector::ExpandLevels(int sizeNew) {
+       if (sizeNew == -1)
+               sizeNew = size;
+       int *levelsNew = new int[sizeNew];
+       if (levelsNew) {
+               int i = 0;
+               for (; i < sizeLevels; i++)
+                       levelsNew[i] = levels[i];
+               for (; i < sizeNew; i++)
+                       levelsNew[i] = SC_FOLDLEVELBASE;
+               delete []levels;
+               levels = levelsNew;
+               sizeLevels = sizeNew;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void LineVector::InsertValue(int pos, int value) {
+       //Platform::DebugPrintf("InsertValue[%d] = %d\n", pos, value);
+       if ((lines + 2) >= size) {
+               Expand(size + growSize);
+               if (levels) {
+                       ExpandLevels(size + growSize);
+               }
+       }
+       lines++;
+       for (int i = lines + 1; i > pos; i--) {
+               linesData[i] = linesData[i - 1];
+       }
+       linesData[pos].startPosition = value;
+       linesData[pos].handleSet = 0;
+}
+
+void LineVector::SetValue(int pos, int value) {
+       //Platform::DebugPrintf("SetValue[%d] = %d\n", pos, value);
+       if ((pos + 2) >= size) {
+               //Platform::DebugPrintf("Resize %d %d\n", size,pos);
+               Expand(pos + growSize);
+               //Platform::DebugPrintf("end Resize %d %d\n", size,pos);
+               lines = pos;
+               if (levels) {
+                       ExpandLevels(pos + growSize);
+               }
+       }
+       linesData[pos].startPosition = value;
+}
+
+void LineVector::Remove(int pos) {
+       //Platform::DebugPrintf("Remove %d\n", pos);
+       // Retain the markers from the deleted line by oring them into the previous line
+       if (pos > 0) {
+               MergeMarkers(pos - 1);
+       }
+       for (int i = pos; i < lines; i++) {
+               linesData[i] = linesData[i + 1];
+       }
+       lines--;
+}
+
+int LineVector::LineFromPosition(int pos) {
+       //Platform::DebugPrintf("LineFromPostion %d lines=%d end = %d\n", pos, lines, linesData[lines].startPosition);
+       if (lines == 0)
+               return 0;
+       //Platform::DebugPrintf("LineFromPosition %d\n", pos);
+       if (pos >= linesData[lines].startPosition)
+               return lines - 1;
+       int lower = 0;
+       int upper = lines;
+       int middle = 0;
+       do {
+               middle = (upper + lower + 1) / 2;       // Round high
+               if (pos < linesData[middle].startPosition) {
+                       upper = middle - 1;
+               } else {
+                       lower = middle;
+               }
+       } while (lower < upper);
+       //Platform::DebugPrintf("LineFromPostion %d %d %d\n", pos, lower, linesData[lower].startPosition, linesData[lower > 1 ? lower - 1 : 0].startPosition);
+       return lower;
+}
+
+int LineVector::AddMark(int line, int markerNum) {
+       handleCurrent++;
+       if (!linesData[line].handleSet) {
+               // Need new structure to hold marker handle
+               linesData[line].handleSet = new MarkerHandleSet;
+               if (!linesData[line].handleSet)
+                       return - 1;
+       }
+       linesData[line].handleSet->InsertHandle(handleCurrent, markerNum);
+
+       return handleCurrent;
+}
+
+void LineVector::MergeMarkers(int pos) {
+       if (linesData[pos].handleSet || linesData[pos + 1].handleSet) {
+               if (linesData[pos].handleSet && linesData[pos + 1].handleSet) {
+                       linesData[pos].handleSet->CombineWith(linesData[pos].handleSet);
+                       linesData[pos].handleSet = 0;
+               }
+       }
+}
+
+void LineVector::DeleteMark(int line, int markerNum) {
+       if (linesData[line].handleSet) {
+               if (markerNum == -1) {
+                       delete linesData[line].handleSet;
+                       linesData[line].handleSet = 0;
+               } else {
+                       linesData[line].handleSet->RemoveNumber(markerNum);
+                       if (linesData[line].handleSet->Length() == 0) {
+                               delete linesData[line].handleSet;
+                               linesData[line].handleSet = 0;
+                       }
+               }
+       }
+}
+
+void LineVector::DeleteMarkFromHandle(int markerHandle) {
+       int line = LineFromHandle(markerHandle);
+       if (line >= 0) {
+               linesData[line].handleSet->RemoveHandle(markerHandle);
+               if (linesData[line].handleSet->Length() == 0) {
+                       delete linesData[line].handleSet;
+                       linesData[line].handleSet = 0;
+               }
+       }
+}
+
+int LineVector::LineFromHandle(int markerHandle) {
+       for (int line = 0; line < lines; line++) {
+               if (linesData[line].handleSet) {
+                       if (linesData[line].handleSet->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_) {
+       delete []data;
+       position = position_;
+       at = at_;
+       data = data_;
+       lenData = lenData_;
+}
+
+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;
+
+       // Ownership of source data transferred to this
+       source->position = 0;
+       source->at = startAction;
+       source->data = 0;
+       source->lenData = 0;
+}
+
+CellBuffer::CellBuffer(int initialLength) {
+       body = new char[initialLength];
+       size = initialLength;
+       length = 0;
+       part1len = 0;
+       gaplen = initialLength;
+       part2body = body + gaplen;
+       readOnly = false;
+
+       lenActions = 100;
+       actions = new Action[lenActions];
+       maxAction = 0;
+       currentAction = 0;
+       collectingUndo = undoCollectAutoStart;
+       undoSequenceDepth = 0;
+       savePoint = 0;
+
+       actions[currentAction].Create(startAction);
+}
+
+CellBuffer::~CellBuffer() {
+       delete []body;
+       body = 0;
+       delete []actions;
+       actions = 0;
+}
+
+void CellBuffer::GapTo(int position) {
+       if (position == part1len)
+               return;
+       if (position < part1len) {
+               int diff = part1len - position;
+               //Platform::DebugPrintf("Move gap backwards to %d diff = %d part1len=%d length=%d \n", position,diff, part1len, length);
+               for (int i = 0; i < diff; i++)
+                       body[part1len + gaplen - i - 1] = body[part1len - i - 1];
+       } else {        // position > part1len
+               int diff = position - part1len;
+               //Platform::DebugPrintf("Move gap forwards to %d diff =%d\n", position,diff);
+               for (int i = 0; i < diff; i++)
+                       body[part1len + i] = body[part1len + gaplen + i];
+       }
+       part1len = position;
+       part2body = body + gaplen;
+}
+
+void CellBuffer::RoomFor(int insertionLength) {
+       //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
+       if (gaplen <= insertionLength) {
+               //Platform::DebugPrintf("need room %d %d\n", gaplen, insertionLength);
+               GapTo(length);
+               int newSize = size + insertionLength + 4000;
+               //Platform::DebugPrintf("moved gap %d\n", newSize);
+               char *newBody = new char[newSize];
+               memcpy(newBody, body, size);
+               delete []body;
+               body = newBody;
+               gaplen += newSize - size;
+               part2body = body + gaplen;
+               size = newSize;
+               //Platform::DebugPrintf("end need room %d %d - size=%d length=%d\n", gaplen, insertionLength,size,length);
+       }
+}
+
+// To make it easier to write code that uses ByteAt, a position outside the range of the buffer
+// can be retrieved. All characters outside the range have the value '\0'.
+char CellBuffer::ByteAt(int position) {
+       if (position < part1len) {
+               if (position < 0) {
+                       return '\0';
+               } else {
+                       return body[position];
+               }
+       } else {
+               if (position >= length) {
+                       return '\0';
+               } else {
+                       return part2body[position];
+               }
+       }
+}
+
+void CellBuffer::SetByteAt(int position, char ch) {
+
+       if (position < 0) {
+               //Platform::DebugPrintf("Bad position %d\n",position);
+               return;
+       }
+       if (position >= length + 11) {
+               Platform::DebugPrintf("Very Bad position %d of %d\n", position, length);
+               //exit(2);
+               return;
+       }
+       if (position >= length) {
+               //Platform::DebugPrintf("Bad position %d of %d\n",position,length);
+               return;
+       }
+
+       if (position < part1len) {
+               body[position] = ch;
+       } else {
+               part2body[position] = ch;
+       }
+}
+
+char CellBuffer::CharAt(int position) {
+       return ByteAt(position*2);
+}
+
+void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) {
+       if (lengthRetrieve < 0)
+               return;
+       if (position < 0)
+               return;
+       int bytePos = position * 2;
+       if ((bytePos + lengthRetrieve * 2) > length) {
+               Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n",bytePos,
+                       lengthRetrieve, length);
+               return;
+       }
+       GapTo(0);       // Move the buffer so its easy to subscript into it
+       char *pb = part2body + bytePos;
+       while (lengthRetrieve--) {
+               *buffer++ = *pb;
+               pb +=2;
+       }
+}
+
+char CellBuffer::StyleAt(int position) {
+       return ByteAt(position*2 + 1);
+}
+
+const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
+       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 / 2];
+                       for (int i = 0; i < insertLength / 2; i++) {
+                               data[i] = s[i * 2];
+                       }
+                       AppendAction(insertAction, position, data, insertLength / 2);
+               }
+
+               BasicInsertString(position, s, insertLength);
+       }
+       return data;
+}
+
+void CellBuffer::InsertCharStyle(int position, char ch, char style) {
+       char s[2];
+       s[0] = ch;
+       s[1] = style;
+       InsertString(position*2, s, 2);
+}
+
+bool CellBuffer::SetStyleAt(int position, char style, char mask) {
+       char curVal = ByteAt(position*2 + 1);
+       if ((curVal & mask) != style) {
+               SetByteAt(position*2 + 1, (curVal & ~mask) | style);
+               return true;
+       } else {
+               return false;
+       }
+}
+
+bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mask) {
+       int bytePos = position * 2 + 1;
+       bool changed = false;
+       while (lengthStyle--) {
+               char curVal = ByteAt(bytePos);
+               if ((curVal & mask) != style) {
+                       SetByteAt(bytePos, (curVal & ~mask) | style);
+                       changed = true;
+               }
+               bytePos += 2;
+       }
+       return changed;
+}
+
+void CellBuffer::EnsureUndoRoom() {
+       //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, length, currentAction);
+       if (currentAction >= 2) {
+               // Have to test that there is room for 2 more actions in the array
+               // as two actions may be created by this 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 CellBuffer::AppendAction(actionType at, int position, char *data, int lengthData) {
+       EnsureUndoRoom();
+       //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
+       if (currentAction >= 2) {
+               // See if current action can be coalesced into previous action
+               // Will work if both are inserts or deletes and position is same or two different
+               if ((at != actions[currentAction - 1].at) || (abs(position - actions[currentAction - 1].position) > 2)) {
+                       currentAction++;
+               } else if (currentAction == savePoint) {
+                       currentAction++;
+               }
+       } else {
+               currentAction++;
+       }
+       actions[currentAction].Create(at, position, data, lengthData);
+       if ((collectingUndo == undoCollectAutoStart) && (0 == undoSequenceDepth)) {
+               currentAction++;
+               actions[currentAction].Create(startAction);
+       }
+       maxAction = currentAction;
+}
+
+const char *CellBuffer::DeleteChars(int position, int deleteLength) {
+       // InsertString and DeleteChars are the bottleneck though which all changes occur
+       char *data = 0;
+       if (!readOnly) {
+               if (collectingUndo) {
+                       // Save into the undo/redo stack, but only the characters - not the formatting
+                       data = new char[deleteLength / 2];
+                       for (int i = 0; i < deleteLength / 2; i++) {
+                               data[i] = ByteAt(position + i * 2);
+                       }
+                       AppendAction(removeAction, position, data, deleteLength / 2);
+               }
+
+               BasicDeleteChars(position, deleteLength);
+       }
+       return data;
+}
+
+int CellBuffer::ByteLength() {
+       return length;
+}
+
+int CellBuffer::Length() {
+       return ByteLength() / 2;
+}
+
+int CellBuffer::Lines() {
+       //Platform::DebugPrintf("Lines = %d\n", lv.lines);
+       return lv.lines;
+}
+
+int CellBuffer::LineStart(int line) {
+       if (line < 0)
+               return 0;
+       else if (line > lv.lines)
+               return length;
+       else
+               return lv.linesData[line].startPosition;
+}
+
+bool CellBuffer::IsReadOnly() {
+       return readOnly;
+}
+
+void CellBuffer::SetReadOnly(bool set) {
+       readOnly = set;
+}
+
+void CellBuffer::SetSavePoint() {
+       savePoint = currentAction;
+}
+
+bool CellBuffer::IsSavePoint() {
+       return savePoint == currentAction;
+}
+
+int CellBuffer::AddMark(int line, int markerNum) {
+       if ((line >= 0) && (line < lv.lines)) {
+               return lv.AddMark(line, markerNum);
+       }
+       return - 1;
+}
+
+void CellBuffer::DeleteMark(int line, int markerNum) {
+       if ((line >= 0) && (line < lv.lines)) {
+               lv.DeleteMark(line, markerNum);
+       }
+}
+
+void CellBuffer::DeleteMarkFromHandle(int markerHandle) {
+       lv.DeleteMarkFromHandle(markerHandle);
+}
+
+int CellBuffer::GetMark(int line) {
+       if ((line >= 0) && (line < lv.lines) && (lv.linesData[line].handleSet))
+               return lv.linesData[line].handleSet->MarkValue();
+       return 0;
+}
+
+void CellBuffer::DeleteAllMarks(int markerNum) {
+       for (int line = 0; line < lv.lines; line++) {
+               lv.DeleteMark(line, markerNum);
+       }
+}
+
+int CellBuffer::LineFromHandle(int markerHandle) {
+       return lv.LineFromHandle(markerHandle);
+}
+
+// Without undo
+
+void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
+       //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
+       if (insertLength == 0)
+               return;
+       RoomFor(insertLength);
+       GapTo(position);
+
+       memcpy(body + part1len, s, insertLength);
+       length += insertLength;
+       part1len += insertLength;
+       gaplen -= insertLength;
+       part2body = body + gaplen;
+
+       int lineInsert = lv.LineFromPosition(position / 2) + 1;
+       // Point all the lines after the insertion point further along in the buffer
+       for (int lineAfter = lineInsert; lineAfter <= lv.lines; lineAfter++) {
+               lv.linesData[lineAfter].startPosition += insertLength / 2;
+       }
+       char chPrev = ' ';
+       if ((position - 2) >= 0)
+               chPrev = ByteAt(position - 2);
+       char chAfter = ' ';
+       if ((position + insertLength) < length)
+               chAfter = ByteAt(position + insertLength);
+       if (chPrev == '\r' && chAfter == '\n') {
+               //Platform::DebugPrintf("Splitting a crlf pair at %d\n", lineInsert);
+               // Splitting up a crlf pair at position
+               lv.InsertValue(lineInsert, position / 2);
+               lineInsert++;
+       }
+       char ch = ' ';
+       for (int i = 0; i < insertLength; i += 2) {
+               ch = s[i];
+               if (ch == '\r') {
+                       //Platform::DebugPrintf("Inserting cr at %d\n", lineInsert);
+                       lv.InsertValue(lineInsert, (position + i) / 2 + 1);
+                       lineInsert++;
+               } else if (ch == '\n') {
+                       if (chPrev == '\r') {
+                               //Platform::DebugPrintf("Patching cr before lf at %d\n", lineInsert-1);
+                               // Patch up what was end of line
+                               lv.SetValue(lineInsert - 1, (position + i) / 2 + 1);
+                       } else {
+                               //Platform::DebugPrintf("Inserting lf at %d\n", lineInsert);
+                               lv.InsertValue(lineInsert, (position + i) / 2 + 1);
+                               lineInsert++;
+                       }
+               }
+               chPrev = ch;
+       }
+       // Joining two lines where last insertion is cr and following text starts with lf
+       if (chAfter == '\n') {
+               if (ch == '\r') {
+                       //Platform::DebugPrintf("Joining cr before lf at %d\n", lineInsert-1);
+                       // End of line already in buffer so drop the newly created one
+                       lv.Remove(lineInsert - 1);
+               }
+       }
+}
+
+void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
+       //Platform::DebugPrintf("Deleting at %d for %d\n", position, deleteLength);
+       if (deleteLength == 0)
+               return;
+
+       if ((position == 0) && (deleteLength == length)) {
+               // If whole buffer is being deleted, faster to reinitialise lines data
+               // than to delete each line.
+               //printf("Whole buffer being deleted\n");
+               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 / 2) + 1;
+               // Point all the lines after the insertion point further along in the buffer
+               for (int lineAfter = lineRemove; lineAfter <= lv.lines; lineAfter++) {
+                       lv.linesData[lineAfter].startPosition -= deleteLength / 2;
+               }
+               char chPrev = ' ';
+               if (position >= 2)
+                       chPrev = ByteAt(position - 2);
+               char chBefore = chPrev;
+               char chNext = ' ';
+               if (position < length)
+                       chNext = ByteAt(position);
+               bool ignoreNL = false;
+               if (chPrev == '\r' && chNext == '\n') {
+                       //Platform::DebugPrintf("Deleting lf after cr, move line end to cr at %d\n", lineRemove);
+                       // Move back one
+                       lv.SetValue(lineRemove, position / 2);
+                       lineRemove++;
+                       ignoreNL = true;        // First \n is not real deletion
+               }
+
+               char ch = chNext;
+               for (int i = 0; i < deleteLength; i += 2) {
+                       chNext = ' ';
+                       if ((position + i + 2) < length)
+                               chNext = ByteAt(position + i + 2);
+                       //Platform::DebugPrintf("Deleting %d %x\n", i, ch);
+                       if (ch == '\r') {
+                               if (chNext != '\n') {
+                                       //Platform::DebugPrintf("Removing cr end of line\n");
+                                       lv.Remove(lineRemove);
+                               }
+                       } else if ((ch == '\n') && !ignoreNL) {
+                               //Platform::DebugPrintf("Removing lf end of line\n");
+                               lv.Remove(lineRemove);
+                               ignoreNL = false;       // Further \n are not real deletions
+                       }
+
+                       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 = ' ';
+               if ((position + deleteLength) < length)
+                       chAfter = ByteAt(position + deleteLength);
+               if (chBefore == '\r' && chAfter == '\n') {
+                       //d.printf("Joining cr before lf at %d\n", lineRemove);
+                       // Using lineRemove-1 as cr ended line before start of deletion
+                       lv.Remove(lineRemove - 1);
+                       lv.SetValue(lineRemove - 1, position / 2 + 1);
+               }
+       }
+       GapTo(position);
+       length -= deleteLength;
+       gaplen += deleteLength;
+       part2body = body + gaplen;
+}
+
+undoCollectionType CellBuffer::SetUndoCollection(undoCollectionType collectUndo) {
+       collectingUndo = collectUndo;
+       undoSequenceDepth = 0;
+       return collectingUndo;
+}
+
+bool CellBuffer::IsCollectingUndo() {
+       return collectingUndo;
+}
+
+void CellBuffer::AppendUndoStartAction() {
+       EnsureUndoRoom();
+       // Finish any currently active undo sequence
+       undoSequenceDepth = 0;
+       if (actions[currentAction].at != startAction) {
+               undoSequenceDepth++;
+               currentAction++;
+               actions[currentAction].Create(startAction);
+               maxAction = currentAction;
+       }
+}
+
+void CellBuffer::BeginUndoAction() {
+       EnsureUndoRoom();
+       if (undoSequenceDepth == 0) {
+               if (actions[currentAction].at != startAction) {
+                       currentAction++;
+                       actions[currentAction].Create(startAction);
+                       maxAction = currentAction;
+               }
+       }
+       undoSequenceDepth++;
+}
+
+void CellBuffer::EndUndoAction() {
+       EnsureUndoRoom();
+       undoSequenceDepth--;
+       if (0 == undoSequenceDepth) {
+               if (actions[currentAction].at != startAction) {
+                       currentAction++;
+                       actions[currentAction].Create(startAction);
+                       maxAction = currentAction;
+               }
+       }
+}
+
+void CellBuffer::DeleteUndoHistory() {
+       for (int i = 1; i < maxAction; i++)
+               actions[i].Destroy();
+       maxAction = 0;
+       currentAction = 0;
+       savePoint = 0;
+}
+
+bool CellBuffer::CanUndo() {
+       return (!readOnly) && ((currentAction > 0) && (maxAction > 0));
+}
+
+int CellBuffer::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 &CellBuffer::UndoStep() {
+       const Action &actionStep = actions[currentAction];
+       if (actionStep.at == insertAction) {
+               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+       } else if (actionStep.at == removeAction) {
+               char *styledData = new char[actionStep.lenData * 2];
+               for (int i = 0; i < actionStep.lenData; i++) {
+                       styledData[i*2] = actionStep.data[i];
+                       styledData[i*2+1] = 0;
+               }
+               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               delete []styledData;
+       }
+       currentAction--;
+       return actionStep;
+}
+
+bool CellBuffer::CanRedo() {
+       return (!readOnly) && (maxAction > currentAction);
+}
+
+int CellBuffer::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 &CellBuffer::RedoStep() {
+       const Action &actionStep = actions[currentAction];
+       if (actionStep.at == insertAction) {
+               char *styledData = new char[actionStep.lenData * 2];
+               for (int i = 0; i < actionStep.lenData; i++) {
+                       styledData[i*2] = actionStep.data[i];
+                       styledData[i*2+1] = 0;
+               }
+               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               delete []styledData;
+       } else if (actionStep.at == removeAction) {
+               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+       }
+       currentAction++;
+       return actionStep;
+}
+
+int CellBuffer::SetLineState(int line, int state) {
+       int stateOld = lineStates[line];
+       lineStates[line] = state;
+       return stateOld;
+}
+
+int CellBuffer::GetLineState(int line) {
+       return lineStates[line];
+}
+
+int CellBuffer::GetMaxLineState() {
+       return lineStates.Length();
+}
+               
+int CellBuffer::SetLevel(int line, int level) {
+       int prev = 0;
+       if ((line >= 0) && (line < lv.lines)) {
+               if (!lv.levels) {
+                       lv.ExpandLevels();
+               }
+               prev = lv.levels[line];
+               if (lv.levels[line] != level) {
+                       lv.levels[line] = level;
+               }
+       }
+       return prev;
+}
+
+int CellBuffer::GetLevel(int line) {
+       if (lv.levels && (line >= 0) && (line < lv.lines)) {
+               return lv.levels[line];
+       } else {
+               return SC_FOLDLEVELBASE;
+       }
+}
+
diff --git a/src/stc/scintilla/src/CellBuffer.h b/src/stc/scintilla/src/CellBuffer.h
new file mode 100644 (file)
index 0000000..5fbe2ea
--- /dev/null
@@ -0,0 +1,197 @@
+// Scintilla source code edit control
+// CellBuffer.h - manages the text of the document
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CELLBUFFER_H
+#define CELLBUFFER_H
+
+// This holds the marker identifier and the marker type to display.
+// MarkerHandleNumbers are members of lists.
+struct MarkerHandleNumber {
+       int handle;
+       int number;
+       MarkerHandleNumber *next;
+};
+
+// A marker handle set contains any number of MarkerHandleNumbers
+class MarkerHandleSet {
+       MarkerHandleNumber *root;
+public:
+       MarkerHandleSet();
+       ~MarkerHandleSet();
+       int Length();
+       int NumberFromHandle(int handle);
+       int MarkValue();        // Bit set of marker numbers
+       bool Contains(int handle);
+       bool InsertHandle(int handle, int markerNum);
+       void RemoveHandle(int handle);
+       void RemoveNumber(int markerNum);
+       void CombineWith(MarkerHandleSet *other);
+};
+
+// Each line stores the starting position of the first character of the line in the cell buffer
+// and potentially a marker handle set. Often a line will not have any attached markers.
+struct LineData {
+       int startPosition;
+       MarkerHandleSet *handleSet;
+       LineData() : startPosition(0), handleSet(0) {
+       }
+};
+
+// The line vector contains information about each of the lines in a cell buffer.
+class LineVector {
+public:
+       enum { growSize = 4000 };
+       int lines;
+       LineData *linesData;
+       int size;
+       int *levels;
+       int sizeLevels;
+       
+       // Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
+       int handleCurrent;
+       
+       LineVector();
+       ~LineVector();
+       void Init();
+
+       void Expand(int sizeNew);
+       void ExpandLevels(int sizeNew=-1);
+       void InsertValue(int pos, int value);
+       void SetValue(int pos, int value);
+       void Remove(int pos);
+       int LineFromPosition(int pos);
+       
+       int AddMark(int line, int marker);
+       void MergeMarkers(int pos);
+       void DeleteMark(int line, int markerNum);
+       void DeleteMarkFromHandle(int markerHandle);
+       int LineFromHandle(int markerHandle);
+};
+
+// Actions are used to store all the information required to perform one undo/redo step.
+enum actionType { insertAction, removeAction, startAction };
+
+class Action {
+public:
+       actionType at;
+       int position;
+       char *data;
+       int lenData;
+
+       Action();
+       ~Action();
+       void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0);
+       void Destroy();
+       void Grab(Action *source);
+};
+
+enum undoCollectionType { undoCollectNone, undoCollectAutoStart, undoCollectManualStart };
+
+// Holder for an expandable array of characters that supports undo and line markers
+// Based on article "Data Structures in a Bit-Mapped Text Editor"
+// by Wilfred J. Hansen, Byte January 1987, page 183
+class CellBuffer {
+private:
+       char *body;
+       int size;
+       int length;
+       int part1len;
+       int gaplen;
+       char *part2body;
+       bool readOnly;
+
+       Action *actions;
+       int lenActions;
+       int maxAction;
+       int currentAction;
+       undoCollectionType collectingUndo;
+       int undoSequenceDepth;
+       int savePoint;
+
+       LineVector lv;
+
+       SVector<int, 4000> lineStates;
+
+       void GapTo(int position);
+       void RoomFor(int insertionLength);
+
+       void EnsureUndoRoom();
+       void AppendAction(actionType at, int position, char *data, int length);
+
+       inline char ByteAt(int position);
+       void SetByteAt(int position, char ch);
+
+public:
+
+       CellBuffer(int initialLength = 4000);
+       ~CellBuffer();
+       
+       // Retrieving positions outside the range of the buffer works and returns 0
+       char CharAt(int position);
+       void GetCharRange(char *buffer, int position, int lengthRetrieve);
+       char StyleAt(int position);
+       
+       int ByteLength();
+       int Length();
+       int Lines();
+       int LineStart(int line);
+       int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
+       const char *InsertString(int position, char *s, int insertLength);
+       void InsertCharStyle(int position, char ch, char style);
+       
+       // Setting styles for positions outside the range of the buffer is safe and has no effect.
+       // True is returned if the style of a character changed.
+       bool SetStyleAt(int position, char style, char mask=(char)0xff);
+       bool SetStyleFor(int position, int length, char style, char mask);
+       
+       const char *DeleteChars(int position, int deleteLength);
+
+       bool IsReadOnly();
+       void SetReadOnly(bool set);
+
+       // The save point is a marker in the undo stack where the container has stated that 
+       // the buffer was saved. Undo and redo can move over the save point.
+       void SetSavePoint();
+       bool IsSavePoint();
+
+       // Line marker functions
+       int AddMark(int line, int markerNum);
+       void DeleteMark(int line, int markerNum);
+       void DeleteMarkFromHandle(int markerHandle);
+       int GetMark(int line);
+       void DeleteAllMarks(int markerNum);
+       int LineFromHandle(int markerHandle);
+       // Without undo
+       void BasicInsertString(int position, char *s, int insertLength);
+       void BasicDeleteChars(int position, int deleteLength);
+
+       undoCollectionType SetUndoCollection(undoCollectionType collectUndo);
+       bool IsCollectingUndo();
+       void AppendUndoStartAction();
+       void BeginUndoAction();
+       void EndUndoAction();
+       void DeleteUndoHistory();
+       
+       // To perform an undo, StartUndo is called to retreive the number of steps, then UndoStep is 
+       // called that many times. Similarly for redo.
+       bool CanUndo();
+       int StartUndo();
+       const Action &UndoStep();
+       bool CanRedo();
+       int StartRedo();
+       const Action &RedoStep();
+       
+       int SetLineState(int line, int state);
+       int GetLineState(int line);
+       int GetMaxLineState();
+               
+       int SetLevel(int line, int level);
+       int GetLevel(int line);
+};
+
+#define CELL_SIZE      2
+
+#endif
diff --git a/src/stc/scintilla/src/ContractionState.cxx b/src/stc/scintilla/src/ContractionState.cxx
new file mode 100644 (file)
index 0000000..6f41461
--- /dev/null
@@ -0,0 +1,203 @@
+// Scintilla source code edit control
+// ContractionState.cxx - manages visibility of lines for folding
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include "Platform.h"
+
+#include "ContractionState.h"
+
+OneLine::OneLine() {
+       displayLine = 0;
+       docLine = 0;
+       visible = true;
+       expanded = true;
+}
+
+ContractionState::ContractionState() {
+       lines = 0;
+       size = 0;
+       linesInDoc = 1;
+       linesInDisplay = 1;
+       valid = false;
+}
+
+ContractionState::~ContractionState() {
+       Clear();
+}
+
+void ContractionState::MakeValid() const {
+       if (!valid) {
+               // Could be cleverer by keeping the index of the last still valid entry 
+               // rather than invalidating all.
+               int linePrev = -1;
+               int lineDisplay = 0;
+               for (int line=0; line<linesInDoc; line++) {
+                       lines[line].displayLine = lineDisplay;
+                       if (lines[line].visible) {
+                               lines[lineDisplay].docLine = line;
+                               lineDisplay++;
+                       }
+               }
+               valid = true;
+       }
+}
+
+void ContractionState::Clear() {
+       delete []lines;
+       lines = 0;
+       size = 0;
+       linesInDoc = 1;
+       linesInDisplay = 1;
+}
+
+int ContractionState::LinesInDoc() const {
+       return linesInDoc;
+}
+
+int ContractionState::LinesDisplayed() const {
+       return linesInDisplay;
+}
+
+int ContractionState::DisplayFromDoc(int lineDoc) const {
+       if (size == 0) {
+               return lineDoc;
+       }
+       MakeValid();
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].displayLine;
+       }
+       return -1;
+}
+
+int ContractionState::DocFromDisplay(int lineDisplay) const {
+       if (lineDisplay <= 0)
+               return 0;
+       if (lineDisplay >= linesInDisplay)
+               return linesInDoc-1;
+       if (size == 0)
+               return lineDisplay;
+       MakeValid();
+       return lines[lineDisplay].docLine;
+}
+
+void ContractionState::Grow(int sizeNew) {
+       OneLine *linesNew = new OneLine[sizeNew];
+       if (linesNew) {
+               int i = 0;
+               for (; i < size; i++) {
+                       linesNew[i] = lines[i];
+               }
+               for (; i < sizeNew; i++) {
+                       linesNew[i].displayLine = i;
+               }
+               delete []lines;
+               lines = linesNew;
+               size = sizeNew;
+               valid = false;
+       } else {
+               Platform::DebugPrintf("No memory available\n");
+               // TODO: Blow up
+       }
+}
+
+void ContractionState::InsertLines(int lineDoc, int lineCount) {
+       if (size == 0) {
+               linesInDoc += lineCount;
+               linesInDisplay += lineCount;
+               return;
+       }
+       //Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
+       if ((linesInDoc + 2) >= size) {
+               Grow(size + growSize);
+       }
+       linesInDoc += lineCount;
+       linesInDisplay += lineCount;
+       for (int i = linesInDoc + 1; i >= lineDoc + lineCount; i--) {
+               lines[i].visible = lines[i - lineCount].visible;
+               lines[i].expanded = lines[i - lineCount].expanded;
+       }
+       for (int d=0;d<lineCount;d++) {
+               lines[lineDoc+d].visible = true;        // Should inherit visibility from context ?
+               lines[lineDoc+d].expanded = true;
+       }
+       valid = false;
+}
+
+void ContractionState::DeleteLines(int lineDoc, int lineCount) {
+       if (size == 0) {
+               linesInDoc -= lineCount;
+               linesInDisplay -= lineCount;
+               return;
+       }
+       int delta = 0;
+       for (int d=0;d<lineCount;d++)
+               if (lines[lineDoc+d].visible)
+                       delta--;
+       for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
+               lines[i].visible = lines[i + lineCount].visible;
+               lines[i].expanded = lines[i + lineCount].expanded;
+       }
+       linesInDoc -= lineCount;
+       linesInDisplay += delta;
+       valid = false;
+}
+
+bool ContractionState::GetVisible(int lineDoc) const {
+       if (size == 0)
+               return true;
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].visible;
+       } else {
+               return false;
+       }
+}
+
+bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
+       if (size == 0) {
+               Grow(lineDocEnd + growSize);
+       }
+       // TODO: modify docLine members to mirror displayLine
+       int delta = 0;
+       // Change lineDocs
+       if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
+               for (int line=lineDocStart; line <= lineDocEnd; line++) {
+                       if (lines[line].visible != visible) {
+                               delta += visible ? 1 : -1;              
+                               lines[line].visible = visible;
+                       }
+                       lines[line].displayLine += delta;
+               }
+               if (delta != 0) {
+                       for (int line=lineDocEnd+1; line <= linesInDoc; line++) {
+                               lines[line].displayLine += delta;
+                       }
+               }
+       }
+       linesInDisplay += delta;
+       valid = false;
+       return delta != 0;
+}
+
+bool ContractionState::GetExpanded(int lineDoc) const {
+       if (size == 0) 
+               return true;
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               return lines[lineDoc].expanded;
+       } else {
+               return false;
+       }
+}
+
+bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
+       if (size == 0) {
+               Grow(lineDoc + growSize);
+       }
+       if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
+               if (lines[lineDoc].expanded != expanded) {
+                       lines[lineDoc].expanded = expanded;
+                       return true;
+               }
+       }
+       return false;
+}
diff --git a/src/stc/scintilla/src/ContractionState.h b/src/stc/scintilla/src/ContractionState.h
new file mode 100644 (file)
index 0000000..9e17a76
--- /dev/null
@@ -0,0 +1,50 @@
+// Scintilla source code edit control
+// ContractionState.h - manages visibility of lines for folding
+// Copyright 1998-2000 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
+
+class OneLine {
+public:
+       int displayLine;        // position within set of visible lines
+       int docLine;            // inverse of displayLine
+       bool visible;
+       bool expanded;
+       
+       OneLine();
+       virtual ~OneLine() {}
+};
+
+class ContractionState {
+       void Grow(int sizeNew);
+       enum { growSize = 4000 };
+       int linesInDoc;
+       int linesInDisplay;
+       mutable OneLine *lines;
+       int size;
+       mutable bool valid;
+       void MakeValid() const;
+public:
+       ContractionState();
+       virtual ~ContractionState();
+       
+       void Clear();
+       
+       int LinesInDoc() const; 
+       int LinesDisplayed() const;     
+       int DisplayFromDoc(int lineDoc) const;
+       int DocFromDisplay(int lineDisplay) const;
+       
+       void InsertLines(int lineDoc, int lineCount);
+       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);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/Document.cxx b/src/stc/scintilla/src/Document.cxx
new file mode 100644 (file)
index 0000000..7d83224
--- /dev/null
@@ -0,0 +1,734 @@
+// Scintilla source code edit control
+// Document.cxx - text document that handles notifications, DBCS, styling, words and end of line
+// Copyright 1998-2000 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 "SVector.h"
+#include "CellBuffer.h"
+#include "Document.h"
+
+Document::Document() {
+       refCount = 0;
+#ifdef unix
+       eolMode = SC_EOL_LF;
+#else
+       eolMode = SC_EOL_CRLF;
+#endif
+       dbcsCodePage = 0;
+       stylingBits = 5;
+       stylingBitsMask = 0x1F;
+       stylingPos = 0;
+       stylingMask = 0;
+       for (int ch = 0; ch < 256; ch++) {
+               wordchars[ch] = isalnum(ch) || ch == '_';
+       }
+       endStyled = 0;
+       enteredCount = 0;
+       tabInChars = 8;
+       watchers = 0;
+       lenWatchers = 0;
+}
+
+Document::~Document() {
+       for (int i = 0; i < lenWatchers; i++) {
+               watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
+       }
+       delete []watchers;
+       watchers = 0;
+       lenWatchers = 0;
+}
+
+// Increase reference count and return its previous value.
+int Document::AddRef() {
+       return refCount++;
+}
+
+// Decrease reference count and return its provius 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::LineStart(int line) {
+       return cb.LineStart(line);
+}
+
+int Document::LineFromPosition(int pos) {
+       return cb.LineFromPosition(pos);
+}
+
+int Document::LineEndPosition(int position) {
+       int line = LineFromPosition(position);
+       if (line == LinesTotal() - 1) {
+               position = LineStart(line + 1);
+       } else {
+               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::VCHomePosition(int position) {
+       int line = LineFromPosition(position);
+       int startPosition = LineStart(line);
+       int endLine = LineStart(line + 1) - 1;
+       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, LineStart(line), 0, 0, 0);
+               mh.line = 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) && IsSubordinate(level, GetLevel(lineMaxSubord+1))) {
+               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 ((lineMaxSubord > lineParent) && (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG)) {
+                               lineMaxSubord--;
+                       }
+               }
+       }
+       return lineMaxSubord;
+}
+
+int Document::GetFoldParent(int line) {
+       int level = GetLevel(line);
+       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');
+}
+
+bool Document::IsDBCS(int pos) {
+#if PLAT_WIN
+       if (dbcsCodePage) {
+               // Anchor DBCS calculations at start of line because start of line can
+               // not be a DBCS trail byte.
+               int startLine = pos;
+               while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
+                       startLine--;
+               while (startLine <= pos) {
+                       if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) {
+                               startLine++;
+                               if (startLine >= pos)
+                                       return true;
+                       }
+                       startLine++;
+               }
+       }
+       return false;
+#else
+       return false;
+#endif
+}
+
+// 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 value - should be fixed up after
+       if (pos < 0)
+               return pos;
+       if (pos > Length())
+               return pos;
+
+       // Position 0 and Length() can not be between any two characters
+       if (pos == 0)
+               return pos;
+       if (pos == Length())
+               return pos;
+
+       // 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 PLAT_WIN
+       if (dbcsCodePage) {
+               // Anchor DBCS calculations at start of line because start of line can
+               // not be a DBCS trail byte.
+               int startLine = pos;
+               while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n')
+                       startLine--;
+               bool atLeadByte = false;
+               while (startLine < pos) {
+                       if (atLeadByte)
+                               atLeadByte = false;
+                       else if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine)))
+                               atLeadByte = true;
+                       else
+                               atLeadByte = false;
+                       startLine++;
+                       //Platform::DebugPrintf("DBCS %s\n", atlead ? "D" : "-");
+               }
+
+               if (atLeadByte) {
+                       // Position is between a lead byte and a trail byte
+                       if (moveDir > 0)
+                               return pos + 1;
+                       else
+                               return pos - 1;
+               }
+       }
+#endif
+
+       return pos;
+}
+
+void Document::ModifiedAt(int pos) {
+       if (endStyled > pos)
+               endStyled = pos;
+}
+
+// Document only modified by gateways DeleteChars, InsertStyledString, Undo, Redo, and SetStyleAt.
+// SetStyleAt does not change the persistent state of a document
+
+// Unlike Undo, Redo, and InsertStyledString, the pos argument is a cell number not a char number
+void Document::DeleteChars(int pos, int len) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               if (cb.IsReadOnly())
+                       NotifyModifyAttempt();
+               if (!cb.IsReadOnly()) {
+                       int prevLinesTotal = LinesTotal();
+                       bool startSavePoint = cb.IsSavePoint();
+                       const char *text = cb.DeleteChars(pos*2, len * 2);
+                       if (startSavePoint && cb.IsCollectingUndo())
+                               NotifySavePoint(!startSavePoint);
+                       ModifiedAt(pos);
+                       int modFlags = SC_MOD_DELETETEXT | SC_PERFORMED_USER;
+                       DocModification mh(modFlags, pos, len, LinesTotal() - prevLinesTotal, text);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+void Document::InsertStyledString(int position, char *s, int insertLength) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               if (cb.IsReadOnly())
+                       NotifyModifyAttempt();
+               if (!cb.IsReadOnly()) {
+                       int prevLinesTotal = LinesTotal();
+                       bool startSavePoint = cb.IsSavePoint();
+                       const char *text = cb.InsertString(position, s, insertLength);
+                       if (startSavePoint && cb.IsCollectingUndo())
+                               NotifySavePoint(!startSavePoint);
+                       ModifiedAt(position / 2);
+       
+                       int modFlags = SC_MOD_INSERTTEXT | SC_PERFORMED_USER;
+                       DocModification mh(modFlags, position / 2, insertLength / 2, LinesTotal() - prevLinesTotal, text);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+int Document::Undo() {
+       int newPos = 0;
+       if (enteredCount == 0) {
+               enteredCount++;
+               bool startSavePoint = cb.IsSavePoint();
+               int steps = cb.StartUndo();
+               for (int step=0; step<steps; step++) {
+                       int prevLinesTotal = LinesTotal();
+                       const Action &action = cb.UndoStep();
+                       int cellPosition = action.position / 2;
+                       ModifiedAt(cellPosition);
+                       newPos = cellPosition;
+                       
+                       int modFlags = SC_PERFORMED_UNDO;
+                       // With undo, an insertion action becomes a deletion notification
+                       if (action.at == removeAction) {
+                               newPos += action.lenData;
+                               modFlags |= SC_MOD_INSERTTEXT;
+                       } else {
+                               modFlags |= SC_MOD_DELETETEXT;
+                       }
+                       if (step == steps-1)
+                               modFlags |= SC_LASTSTEPINUNDOREDO;
+                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData, 
+                               LinesTotal() - prevLinesTotal, action.data));
+               }
+       
+               bool endSavePoint = cb.IsSavePoint();
+               if (startSavePoint != endSavePoint)
+                       NotifySavePoint(endSavePoint);
+               enteredCount--;
+       }
+       return newPos;
+}
+
+int Document::Redo() {
+       int newPos = 0;
+       if (enteredCount == 0) {
+               enteredCount++;
+               bool startSavePoint = cb.IsSavePoint();
+               int steps = cb.StartRedo();
+               for (int step=0; step<steps; step++) {
+                       int prevLinesTotal = LinesTotal();
+                       const Action &action = cb.RedoStep();
+                       int cellPosition = action.position / 2;
+                       ModifiedAt(cellPosition);
+                       newPos = cellPosition;
+                       
+                       int modFlags = SC_PERFORMED_REDO;
+                       if (action.at == insertAction) {
+                               newPos += action.lenData;
+                               modFlags |= SC_MOD_INSERTTEXT;
+                       } else {
+                               modFlags |= SC_MOD_DELETETEXT;
+                       }
+                       if (step == steps-1)
+                               modFlags |= SC_LASTSTEPINUNDOREDO;
+                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData, 
+                               LinesTotal() - prevLinesTotal, action.data));
+               }
+       
+               bool endSavePoint = cb.IsSavePoint();
+               if (startSavePoint != endSavePoint)
+                       NotifySavePoint(endSavePoint);
+               enteredCount--;
+       }
+       return newPos;
+}
+
+void Document::InsertChar(int pos, char ch) {
+       char chs[2];
+       chs[0] = ch;
+       chs[1] = 0;
+       InsertStyledString(pos*2, chs, 2);
+}
+
+// Insert a null terminated string
+void Document::InsertString(int position, const char *s) {
+       InsertString(position, s, strlen(s));
+}
+
+// Insert a string with a length
+void Document::InsertString(int position, const char *s, int insertLength) {
+       char *sWithStyle = new char[insertLength * 2];
+       if (sWithStyle) {
+               for (int i = 0; i < insertLength; i++) {
+                       sWithStyle[i*2] = s[i];
+                       sWithStyle[i*2 + 1] = 0;
+               }
+               InsertStyledString(position*2, sWithStyle, insertLength*2);
+               delete []sWithStyle;
+       }
+}
+
+void Document::DelChar(int pos) {
+       if (IsCrLf(pos)) {
+               DeleteChars(pos, 2);
+       } else if (IsDBCS(pos)) {
+               DeleteChars(pos, 2);
+       } else if (pos < Length()) {
+               DeleteChars(pos, 1);
+       }
+}
+
+int Document::DelCharBack(int pos) {
+       if (pos <= 0) {
+               return pos;
+       } else if (IsCrLf(pos - 2)) {
+               DeleteChars(pos - 2, 2);
+               return pos - 2;
+       } else if (IsDBCS(pos - 1)) {
+               DeleteChars(pos - 2, 2);
+               return pos - 2;
+       } else {
+               DeleteChars(pos - 1, 1);
+               return pos - 1;
+       }
+}
+
+void Document::Indent(bool forwards, int lineBottom, int lineTop) {
+       if (forwards) {
+               // Indent by a tab
+               for (int line = lineBottom; line >= lineTop; line--) {
+                       InsertChar(LineStart(line), '\t');
+               }
+       } else {
+               // 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 ispc = 0;
+                       while (ispc < tabInChars && cb.CharAt(LineStart(line) + ispc) == ' ')
+                               ispc++;
+                       int posStartLine = LineStart(line);
+                       if (ispc == tabInChars) {
+                               DeleteChars(posStartLine, ispc);
+                       } else if (cb.CharAt(posStartLine + ispc) == '\t') {
+                               DeleteChars(posStartLine, ispc + 1);
+                       } else {        // Hit a non-white
+                               DeleteChars(posStartLine, ispc);
+                       }
+               }
+       }
+}
+
+void Document::ConvertLineEnds(int eolModeSet) {
+       BeginUndoAction();
+       for (int pos = 0; pos < Length(); pos++) {
+               if (cb.CharAt(pos) == '\r') {
+                       if (cb.CharAt(pos+1) == '\n') {
+                               if (eolModeSet != SC_EOL_CRLF) {
+                                       DeleteChars(pos, 2);
+                                       if (eolModeSet == SC_EOL_CR)
+                                               InsertString(pos, "\r", 1);
+                                       else
+                                               InsertString(pos, "\n", 1);
+                               } else {
+                                       pos++;
+                               }
+                       } else {
+                               if (eolModeSet != SC_EOL_CR) {
+                                       DeleteChars(pos, 1);
+                                       if (eolModeSet == SC_EOL_CRLF) {
+                                               InsertString(pos, "\r\n", 2);
+                                               pos++;
+                                       } else {
+                                               InsertString(pos, "\n", 1);
+                                       }
+                               }
+                       }
+               } else if (cb.CharAt(pos) == '\n') {
+                       if (eolModeSet != SC_EOL_LF) {
+                               DeleteChars(pos, 1);
+                               if (eolModeSet == SC_EOL_CRLF) {
+                                       InsertString(pos, "\r\n", 2);
+                                       pos++;
+                               } else {
+                                       InsertString(pos, "\r", 1);
+                               }
+                       }
+               }
+       }
+       EndUndoAction();
+}
+
+bool Document::IsWordChar(unsigned char ch) {
+       return wordchars[ch];
+}
+
+int Document::ExtendWordSelect(int pos, int delta) {
+       if (delta < 0) {
+               while (pos > 0 && IsWordChar(cb.CharAt(pos - 1)))
+                       pos--;
+       } else {
+               while (pos < (Length()) && IsWordChar(cb.CharAt(pos)))
+                       pos++;
+       }
+       return pos;
+}
+
+int Document::NextWordStart(int pos, int delta) {
+       if (delta < 0) {
+               while (pos > 0 && (cb.CharAt(pos - 1) == ' ' || cb.CharAt(pos - 1) == '\t'))
+                       pos--;
+               if (isspace(cb.CharAt(pos - 1))) {      // Back up to previous line
+                       while (pos > 0 && isspace(cb.CharAt(pos - 1)))
+                               pos--;
+               } else {
+                       bool startAtWordChar = IsWordChar(cb.CharAt(pos - 1));
+                       while (pos > 0 && !isspace(cb.CharAt(pos - 1)) && (startAtWordChar == IsWordChar(cb.CharAt(pos - 1))))
+                               pos--;
+               }
+       } else {
+               bool startAtWordChar = IsWordChar(cb.CharAt(pos));
+               while (pos < (Length()) && isspace(cb.CharAt(pos)))
+                       pos++;
+               while (pos < (Length()) && !isspace(cb.CharAt(pos)) && (startAtWordChar == IsWordChar(cb.CharAt(pos))))
+                       pos++;
+               while (pos < (Length()) && (cb.CharAt(pos) == ' ' || cb.CharAt(pos) == '\t'))
+                       pos++;
+       }
+       return pos;
+}
+
+bool Document::IsWordAt(int start, int end) {
+       int lengthDoc = Length();
+       if (start > 0) {
+               char ch = CharAt(start - 1);
+               if (IsWordChar(ch))
+                       return false;
+       }
+       if (end < lengthDoc - 1) {
+               char ch = CharAt(end);
+               if (IsWordChar(ch))
+                       return false;
+       }
+       return true;
+}
+
+// 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 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 = strlen(s);
+       int endSearch = 0;
+       if (startPos <= endPos) {
+               endSearch = endPos - lengthFind + 1;
+       } else {
+               endSearch = endPos;
+       }
+       //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
+       char firstChar = s[0];
+       if (!caseSensitive)
+               firstChar = toupper(firstChar);
+       int pos = startPos;
+       while (forward ? (pos < endSearch) : (pos >= endSearch)) {
+               char ch = CharAt(pos);
+               if (caseSensitive) {
+                       if (ch == firstChar) {
+                               bool found = true;
+                               for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+                                       ch = CharAt(pos + posMatch);
+                                       if (ch != s[posMatch])
+                                               found = false;
+                               }
+                               if (found) {
+                                       if ((!word) || IsWordAt(pos, pos + lengthFind))
+                                               return pos;
+                               }
+                       }
+               } else {
+                       if (toupper(ch) == firstChar) {
+                               bool found = true;
+                               for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
+                                       ch = CharAt(pos + posMatch);
+                                       if (toupper(ch) != toupper(s[posMatch]))
+                                               found = false;
+                               }
+                               if (found) {
+                                       if ((!word) || IsWordAt(pos, pos + lengthFind))
+                                               return pos;
+                               }
+                       }
+               }
+               pos += increment;
+               if (dbcsCodePage) {
+                       // Ensure trying to match from start of character
+                       pos = MovePositionOutsideChar(pos, increment, false);
+               }
+       }
+       //Platform::DebugPrintf("Not found\n");
+       return - 1;
+}
+
+int Document::LinesTotal() {
+       return cb.Lines();
+}
+
+void Document::SetWordChars(unsigned char *chars) {
+       int ch;
+       for (ch = 0; ch < 256; ch++) {
+               wordchars[ch] = false;
+       }
+       if (chars) {
+               while (*chars) {
+                       wordchars[*chars] = true;
+                       chars++;
+               }
+       } else {
+               for (ch = 0; ch < 256; ch++) {
+                       wordchars[ch] = isalnum(ch) || ch == '_';
+               }
+       }
+}
+
+void Document::SetStylingBits(int bits) {
+       stylingBits = bits;
+       stylingBitsMask = 0;
+       for (int bit=0; bit<stylingBits; bit++) {
+               stylingBitsMask <<= 1;
+               stylingBitsMask |= 1;
+       }
+}
+
+void Document::StartStyling(int position, char mask) {
+       stylingPos = position;
+       stylingMask = mask;
+}
+
+void Document::SetStyleFor(int length, char style) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               int prevEndStyled = endStyled;
+               if (cb.SetStyleFor(stylingPos, length, style, stylingMask)) {
+                       DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, 
+                               prevEndStyled, length);
+                       NotifyModified(mh);
+               }
+               stylingPos += length;
+               endStyled = stylingPos;
+               enteredCount--;
+       }
+}
+
+void Document::SetStyles(int length, char *styles) {
+       if (enteredCount == 0) {
+               enteredCount++;
+               int prevEndStyled = endStyled;
+               bool didChange = false;
+               for (int iPos = 0; iPos < length; iPos++, stylingPos++) {
+                       if (cb.SetStyleAt(stylingPos, styles[iPos], stylingMask)) {
+                               didChange = true;
+                       }
+               }
+               endStyled = stylingPos;
+               if (didChange) {
+                       DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, 
+                               prevEndStyled, endStyled - prevEndStyled);
+                       NotifyModified(mh);
+               }
+               enteredCount--;
+       }
+}
+
+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) {
+       for (int i = 0; i < lenWatchers; i++) {
+               watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
+       }
+}
diff --git a/src/stc/scintilla/src/Document.h b/src/stc/scintilla/src/Document.h
new file mode 100644 (file)
index 0000000..fba611c
--- /dev/null
@@ -0,0 +1,222 @@
+// Scintilla source code edit control
+// Document.h - text document that handles notifications, DBCS, styling, words and end of line
+// Copyright 1998-2000 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
+
+// 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);
+       }
+       
+       bool Contains(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 {
+
+public:
+       // Used to pair watcher pointer with user data
+       class WatcherWithUserData {
+       public:
+               DocWatcher *watcher;
+               void *userData;
+               WatcherWithUserData() {
+                       watcher = 0;
+                       userData = 0;
+               }
+       };
+       
+private:       
+       int refCount;
+       CellBuffer cb;
+       bool wordchars[256];
+       int stylingPos;
+       int stylingMask;
+       int endStyled;
+       int enteredCount;
+       
+       WatcherWithUserData *watchers;
+       int lenWatchers;
+       
+public:
+       int stylingBits;
+       int stylingBitsMask;
+       
+       int eolMode;
+       int dbcsCodePage;
+       int tabInChars;
+       
+       Document();
+       virtual ~Document();
+       
+       int AddRef();
+       int Release();
+       
+       int LineFromPosition(int pos);
+       int ClampPositionIntoDocument(int pos);
+       bool IsCrLf(int pos);
+       int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
+
+       // Gateways to modifying document
+       void DeleteChars(int pos, int len);
+       void InsertStyledString(int position, char *s, int insertLength);
+       int Undo();
+       int Redo();
+       bool CanUndo() { return cb.CanUndo(); }
+       bool CanRedo() { return cb.CanRedo(); }
+       void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
+       undoCollectionType SetUndoCollection(undoCollectionType collectUndo) {
+               return cb.SetUndoCollection(collectUndo);
+       }
+       void AppendUndoStartAction() { cb.AppendUndoStartAction(); }
+       void BeginUndoAction() { cb.BeginUndoAction(); }
+       void EndUndoAction() { cb.EndUndoAction(); }
+       void SetSavePoint();
+       bool IsSavePoint() { return cb.IsSavePoint(); }
+       void Indent(bool forwards, int lineBottom, int lineTop);
+       void ConvertLineEnds(int eolModeSet);
+       void SetReadOnly(bool set) { cb.SetReadOnly(set); }
+
+       void InsertChar(int pos, char ch);
+       void InsertString(int position, const char *s);
+       void InsertString(int position, const char *s, int insertLength);
+       void DelChar(int pos);
+       int 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) { return cb.AddMark(line, markerNum); }
+       void DeleteMark(int line, int markerNum) { cb.DeleteMark(line, markerNum); }
+       void DeleteMarkFromHandle(int markerHandle) { cb.DeleteMarkFromHandle(markerHandle); }
+       void DeleteAllMarks(int markerNum) { cb.DeleteAllMarks(markerNum); }
+       int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
+       int LineStart(int line);
+       int LineEndPosition(int position);
+       int VCHomePosition(int position);
+
+       int SetLevel(int line, int level);
+       int GetLevel(int line) { return cb.GetLevel(line); }
+       int GetLastChild(int lineParent, int level=-1);
+       int GetFoldParent(int line);
+
+       void Indent(bool forwards);
+       int ExtendWordSelect(int pos, int delta);
+       int NextWordStart(int pos, int delta);
+       int Length() { return cb.Length(); }
+       long FindText(int minPos, int maxPos, const char *s, bool caseSensitive, bool word);
+       long FindText(WORD iMessage,WPARAM wParam,LPARAM lParam);
+       int LinesTotal();
+       
+       void SetWordChars(unsigned char *chars);
+       void SetStylingBits(int bits);
+       void StartStyling(int position, char mask);
+       void SetStyleFor(int length, char style);
+       void SetStyles(int length, char *styles);
+       int GetEndStyled() { return endStyled; }
+
+       int SetLineState(int line, int state) { return cb.SetLineState(line, 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; }
+       
+private:
+       bool IsDBCS(int pos);
+       bool IsWordChar(unsigned char ch);
+       bool IsWordAt(int start, int end);
+       void ModifiedAt(int pos);
+               
+       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) :
+               modificationType(modificationType_),
+               position(position_),
+               length(length_),
+               linesAdded(linesAdded_),
+               text(text_),
+               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;
+};
+
+#endif
diff --git a/src/stc/scintilla/src/Editor.cxx b/src/stc/scintilla/src/Editor.cxx
new file mode 100644 (file)
index 0000000..6508c95
--- /dev/null
@@ -0,0 +1,3693 @@
+// Scintilla source code edit control
+// Editor.cxx - main code for the edit control
+// Copyright 1998-2000 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 "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "Document.h"
+#include "Editor.h"
+
+Caret::Caret() :
+active(true), on(true), period(500) {}
+
+Timer::Timer() :
+ticking(false), ticksToWait(0), tickerID(0) {}
+
+Editor::Editor() {
+       ctrlID = 0;
+
+       stylesValid = false;
+
+       hideSelection = false;
+       inOverstrike = false;
+
+       bufferedDraw = true;
+
+       lastClickTime = 0;
+       ptMouseLast.x = 0;
+       ptMouseLast.y = 0;
+       firstExpose = true;
+       inDragDrop = false;
+       dropWentOutside = false;
+       posDrag = invalidPosition;
+       posDrop = invalidPosition;
+       selectionType = selChar;
+
+       lastXChosen = 0;
+       lineAnchor = 0;
+       originalAnchorPos = 0;
+
+       dragChars = 0;
+       lenDrag = 0;
+       dragIsRectangle = false;
+       selType = selStream;
+       xStartSelect = 0;
+       xEndSelect = 0;
+
+       caretPolicy = CARET_SLOP;
+       caretSlop = 0;
+
+       searchAnchor = 0;
+       
+       ucWheelScrollLines = 0;
+       cWheelDelta = 0;   //wheel delta from roll
+
+       xOffset = 0;
+       xCaretMargin = 50;
+       
+       currentPos = 0;
+       anchor = 0;
+
+       topLine = 0;
+       posTopLine = 0;
+       
+       needUpdateUI = true;
+       braces[0]=invalidPosition;
+       braces[1]=invalidPosition;
+       bracesMatchStyle = STYLE_BRACEBAD;
+       
+       edgeState = EDGE_NONE;
+       theEdge = 0;
+       
+       paintState = notPainting;
+       
+       modEventMask = SC_MODEVENTMASKALL;
+
+       pdoc = new Document();
+       pdoc ->AddRef();
+       pdoc->AddWatcher(this, 0);
+
+#ifdef MACRO_SUPPORT
+       recordingMacro = 0;
+#endif
+       foldFlags = 0;
+}
+
+Editor::~Editor() {
+       pdoc->RemoveWatcher(this, 0);
+       pdoc->Release();
+       pdoc = 0;
+       DropGraphics();
+
+       delete []dragChars;
+       dragChars = 0;
+       lenDrag = 0;
+}
+
+void Editor::Finalise() {
+}
+
+void Editor::DropGraphics() {
+       pixmapLine.Release();
+       pixmapSelMargin.Release();
+       pixmapSelPattern.Release();
+}
+
+void Editor::InvalidateStyleData() {
+       stylesValid = false;
+       palette.Release();
+       DropGraphics();
+}
+
+void Editor::InvalidateStyleRedraw() {
+       InvalidateStyleData();
+       Redraw();
+}
+
+void Editor::RefreshColourPalette(Palette &pal, bool want) {
+       vs.RefreshColourPalette(pal, want);
+}
+
+void Editor::RefreshStyleData() {
+       if (!stylesValid) {
+               stylesValid = true;
+               Surface surface;
+               surface.Init();
+               vs.Refresh(surface);
+               RefreshColourPalette(palette, true);
+               palette.Allocate(wMain);
+               RefreshColourPalette(palette, false);
+               SetScrollBars();
+       }
+}
+
+PRectangle Editor::GetClientRectangle() {
+       return wDraw.GetClientPosition();
+}
+
+PRectangle Editor::GetTextRectangle() {
+       PRectangle rc = GetClientRectangle();
+       rc.left += vs.fixedColumnWidth;
+       rc.right -= vs.rightMarginWidth;
+       return rc;
+}
+
+int Editor::LinesOnScreen() {
+       PRectangle rcClient = GetClientRectangle();
+       int htClient = rcClient.bottom - rcClient.top;
+       //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
+       return htClient / vs.lineHeight;
+}
+
+int Editor::LinesToScroll() {
+       int retVal = LinesOnScreen() - 1;
+       if (retVal < 1)
+               return 1;
+       else
+               return retVal;
+}
+
+int Editor::MaxScrollPos() {
+       //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
+       //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
+       int retVal = cs.LinesDisplayed() - LinesOnScreen();
+       if (retVal < 0)
+               return 0;
+       else
+               return retVal;
+}
+
+bool IsControlCharacter(char ch) {
+       // iscntrl returns true for lots of chars > 127 which are displayable
+       return ch >= 0 && ch < ' ';
+}
+
+const char *ControlCharacterString(char ch) {
+       const char *reps[] = {
+           "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+           "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+           "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+           "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+       };
+       if (ch < (sizeof(reps) / sizeof(reps[0]))) {
+               return reps[ch];
+       } else {
+               return "BAD";
+       }
+}
+
+Point Editor::LocationFromPosition(unsigned int pos) {
+       RefreshStyleData();
+       int line = pdoc->LineFromPosition(pos);
+       int lineVisible = cs.DisplayFromDoc(line);
+       //Platform::DebugPrintf("line=%d\n", line);
+       Surface surface;
+       surface.Init();
+       Point pt;
+       pt.y = (lineVisible - topLine) * vs.lineHeight;         // + half a lineheight?
+       unsigned int posLineStart = pdoc->LineStart(line);
+       if ((pos - posLineStart) > LineLayout::maxLineLength) {
+               // very long line so put x at arbitrary large position
+               pt.x = 30000 + vs.fixedColumnWidth - xOffset;
+       } else {
+               LineLayout ll;
+               LayoutLine(line, &surface, vs, ll);
+               pt.x = ll.positions[pos - posLineStart] + vs.fixedColumnWidth - xOffset;
+       }
+       return pt;
+}
+
+int Editor::XFromPosition(unsigned int pos) {
+       Point pt = LocationFromPosition(pos);
+       return pt.x - vs.fixedColumnWidth + xOffset;
+}
+       
+int Editor::LineFromLocation(Point pt) {
+       return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+}
+
+void Editor::SetTopLine(int topLineNew) {
+       topLine = topLineNew;
+       posTopLine = pdoc->LineStart(topLine);
+}
+
+int Editor::PositionFromLocation(Point pt) {
+       RefreshStyleData();
+       pt.x = pt.x - vs.fixedColumnWidth + xOffset;
+       int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
+       if (pt.y < 0) { // Division rounds towards 0
+               line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine);
+       }
+       if (line < 0)
+               return 0;
+       if (line >= pdoc->LinesTotal())
+               return pdoc->Length();
+//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+       Surface surface;
+       surface.Init();
+       unsigned int posLineStart = pdoc->LineStart(line);
+
+       LineLayout ll;
+       LayoutLine(line, &surface, vs, ll);
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+               if (pt.x < ((ll.positions[i] + ll.positions[i + 1]) / 2) || 
+                       ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+                       return i + posLineStart;
+               }
+       }
+
+       return ll.numCharsInLine + posLineStart;
+}
+
+int Editor::PositionFromLineX(int line, int x) {
+       RefreshStyleData();
+       if (line >= pdoc->LinesTotal())
+               return pdoc->Length();
+       //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
+       Surface surface;
+       surface.Init();
+       unsigned int posLineStart = pdoc->LineStart(line);
+
+       LineLayout ll;
+       LayoutLine(line, &surface, vs, ll);
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+               if (x < ((ll.positions[i] + ll.positions[i + 1]) / 2) || 
+                       ll.chars[i] == '\r' || ll.chars[i] == '\n') {
+                       return i + posLineStart;
+               }
+       }
+
+       return ll.numCharsInLine + posLineStart;
+}
+
+void Editor::RedrawRect(PRectangle rc) {
+       //Platform::DebugPrintf("Redraw %d %d - %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
+       wDraw.InvalidateRectangle(rc);
+}
+
+void Editor::Redraw() {
+       //Platform::DebugPrintf("Redraw all\n");
+       wDraw.InvalidateAll();
+}
+
+void Editor::RedrawSelMargin() {
+       if (vs.maskInLine) {
+               Redraw();
+       } else {
+               PRectangle rcSelMargin = GetClientRectangle();
+               rcSelMargin.right = vs.fixedColumnWidth;
+               wDraw.InvalidateRectangle(rcSelMargin);
+       }
+}
+
+PRectangle Editor::RectangleFromRange(int start, int end) {
+       int minPos = start;
+       if (minPos > end)
+               minPos = end;
+       int maxPos = start;
+       if (maxPos < end)
+               maxPos = end;
+       int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
+       int maxLine = cs.DisplayFromDoc(pdoc->LineFromPosition(maxPos));
+       PRectangle rcClient = GetTextRectangle();
+       PRectangle rc;
+       rc.left = vs.fixedColumnWidth;
+       rc.top = (minLine - topLine) * vs.lineHeight;
+       if (rc.top < 0)
+               rc.top = 0;
+       rc.right = rcClient.right;
+       rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
+       // Ensure PRectangle is within 16 bit space
+       rc.top = Platform::Clamp(rc.top, -32000, 32000);
+       rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
+
+       return rc;
+}
+
+void Editor::InvalidateRange(int start, int end) {
+       RedrawRect(RectangleFromRange(start, end));
+}
+
+int Editor::CurrentPosition() {
+       return currentPos;
+}
+
+bool Editor::SelectionEmpty() {
+       return anchor == currentPos;
+}
+
+int Editor::SelectionStart(int line) {
+       if ((line == -1) || (selType == selStream)) {
+               return Platform::Minimum(currentPos, anchor);
+       } else { // selType == selRectangle
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               int lineStart = pdoc->LineFromPosition(selStart);
+               int lineEnd = pdoc->LineFromPosition(selEnd);
+               if (line < lineStart || line > lineEnd) {
+                       return -1;
+               } else {
+                       int minX = Platform::Minimum(xStartSelect, xEndSelect);
+                       //return PositionFromLineX(line, minX + vs.fixedColumnWidth - xOffset);
+                       return PositionFromLineX(line, minX);
+               }
+       } 
+}
+
+int Editor::SelectionEnd(int line) {
+       if ((line == -1) || (selType == selStream)) {
+               return Platform::Maximum(currentPos, anchor);
+       } else { // selType == selRectangle
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               int lineStart = pdoc->LineFromPosition(selStart);
+               int lineEnd = pdoc->LineFromPosition(selEnd);
+               if (line < lineStart || line > lineEnd) {
+                       return -1;
+               } else {
+                       int maxX = Platform::Maximum(xStartSelect, xEndSelect);
+                       // measure line and return character closest to minx
+                       return PositionFromLineX(line, maxX);
+               }
+       }
+}
+
+void Editor::SetSelection(int currentPos_, int anchor_) {
+       currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+       anchor_ = pdoc->ClampPositionIntoDocument(anchor_);
+       if ((currentPos != currentPos_) || (anchor != anchor_)) {
+               int firstAffected = anchor;
+               if (firstAffected > currentPos)
+                       firstAffected = currentPos;
+               if (firstAffected > anchor_)
+                       firstAffected = anchor_;
+               if (firstAffected > currentPos_)
+                       firstAffected = currentPos_;
+               int lastAffected = anchor;
+               if (lastAffected < currentPos)
+                       lastAffected = currentPos;
+               if (lastAffected < anchor_)
+                       lastAffected = anchor_;
+               if (lastAffected < (currentPos_ + 1))   // +1 ensures caret repainted
+                       lastAffected = (currentPos_ + 1);
+               currentPos = currentPos_;
+               anchor = anchor_;
+               needUpdateUI = true;
+               InvalidateRange(firstAffected, lastAffected);
+       }
+       ClaimSelection();
+}
+
+void Editor::SetSelection(int currentPos_) {
+       currentPos_ = pdoc->ClampPositionIntoDocument(currentPos_);
+       if (currentPos != currentPos_) {
+               int firstAffected = anchor;
+               if (firstAffected > currentPos)
+                       firstAffected = currentPos;
+               if (firstAffected > currentPos_)
+                       firstAffected = currentPos_;
+               int lastAffected = anchor;
+               if (lastAffected < currentPos)
+                       lastAffected = currentPos;
+               if (lastAffected < (currentPos_ + 1))   // +1 ensures caret repainted
+                       lastAffected = (currentPos_ + 1);
+               currentPos = currentPos_;
+               needUpdateUI = true;
+               InvalidateRange(firstAffected, lastAffected);
+       }
+       ClaimSelection();
+}
+
+void Editor::SetEmptySelection(int currentPos_) {
+       SetSelection(currentPos_, currentPos_);
+}
+
+int Editor::MovePositionTo(int newPos, bool extend) {
+       int delta = newPos - currentPos;
+       newPos = pdoc->ClampPositionIntoDocument(newPos);
+       newPos = pdoc->MovePositionOutsideChar(newPos, delta);
+       if (extend) {
+               SetSelection(newPos);
+       } else {
+               SetEmptySelection(newPos);
+       }
+       EnsureCaretVisible();
+       ShowCaretAtCurrentPosition();
+       return 0;
+}
+
+int Editor::MovePositionSoVisible(int pos, int moveDir) {
+       pos = pdoc->ClampPositionIntoDocument(pos);
+       pos = pdoc->MovePositionOutsideChar(pos, moveDir);
+       int lineDoc = pdoc->LineFromPosition(pos);
+       if (cs.GetVisible(lineDoc)) {
+               return pos;
+       } else {
+               int lineDisplay = cs.DisplayFromDoc(lineDoc);
+               if (moveDir > 0) {
+                       lineDisplay = Platform::Clamp(lineDisplay + 1, 0, cs.LinesDisplayed());
+                       return pdoc->LineStart(cs.DocFromDisplay(lineDisplay));
+               } else {
+                       // lineDisplay is already line before fold as lines in fold use display line of line before fold
+                       lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
+                       return pdoc->LineEndPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
+               }
+       }
+}
+
+// Choose the x position that the caret will try to stick to as it is moves up and down
+void Editor::SetLastXChosen() {
+       Point pt = LocationFromPosition(currentPos);
+       lastXChosen = pt.x;
+}
+
+void Editor::ScrollTo(int line) {
+       int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
+       if (topLineNew != topLine) {
+               // Try to optimise small scrolls
+               int linesToMove = topLine - topLineNew;
+               SetTopLine(topLineNew);
+               ShowCaretAtCurrentPosition();
+               // Perform redraw rather than scroll if many lines would be redrawn anyway.
+               if (abs(linesToMove) <= 10) {
+                       ScrollText(linesToMove);
+               } else {
+                       Redraw();
+               }
+               SetVerticalScrollPos();
+       }
+}
+
+void Editor::ScrollText(int linesToMove) {
+       //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
+       Redraw();
+}
+
+void Editor::HorizontalScrollTo(int xPos) {
+       //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
+       xOffset = xPos;
+       if (xOffset < 0)
+               xOffset = 0;
+       SetHorizontalScrollPos();
+       Redraw();
+}
+
+void Editor::EnsureCaretVisible(bool useMargin) {
+       //Platform::DebugPrintf("EnsureCaretVisible %d\n", xOffset);
+       PRectangle rcClient = GetTextRectangle();
+       int posCaret = currentPos;
+       if (posDrag >= 0)
+               posCaret = posDrag;
+       Point pt = LocationFromPosition(posCaret);
+       Point ptEOL = LocationFromPosition(pdoc->LineEndPosition(posCaret));
+       Point ptBottomCaret = pt;
+       int lineCaret = cs.DisplayFromDoc(pdoc->LineFromPosition(posCaret));
+       ptBottomCaret.y += vs.lineHeight - 1;
+
+       // Ensure the caret is reasonably visible in context.
+       int xMargin = Platform::Clamp(xCaretMargin, 2, Platform::Maximum(rcClient.Width() - 10, 4) / 2);
+       if (!useMargin)
+               xMargin = 2;
+       
+       // Ensure certain amount of text visible on both sides of caretSo move if caret just on edge
+       rcClient.left = rcClient.left + xMargin;
+       rcClient.right = rcClient.right - xMargin;
+       
+       if (!rcClient.Contains(pt) || !rcClient.Contains(ptBottomCaret) || (caretPolicy & CARET_STRICT)) {
+               //Platform::DebugPrintf("EnsureCaretVisible move, (%d,%d) (%d,%d)\n", pt.x, pt.y, rcClient.left, rcClient.right);
+               // It should be possible to scroll the window to show the caret,
+               // but this fails to remove the caret on GTK+
+               if (caretPolicy & CARET_SLOP) {
+                       if ((topLine > lineCaret) || ((caretPolicy & CARET_STRICT) && (topLine + caretSlop > lineCaret))) {
+                               SetTopLine(Platform::Clamp(lineCaret - caretSlop, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       } else if ((lineCaret > topLine + LinesOnScreen() - 1) || 
+                               ((caretPolicy & CARET_STRICT) && (lineCaret > topLine + LinesOnScreen() - 1 - caretSlop))) {
+                               SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() + 1 + caretSlop, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       }
+               } else {
+                       if ((topLine > lineCaret) || (lineCaret > topLine + LinesOnScreen() - 1) || (caretPolicy & CARET_STRICT)) {
+                               SetTopLine(Platform::Clamp(lineCaret - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
+                               SetVerticalScrollPos();
+                               Redraw();
+                       }
+               }
+               int xOffsetNew = xOffset;
+               if (pt.x < rcClient.left) {
+                       xOffsetNew = xOffset - (rcClient.left - pt.x);
+               } else if (pt.x >= rcClient.right) {
+                       xOffsetNew = xOffset + (pt.x - rcClient.right);
+                       int xOffsetEOL = xOffset + (ptEOL.x - rcClient.right) - xMargin + 2;
+                       //Platform::DebugPrintf("Margin %d %d\n", xOffsetNew, xOffsetEOL);
+                       // Ensure don't scroll out into empty space
+                       if (xOffsetNew > xOffsetEOL)
+                               xOffsetNew = xOffsetEOL;
+               }
+               if (xOffsetNew < 0)
+                       xOffsetNew = 0;
+               if (xOffset != xOffsetNew) {
+                       xOffset = xOffsetNew;
+                       SetHorizontalScrollPos();
+                       Redraw();
+               }
+       }
+}
+
+void Editor::ShowCaretAtCurrentPosition() {
+       if (!wMain.HasFocus()) {
+               caret.active = false;
+               caret.on = false;
+               return;
+       }
+       caret.active = true;
+       caret.on = true;
+       SetTicking(true);
+}
+
+void Editor::DropCaret() {
+       caret.active = false;
+       InvalidateCaret();
+}
+
+void Editor::InvalidateCaret() {
+       if (posDrag >= 0)
+               InvalidateRange(posDrag, posDrag + 1);
+       else
+               InvalidateRange(currentPos, currentPos + 1);
+}
+
+void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
+       if (vs.fixedColumnWidth == 0)
+               return;
+
+       PRectangle rcMargin = GetClientRectangle();
+       rcMargin.right = vs.fixedColumnWidth;
+
+       if (!rc.Intersects(rcMargin))
+               return;
+
+       Surface *surface;
+       if (bufferedDraw) {
+               surface = &pixmapSelMargin;
+       } else {
+               surface = surfWindow;
+       }
+
+       PRectangle rcSelMargin = rcMargin;
+       rcSelMargin.right = rcMargin.left;
+
+       for (int margin=0; margin < vs.margins; margin++) {
+               if (vs.ms[margin].width > 0) {
+       
+                       rcSelMargin.left = rcSelMargin.right;
+                       rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+                       if (vs.ms[margin].symbol) {
+                               /* alternate scheme:
+                               if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+                                       surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+                               else
+                                       // Required because of special way brush is created for selection margin
+                                       surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
+                               */
+                               if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+                                       // Required because of special way brush is created for selection margin
+                                       surface->FillRectangle(rcSelMargin, pixmapSelPattern); 
+                               else
+                                       surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated); 
+                       } else {
+                               surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated);
+                       }
+                       
+                       int visibleLine = topLine;
+                       int line = cs.DocFromDisplay(visibleLine);
+                       int yposScreen = 0;
+
+                       while (line < pdoc->LinesTotal() && yposScreen < rcMargin.bottom) {
+                               int marks = pdoc->GetMark(line);
+                               if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+                                       if (cs.GetExpanded(line)) {
+                                               marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+                                       } else {
+                                               marks |= 1 << SC_MARKNUM_FOLDER;
+                                       }
+                               }
+                               marks &= vs.ms[margin].mask;
+                               PRectangle rcMarker = rcSelMargin;
+                               rcMarker.top = yposScreen;
+                               rcMarker.bottom = yposScreen + vs.lineHeight;
+                               if (!vs.ms[margin].symbol) {
+                                       char number[100];
+                                       number[0] = '\0';
+                                       sprintf(number, "%d", line + 1);
+                                       if (foldFlags & 8)
+                                               sprintf(number, "%X", pdoc->GetLevel(line));
+                                       int xpos = 0;
+                                       PRectangle rcNumber=rcMarker;
+                                       // Right justify
+                                       int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, strlen(number));
+                                       xpos = rcNumber.right - width - 3;
+                                       rcNumber.left = xpos;
+                                       if ((visibleLine < cs.LinesDisplayed()) && cs.GetVisible(line)) {
+                                               surface->DrawText(rcNumber, vs.styles[STYLE_LINENUMBER].font,
+                                                                 rcNumber.top + vs.maxAscent, number, strlen(number),
+                                                                 vs.styles[STYLE_LINENUMBER].fore.allocated, 
+                                                                 vs.styles[STYLE_LINENUMBER].back.allocated);
+                                       }
+                               }
+                               
+                               if (marks) {
+                                       for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+                                               if (marks & 1) {
+                                                       rcMarker.top++;
+                                                       rcMarker.bottom--;
+                                                       vs.markers[markBit].Draw(surface, rcMarker);
+                                               }
+                                               marks >>= 1;
+                                       }
+                               }
+                               
+                               visibleLine++;
+                               line = cs.DocFromDisplay(visibleLine);
+                               yposScreen += vs.lineHeight;
+                       }
+               }
+       }
+
+       PRectangle rcBlankMargin = rcMargin;
+       rcBlankMargin.left = rcSelMargin.right;
+       surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+       
+       if (bufferedDraw) {
+               surfWindow->Copy(rcMargin, Point(), pixmapSelMargin);
+       }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+       int ydiff = (rcTab.bottom - rcTab.top) / 2;
+       int xhead = rcTab.right - 1 - ydiff;
+       if ((rcTab.left + 2) < (rcTab.right - 1))
+               surface->MoveTo(rcTab.left + 2, ymid);
+       else
+               surface->MoveTo(rcTab.right - 1, ymid);
+       surface->LineTo(rcTab.right - 1, ymid);
+       surface->LineTo(xhead, ymid - ydiff);
+       surface->MoveTo(rcTab.right - 1, ymid);
+       surface->LineTo(xhead, ymid + ydiff);
+}
+
+void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll) {
+       int numCharsInLine = 0;
+       int posLineStart = pdoc->LineStart(line);
+       int posLineEnd = pdoc->LineStart(line + 1);
+       Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
+       char styleByte = 0;
+       int styleMask = pdoc->stylingBitsMask;
+       for (int charInDoc = posLineStart; 
+               charInDoc < posLineEnd && numCharsInLine < LineLayout::maxLineLength - 1; 
+               charInDoc++) {
+               char chDoc = pdoc->CharAt(charInDoc);
+               styleByte = pdoc->StyleAt(charInDoc);
+               if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) {
+                       ll.chars[numCharsInLine] = chDoc;
+                       ll.styles[numCharsInLine] = styleByte & styleMask;
+                       ll.indicators[numCharsInLine] = styleByte & ~styleMask;
+                       numCharsInLine++;
+               }
+       }
+       ll.chars[numCharsInLine] = 0;
+       ll.styles[numCharsInLine] = styleByte;  // For eolFilled
+       ll.indicators[numCharsInLine] = 0;
+
+       // Layout the line, determining the position of each character
+       int startseg = 0;
+       int startsegx = 0;
+       ll.positions[0] = 0;
+       unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
+       
+       for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
+               if ((ll.styles[charInLine] != ll.styles[charInLine + 1]) ||
+                       IsControlCharacter(ll.chars[charInLine]) || IsControlCharacter(ll.chars[charInLine + 1])) {
+                       ll.positions[startseg] = 0;
+                       if (IsControlCharacter(ll.chars[charInLine])) {
+                               if (ll.chars[charInLine] == '\t') {
+                                       ll.positions[charInLine + 1] = ((((startsegx + 2) /
+                                                                          tabWidth) + 1) * tabWidth) - startsegx;
+                               } else {
+                                       const char *ctrlChar = ControlCharacterString(ll.chars[charInLine]);
+                                       // +3 For a blank on front and rounded edge each side:
+                                       ll.positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, strlen(ctrlChar)) + 3;
+                               }
+                       } else {
+                               surface->MeasureWidths(vstyle.styles[ll.styles[charInLine]].font, ll.chars + startseg, 
+                                       charInLine - startseg + 1, ll.positions + startseg + 1);
+                       }
+                       for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) {
+                               ll.positions[posToIncrease] += startsegx;
+                       }
+                       startsegx = ll.positions[charInLine + 1];
+                       startseg = charInLine + 1;
+               }
+       }
+       ll.numCharsInLine = numCharsInLine;
+}
+
+void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout &ll) {
+       
+       PRectangle rcSegment = rcLine;
+       
+       // Using one font for all control characters so it can be controlled independently to ensure
+       // the box goes around the characters tightly. Seems to be no way to work out what height
+       // is taken by an individual character - internal leading gives varying results.
+       Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+       int marks = 0;
+       Colour markBack = Colour(0, 0, 0);
+       if (vsDraw.maskInLine) {
+               marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+               if (marks) {
+                       for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+                               if (marks & 1) {
+                                       markBack = vsDraw.markers[markBit].back.allocated;
+                               }
+                               marks >>= 1;
+                       }
+               }
+               marks = pdoc->GetMark(line) & vsDraw.maskInLine;
+       }
+
+       int posLineStart = pdoc->LineStart(line);
+       int posLineEnd = pdoc->LineStart(line + 1);
+
+       int selStart = SelectionStart(line);
+       int selEnd = SelectionEnd(line);
+
+       int styleMask = pdoc->stylingBitsMask;
+       int startseg = 0;
+       for (int i = 0; i < ll.numCharsInLine; i++) {
+
+               int iDoc = i + posLineStart;
+               // If there is the end of a style run for any reason
+               if ((ll.styles[i] != ll.styles[i + 1]) ||
+                       IsControlCharacter(ll.chars[i]) || IsControlCharacter(ll.chars[i + 1]) ||
+                       ((selStart != selEnd) && ((iDoc + 1 == selStart) || (iDoc + 1 == selEnd))) ||
+                               (i == (theEdge-1))) {
+                       int styleMain = ll.styles[i];
+                       Colour textBack = vsDraw.styles[styleMain].back.allocated;
+                       Colour textFore = vsDraw.styles[styleMain].fore.allocated;
+                       Font &textFont = vsDraw.styles[styleMain].font;
+                       bool inSelection = (iDoc >= selStart) && (iDoc < selEnd) && (selStart != selEnd);
+                       if (inSelection && !hideSelection) {
+                               if (vsDraw.selbackset)
+                                       textBack = vsDraw.selbackground.allocated;
+                               if (vsDraw.selforeset)
+                                       textFore = vsDraw.selforeground.allocated;
+                       } else {
+                               if (marks)
+                                       textBack = markBack;
+                               if ((edgeState == EDGE_BACKGROUND) && (i >= theEdge) && (ll.chars[i] != '\n') && (ll.chars[i] != '\r'))
+                                       textBack = vs.edgecolour.allocated;
+                       }
+                       // Manage tab display
+                       if (ll.chars[i] == '\t') {
+                               rcSegment.left = ll.positions[i] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               surface->FillRectangle(rcSegment, textBack);
+                               if (vsDraw.viewWhitespace) {
+                                       surface->PenColour(textFore);
+                                       PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+                                                        rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+                                       DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
+                               }
+                       // Manage control character display
+                       } else if (IsControlCharacter(ll.chars[i])) {
+                               const char *ctrlChar = ControlCharacterString(ll.chars[i]);
+                               rcSegment.left = ll.positions[i] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               surface->FillRectangle(rcSegment, textBack);
+                               int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+                                                      surface->InternalLeading(ctrlCharsFont);
+                               PRectangle rcCChar = rcSegment;
+                               rcCChar.left = rcCChar.left + 1;
+                               rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+                               rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+                               PRectangle rcCentral = rcCChar;
+                               rcCentral.top++;
+                               rcCentral.bottom--;
+                               surface->FillRectangle(rcCentral, textFore);
+                               PRectangle rcChar = rcCChar;
+                               rcChar.left++;
+                               rcChar.right--;
+                               surface->DrawTextClipped(rcChar, ctrlCharsFont,
+                                                       rcSegment.top + vsDraw.maxAscent, ctrlChar, strlen(ctrlChar), 
+                                                       textBack, textFore);
+                       // Manage normal display
+                       } else {
+                               rcSegment.left = ll.positions[startseg] + xStart;
+                               rcSegment.right = ll.positions[i + 1] + xStart;
+                               // Only try do draw if really visible - enhances performance by not calling environment to 
+                               // draw strings that are completely past the right side of the window.
+                               if (rcSegment.left <= rcLine.right) {
+                                       surface->DrawText(rcSegment, textFont,
+                                                         rcSegment.top + vsDraw.maxAscent, ll.chars + startseg,
+                                                         i - startseg + 1, textFore, textBack);
+                                       if (vsDraw.viewWhitespace) {
+                                               for (int cpos = 0; cpos <= i - startseg; cpos++) {
+                                                       if (ll.chars[cpos + startseg] == ' ') {
+                                                               int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2;
+                                                               PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
+                                                               rcDot.right = rcDot.left + 1;
+                                                               rcDot.bottom = rcDot.top + 1;
+                                                               surface->FillRectangle(rcDot, textFore);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       startseg = i + 1;
+               }
+       }
+
+       // Draw indicators
+       int indStart[INDIC_MAX + 1] = {0};
+       for (int indica = 0; indica <= INDIC_MAX; indica++)
+               indStart[indica] = 0;
+
+       for (int indicPos = 0; indicPos <= ll.numCharsInLine; indicPos++) {
+               if (ll.indicators[indicPos] != ll.indicators[indicPos + 1]) {
+                       int mask = 1 << pdoc->stylingBits;
+                       for (int indicnum = 0; mask <= 0x100; indicnum++) {
+                               if ((ll.indicators[indicPos + 1] & mask) && !(ll.indicators[indicPos] & mask)) {
+                                       indStart[indicnum] = ll.positions[indicPos + 1];
+                               }
+                               if (!(ll.indicators[indicPos + 1] & mask) && (ll.indicators[indicPos] & mask)) {
+                                       PRectangle rcIndic(
+                                           indStart[indicnum] + xStart,
+                                           rcLine.top + vsDraw.maxAscent,
+                                           ll.positions[indicPos + 1] + xStart,
+                                           rcLine.top + vsDraw.maxAscent + 3);
+                                       vsDraw.indicators[indicnum].Draw(surface, rcIndic);
+                               }
+                               mask = mask << 1;
+                       }
+               }
+       }
+       // End of the drawing of the current line
+
+       // Fill in a PRectangle representing the end of line characters
+       int xEol = ll.positions[ll.numCharsInLine];
+       rcSegment.left = xEol + xStart;
+       rcSegment.right = xEol + vsDraw.aveCharWidth + xStart;
+       bool eolInSelection = (posLineEnd > selStart) && (posLineEnd <= selEnd) && (selStart != selEnd);
+       if (eolInSelection && !hideSelection && vsDraw.selbackset && (line < pdoc->LinesTotal()-1)) {
+               surface->FillRectangle(rcSegment, vsDraw.selbackground.allocated);
+       } else if (marks) {
+               surface->FillRectangle(rcSegment, markBack);
+       } else {
+               surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+       }
+
+       rcSegment.left = xEol + vsDraw.aveCharWidth + xStart;
+       rcSegment.right = rcLine.right;
+       if (marks) {
+               surface->FillRectangle(rcSegment, markBack);
+       } else if (vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].eolFilled) {
+               surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated);
+       } else {
+               surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated);
+       }
+       
+       if (edgeState == EDGE_LINE) {
+               int edgeX = theEdge * vsDraw.spaceWidth;
+               rcSegment.left = edgeX + xStart;
+               rcSegment.right = rcSegment.left + 1;
+               surface->FillRectangle(rcSegment, vs.edgecolour.allocated);
+       }
+}
+
+void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+       //Platform::DebugPrintf("Paint %d %d - %d %d\n", rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+       RefreshStyleData();
+
+       PRectangle rcClient = GetClientRectangle();
+       //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n",
+       //      rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+       if (!pixmapSelPattern.Initialised()) {
+               pixmapSelPattern.InitPixMap(8, 8, surfaceWindow);
+               // This complex procedure is to reproduce the checker board dithered pattern used by windows
+               // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+               // way between the chrome colour and the chrome highlight colour making a nice transition
+               // between the window chrome and the content area. And it works in low colour depths.
+               PRectangle rcPattern(0, 0, 8, 8);
+               if (vs.selbarlight.desired == Colour(0xff, 0xff, 0xff)) {
+                       pixmapSelPattern.FillRectangle(rcPattern, vs.selbar.allocated);
+                       pixmapSelPattern.PenColour(vs.selbarlight.allocated);
+                       for (int stripe = 0; stripe < 8; stripe++) {
+                               pixmapSelPattern.MoveTo(0, stripe * 2);
+                               pixmapSelPattern.LineTo(8, stripe * 2 - 8);
+                       }
+               } else {
+                       // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+                       pixmapSelPattern.FillRectangle(rcPattern, vs.selbarlight.allocated);
+               }
+       }
+
+       if (bufferedDraw) {
+               if (!pixmapLine.Initialised()) {
+                       pixmapLine.InitPixMap(rcClient.Width(), rcClient.Height(),
+                                             surfaceWindow);
+                       pixmapSelMargin.InitPixMap(vs.fixedColumnWidth,
+                                                  rcClient.Height(), surfaceWindow);
+               }
+       }
+
+       surfaceWindow->SetPalette(&palette, true);
+       pixmapLine.SetPalette(&palette, !wMain.HasFocus());
+
+       //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n",
+       //      rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
+
+       int screenLinePaintFirst = rcArea.top / vs.lineHeight;
+       // The area to be painted plus one extra line is styled.
+       // The extra line is to determine when a style change, such as statrting a comment flows on to other lines.
+       int lineStyleLast = topLine + (rcArea.bottom-1) / vs.lineHeight + 1;
+       //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast);
+       int endPosPaint = pdoc->Length();
+       if (lineStyleLast < cs.LinesDisplayed())
+               endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast + 1));
+
+       int xStart = vs.fixedColumnWidth - xOffset;
+       int ypos = 0;
+       if (!bufferedDraw)
+               ypos += screenLinePaintFirst * vs.lineHeight;
+       int yposScreen = screenLinePaintFirst * vs.lineHeight;
+
+       if (endPosPaint > pdoc->GetEndStyled()) {
+               // Notify container to do some more styling
+               NotifyStyleNeeded(endPosPaint);
+       }
+       if (needUpdateUI) {
+               NotifyUpdateUI();
+               needUpdateUI = false;
+       }
+       
+       PaintSelMargin(surfaceWindow, rcArea);
+
+       PRectangle rcRightMargin = rcClient;
+       rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+       if (rcArea.Intersects(rcRightMargin)) {
+               surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back.allocated); 
+       }
+
+       if (paintState == paintAbandoned) {
+               // Either NotifyStyleNeeded or NotifyUpdateUI noticed that painting is needed
+               // outside the current painting rectangle
+               //Platform::DebugPrintf("Abandoning paint\n");
+               return;
+       }
+       //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+       Surface *surface = 0;
+       if (rcArea.right > vs.fixedColumnWidth) {
+
+               if (bufferedDraw) {
+                       surface = &pixmapLine;
+               } else {
+                       surface = surfaceWindow;
+               }
+
+               int visibleLine = topLine + screenLinePaintFirst;
+               int line = cs.DocFromDisplay(visibleLine);
+
+               int posCaret = currentPos;
+               if (posDrag >= 0)
+                       posCaret = posDrag;
+               int lineCaret = pdoc->LineFromPosition(posCaret);
+
+               // Remove selection margin from drawing area so text will not be drawn
+               // on it in unbuffered mode.
+               PRectangle rcTextArea = rcClient;
+               rcTextArea.left = vs.fixedColumnWidth;
+               rcTextArea.right -= vs.rightMarginWidth;
+               surfaceWindow->SetClip(rcTextArea);
+               //GTimer *tim=g_timer_new();
+               while (visibleLine <= cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+                       //g_timer_start(tim);
+                       //Platform::DebugPrintf("Painting line %d\n", line);
+
+                       int posLineStart = pdoc->LineStart(line);
+                       int posLineEnd = pdoc->LineStart(line + 1);
+                       //Platform::DebugPrintf("line %d %d - %d\n", line, posLineStart, posLineEnd);
+
+                       PRectangle rcLine = rcClient;
+                       rcLine.top = ypos;
+                       rcLine.bottom = ypos + vs.lineHeight;
+
+                       // Copy this line and its styles from the document into local arrays
+                       // and determine the x position at which each character starts.
+                       LineLayout ll;
+                       LayoutLine(line, surface, vs, ll);
+                                                       
+                       // Highlight the current braces if any
+                       if ((braces[0] >= posLineStart) && (braces[0] < posLineEnd))
+                               ll.styles[braces[0] - posLineStart] = bracesMatchStyle;
+                       if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd))
+                               ll.styles[braces[1] - posLineStart] = bracesMatchStyle;
+                               
+                       // Draw the line
+                       if (cs.GetVisible(line))
+                               DrawLine(surface, vs, line, xStart, rcLine, ll);
+
+                       if (foldFlags & 2) {
+                               if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+                                       PRectangle rcFoldLine = rcLine;
+                                       rcFoldLine.bottom = rcFoldLine.top + 1;
+                                       surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+                               }
+                       }
+                       
+                       // Draw the Caret
+                       if (line == lineCaret) {
+                               int xposCaret = ll.positions[posCaret - posLineStart] + xStart;
+                               int widthOverstrikeCaret =
+                                   ll.positions[posCaret - posLineStart + 1] - ll.positions[posCaret - posLineStart];
+                               if (posCaret == pdoc->Length()) // At end of document
+                                       widthOverstrikeCaret = vs.aveCharWidth;
+                               if ((posCaret - posLineStart) >= ll.numCharsInLine)     // At end of line
+                                       widthOverstrikeCaret = vs.aveCharWidth;
+                               if (widthOverstrikeCaret < 3)   // Make sure its visible
+                                       widthOverstrikeCaret = 3;
+                               if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) {
+                                       PRectangle rcCaret = rcLine;
+                                       if (posDrag >= 0) {
+                                               rcCaret.left = xposCaret;
+                                               rcCaret.right = xposCaret + 1;
+                                       } else {
+                                               if (inOverstrike) {
+                                                       rcCaret.top = rcCaret.bottom - 2;
+                                                       rcCaret.left = xposCaret + 1;
+                                                       rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+                                               } else {
+                                                       rcCaret.left = xposCaret;
+                                                       rcCaret.right = xposCaret + 1;
+                                               }
+                                       }
+                                       surface->FillRectangle(rcCaret, vs.caretcolour.allocated);
+                               }
+                       }
+                       
+                       if (cs.GetVisible(line)) {
+                               if (bufferedDraw) {
+                                       Point from(vs.fixedColumnWidth, 0);
+                                       PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen,
+                                                         rcClient.right, yposScreen + vs.lineHeight);
+                                       surfaceWindow->Copy(rcCopyArea, from, pixmapLine);
+                               }
+                       }
+
+                       if (!bufferedDraw) {
+                               ypos += vs.lineHeight;
+                       }
+
+                       yposScreen += vs.lineHeight;
+                       visibleLine++;
+                       line = cs.DocFromDisplay(visibleLine);
+                       //gdk_flush();
+                       //g_timer_stop(tim);
+                       //Platform::DebugPrintf("Paint [%0d] took %g\n", line, g_timer_elapsed(tim, 0));
+               }
+               //g_timer_destroy(tim);
+               PRectangle rcBeyondEOF = rcClient;
+               rcBeyondEOF.left = vs.fixedColumnWidth;
+               rcBeyondEOF.right = rcBeyondEOF.right;
+               rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
+               if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+                       surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back.allocated);
+                       if (edgeState == EDGE_LINE) {
+                               int edgeX = theEdge * vs.spaceWidth;
+                               rcBeyondEOF.left = edgeX + xStart;
+                               rcBeyondEOF.right = rcBeyondEOF.left + 1;
+                               surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated);
+                       }
+               }
+       }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace "   "
+
+// This is mostly copied from the Paint method but with some things omitted
+// such as the margin markers, line numbers, selection and caret
+// Should be merged back into a combined Draw method.
+long Editor::FormatRange(bool draw, FORMATRANGE *pfr) {
+       if (!pfr)
+               return 0;
+
+       Surface *surface = new Surface();
+       surface->Init(pfr->hdc);
+       Surface *surfaceMeasure = new Surface();
+       surfaceMeasure->Init(pfr->hdcTarget);
+       
+       ViewStyle vsPrint(vs);
+       
+       // Modify the view style for printing as do not normally want any of the transient features to be printed
+       // Printing supports only the line number margin.
+       int lineNumberIndex = -1;
+       for (int margin=0; margin < ViewStyle::margins; margin++) {
+               if ((!vsPrint.ms[margin].symbol) && (vsPrint.ms[margin].width > 0)) {
+                       lineNumberIndex = margin;
+               } else {
+                       vsPrint.ms[margin].width = 0;
+               }
+       }
+       vsPrint.showMarkedLines = false;
+       vsPrint.fixedColumnWidth = 0;
+       vsPrint.zoomLevel = 0;
+       // Don't show the selection when printing
+       vsPrint.selbackset = false;
+       vsPrint.selforeset = false;
+       // White background for the line numbers
+       vsPrint.styles[STYLE_LINENUMBER].back.desired = Colour(0xff,0xff,0xff); 
+       
+       vsPrint.Refresh(*surfaceMeasure);
+       // Ensure colours are set up
+       vsPrint.RefreshColourPalette(palette, true);
+       vsPrint.RefreshColourPalette(palette, false);
+       // Determining width must hapen after fonts have been realised in Refresh
+       int lineNumberWidth = 0;
+       if (lineNumberIndex >= 0) {
+               lineNumberWidth = surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, 
+                       "9999" lineNumberPrintSpace, 4 + strlen(lineNumberPrintSpace));
+               vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+       }
+
+       int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
+       int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+       if (linePrintLast < linePrintStart)
+               linePrintLast = linePrintStart;
+       int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax - 1);
+       if (linePrintLast > linePrintMax)
+               linePrintLast = linePrintMax;
+       //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+       //      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+       //      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+       int endPosPrint = pdoc->Length();
+       if (linePrintLast < pdoc->LinesTotal())
+               endPosPrint = pdoc->LineStart(linePrintLast + 1);
+
+       if (endPosPrint > pdoc->GetEndStyled()) {
+               // Notify container to do some more styling
+               NotifyStyleNeeded(endPosPrint);
+       }
+       int xStart = vsPrint.fixedColumnWidth + pfr->rc.left + lineNumberWidth;
+       int ypos = pfr->rc.top;
+       int line = linePrintStart;
+
+       if (draw) {     // Otherwise just measuring
+
+               while (line <= linePrintLast && ypos < pfr->rc.bottom) {
+
+                       PRectangle rcLine;
+                       rcLine.left = pfr->rc.left + lineNumberWidth;
+                       rcLine.top = ypos;
+                       rcLine.right = pfr->rc.right;
+                       rcLine.bottom = ypos + vsPrint.lineHeight;
+                       
+                       if (lineNumberWidth) {
+                               char number[100];
+                               sprintf(number, "%d" lineNumberPrintSpace, line + 1);
+                               PRectangle rcNumber = rcLine;
+                               rcNumber.right = rcNumber.left + lineNumberWidth;
+                               // Right justify
+                               rcNumber.left += lineNumberWidth - 
+                                       surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, number, strlen(number));
+                               surface->DrawText(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+                                                 ypos + vsPrint.maxAscent, number, strlen(number),
+                                                 vsPrint.styles[STYLE_LINENUMBER].fore.allocated, 
+                                                 vsPrint.styles[STYLE_LINENUMBER].back.allocated);
+                       }
+                       
+                       // Copy this line and its styles from the document into local arrays
+                       // and determine the x position at which each character starts.
+                       LineLayout ll;
+                       LayoutLine(line, surfaceMeasure, vsPrint, ll);
+                                                       
+                       // Draw the line
+                       DrawLine(surface, vsPrint, line, xStart, rcLine, ll);
+
+                       ypos += vsPrint.lineHeight;
+                       line++;
+               }
+       }
+
+       delete surface;
+       delete surfaceMeasure;
+
+       return endPosPrint;
+}
+
+void Editor::SetScrollBarsTo(PRectangle) {
+       RefreshStyleData();
+
+       int nMax = cs.LinesDisplayed();
+       int nPage = cs.LinesDisplayed() - MaxScrollPos() + 1;
+       bool modified = ModifyScrollBars(nMax, nPage);
+
+       // TODO: ensure always showing as many lines as possible
+       // May not be, if, for example, window made larger
+       if (topLine > MaxScrollPos()) {
+               SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
+               SetVerticalScrollPos();
+               Redraw();
+       }
+       if (modified)
+               Redraw();
+       //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
+}
+
+void Editor::SetScrollBars() {
+       PRectangle rsClient = GetClientRectangle();
+       SetScrollBarsTo(rsClient);
+}
+
+void Editor::AddChar(char ch) {
+       bool wasSelection = currentPos != anchor;
+       ClearSelection();
+       if (inOverstrike && !wasSelection) {
+               if (currentPos < (pdoc->Length() - 1)) {
+                       if ((pdoc->CharAt(currentPos) != '\r') && (pdoc->CharAt(currentPos) != '\n')) {
+                               pdoc->DelChar(currentPos);
+                       }
+               }
+       }
+       pdoc->InsertChar(currentPos, ch);
+       SetEmptySelection(currentPos + 1);
+       EnsureCaretVisible();
+       SetLastXChosen();
+       NotifyChar(ch);
+}
+
+void Editor::ClearSelection() {
+       if (selType == selRectangle) {
+               pdoc->BeginUndoAction();
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int startPos = SelectionStart();
+               int line;
+               for (line=lineStart; line <= lineEnd; line++) {
+                       startPos = SelectionStart(line);
+                       unsigned int chars = SelectionEnd(line) - startPos;
+                       if (0 != chars) {
+                               pdoc->DeleteChars(startPos, chars);
+                       }
+               }
+               SetEmptySelection(startPos);
+               selType = selStream;
+               pdoc->EndUndoAction();
+       } else {
+               int startPos = SelectionStart();
+               unsigned int chars = SelectionEnd() - startPos;
+               SetEmptySelection(startPos);
+               if (0 != chars) {
+                       pdoc->DeleteChars(startPos, chars);
+               }
+       }
+}
+
+void Editor::ClearAll() {
+       if (0 != pdoc->Length()) {
+               pdoc->DeleteChars(0, pdoc->Length());
+       }
+       cs.Clear();
+       anchor = 0;
+       currentPos = 0;
+       SetTopLine(0);
+       SetVerticalScrollPos();
+}
+
+void Editor::Cut() {
+       Copy();
+       ClearSelection();
+}
+
+void Editor::PasteRectangular(int pos, const char *ptr, int len) {
+       currentPos = pos;
+       int insertPos = currentPos;
+       int xInsert = XFromPosition(currentPos);
+       int line = pdoc->LineFromPosition(currentPos);
+       bool prevCr = false;
+       for (int i=0; i<len; i++) {
+               if ((ptr[i] == '\r') || (ptr[i] == '\n')) {
+                       if ((ptr[i] == '\r') || (!prevCr)) 
+                               line++;
+                       if (line >= pdoc->LinesTotal()) {
+                               if (pdoc->eolMode != SC_EOL_LF)
+                                       pdoc->InsertChar(pdoc->Length(), '\r');
+                               if (pdoc->eolMode != SC_EOL_CR)
+                                       pdoc->InsertChar(pdoc->Length(), '\n');
+                       }
+                       currentPos = PositionFromLineX(line, xInsert);
+                       prevCr = ptr[i] == '\r';
+               } else {
+                       pdoc->InsertString(currentPos, ptr+i, 1);
+                       currentPos++;
+                       insertPos = currentPos;
+                       prevCr = false;
+               }
+       }
+       SetEmptySelection(insertPos);
+}
+
+void Editor::Clear() {
+       if (currentPos == anchor) {
+               DelChar();
+       } else {
+               ClearSelection();
+       }
+       SetEmptySelection(currentPos);
+}
+
+void Editor::SelectAll() {
+       SetSelection(0, pdoc->Length());
+       Redraw();
+}
+
+void Editor::Undo() {
+       if (pdoc->CanUndo()) {
+               int newPos = pdoc->Undo();
+               SetEmptySelection(newPos);
+               EnsureCaretVisible();
+       }
+}
+
+void Editor::Redo() {
+       if (pdoc->CanRedo()) {
+               int newPos = pdoc->Redo();
+               SetEmptySelection(newPos);
+               EnsureCaretVisible();
+       }
+}
+
+void Editor::DelChar() {
+       pdoc->DelChar(currentPos);
+}
+
+void Editor::DelCharBack() {
+       if (currentPos == anchor) {
+               int newPos = pdoc->DelCharBack(currentPos);
+               SetEmptySelection(newPos);
+       } else {
+               ClearSelection();
+               SetEmptySelection(currentPos);
+       }
+}
+
+void Editor::NotifyFocus(bool) {
+}
+
+void Editor::NotifyStyleNeeded(int endStyleNeeded) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_STYLENEEDED;
+       scn.position = endStyleNeeded;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyChar(char ch) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_CHARADDED;
+       scn.ch = ch;
+       NotifyParent(scn);
+#ifdef MACRO_SUPPORT
+       if (recordingMacro) {
+               char txt[2];
+               txt[0] = ch;
+               txt[1] = '\0';
+               NotifyMacroRecord(EM_REPLACESEL, 0, (LPARAM) txt);
+       }
+#endif
+}
+
+void Editor::NotifySavePoint(bool isSavePoint) {
+       SCNotification scn;
+       if (isSavePoint) {
+               scn.nmhdr.code = SCN_SAVEPOINTREACHED;
+       } else {
+               scn.nmhdr.code = SCN_SAVEPOINTLEFT;
+       }
+       NotifyParent(scn);
+}
+
+void Editor::NotifyModifyAttempt() {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyDoubleClick(Point, bool) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_DOUBLECLICK;
+       NotifyParent(scn);
+}
+
+void Editor::NotifyUpdateUI() {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_UPDATEUI;
+       NotifyParent(scn);
+}
+
+bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
+       int marginClicked = -1;
+       int x = 0;
+       for (int margin=0; margin < ViewStyle::margins; margin++) {
+               if ((pt.x > x) && (pt.x < x + vs.ms[margin].width))
+                       marginClicked = margin;
+               x += vs.ms[margin].width;
+       }
+       if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
+               SCNotification scn;
+               scn.nmhdr.code = SCN_MARGINCLICK;
+               scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+                               (alt ? SCI_ALT : 0);
+               scn.position = pdoc->LineStart(LineFromLocation(pt));
+               scn.margin = marginClicked;
+               NotifyParent(scn);
+               return true;
+       } else {
+               return false;
+       }
+}
+
+void Editor::NotifyNeedShown(int pos, int len) {
+       SCNotification scn;
+       scn.nmhdr.code = SCN_NEEDSHOWN;
+       scn.position = pos;
+       scn.length = len;
+       NotifyParent(scn);
+}
+
+// Notifications from document
+void Editor::NotifyModifyAttempt(Document*, void *) {
+       //Platform::DebugPrintf("** Modify Attempt\n");
+       NotifyModifyAttempt();
+}
+
+void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
+       //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
+       NotifySavePoint(atSavePoint);
+}
+
+void Editor::NotifyModified(Document*, DocModification mh, void *) {
+       needUpdateUI = true;
+       if (paintState == painting) {
+               CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
+       } else if (paintState == notPainting) {
+               if (mh.modificationType & SC_MOD_CHANGESTYLE) {
+                       if (mh.position < pdoc->LineStart(topLine)) {
+                               // Styling performed before this view
+                               Redraw();
+                       } else {
+                               InvalidateRange(mh.position, mh.position + mh.length);
+                       }
+               } else {
+                       // Move selection and brace highlights
+                       if (mh.modificationType & SC_MOD_INSERTTEXT) {
+                               if (currentPos > mh.position) {
+                                       currentPos += mh.length;
+                               }
+                               if (anchor > mh.position) {
+                                       anchor += mh.length;
+                               }
+                               if (braces[0] > mh.position) {
+                                       braces[0] += mh.length;
+                               }
+                               if (braces[1] > mh.position) {
+                                       braces[1] += mh.length;
+                               }
+                       } else {        // SC_MOD_DELETETEXT
+                               int endPos = mh.position + mh.length;
+                               if (currentPos > mh.position) {
+                                       if (currentPos > endPos) {
+                                               currentPos -= mh.length;
+                                       } else {
+                                               currentPos = endPos;
+                                       }
+                               }
+                               if (anchor > mh.position) {
+                                       if (anchor > endPos) {
+                                               anchor -= mh.length;
+                                       } else {
+                                               anchor = endPos;
+                                       }
+                               }
+                               if (braces[0] > mh.position) {
+                                       if (braces[0] > endPos) {
+                                               braces[0] -= mh.length;
+                                       } else {
+                                               braces[0] = endPos;
+                                       }
+                               }
+                               if (braces[1] > mh.position) {
+                                       if (braces[1] > endPos) {
+                                               braces[1] -= mh.length;
+                                       } else {
+                                               braces[1] = endPos;
+                                       }
+                               }
+                       }
+                       if (mh.linesAdded != 0) {
+
+                               // Update contraction state for inserted and removed lines
+                               // lineOfPos should be calculated in context of state before modification, shouldn't it
+                               int lineOfPos = pdoc->LineFromPosition(mh.position);
+                               if (mh.linesAdded > 0) {
+                                       NotifyNeedShown(mh.position, mh.length);
+                                       cs.InsertLines(lineOfPos, mh.linesAdded);
+                               } else {
+                                       cs.DeleteLines(lineOfPos, -mh.linesAdded);
+                               }
+                               // Avoid scrolling of display if change before current display
+                               if (mh.position < posTopLine) {
+                                       int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
+                                       if (newTop != topLine) {
+                                               SetTopLine(newTop);
+                                               SetVerticalScrollPos();
+                                       }
+                               }
+                               
+                               //Platform::DebugPrintf("** %x Doc Changed\n", this);
+                               // TODO: could invalidate from mh.startModification to end of screen
+                               //InvalidateRange(mh.position, mh.position + mh.length);
+                               Redraw();
+                       } else {
+                               //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
+                               //      mh.position, mh.position + mh.length);
+                               InvalidateRange(mh.position, mh.position + mh.length);
+                       }
+               }
+       } // else paintState == paintAbandoned so no need to do anything
+
+       if (mh.linesAdded != 0) {
+               SetScrollBars();
+       }
+
+       // If client wants to see this modification
+       if (mh.modificationType & modEventMask) {
+               if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
+                       // Real modification made to text of document.
+                       NotifyChange(); // Send EN_CHANGE
+               }
+               SCNotification scn;
+               scn.nmhdr.code = SCN_MODIFIED;
+               scn.position = mh.position;
+               scn.modificationType = mh.modificationType;
+               scn.text = mh.text;
+               scn.length = mh.length;
+               scn.linesAdded = mh.linesAdded;
+               scn.line = mh.line;
+               scn.foldLevelNow = mh.foldLevelNow;
+               scn.foldLevelPrev = mh.foldLevelPrev;
+               NotifyParent(scn);
+       }
+}
+
+void Editor::NotifyDeleted(Document *document, void *userData) {
+       /* Do nothing */
+}
+
+#ifdef MACRO_SUPPORT
+void Editor::NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+
+       // Enumerates all macroable messages
+       switch (iMessage) {
+       case WM_CUT:
+       case WM_COPY:
+       case WM_PASTE:
+       case WM_CLEAR:
+       case EM_REPLACESEL:
+       case SCI_ADDTEXT:
+       case SCI_INSERTTEXT:
+       case SCI_CLEARALL:
+       case SCI_SELECTALL:
+       case SCI_GOTOLINE:
+       case SCI_GOTOPOS:
+       case SCI_SEARCHANCHOR:
+       case SCI_SEARCHNEXT:
+       case SCI_SEARCHPREV:
+       case SCI_LINEDOWN:
+       case SCI_LINEDOWNEXTEND:
+       case SCI_LINEUP:
+       case SCI_LINEUPEXTEND:
+       case SCI_CHARLEFT:
+       case SCI_CHARLEFTEXTEND:
+       case SCI_CHARRIGHT:
+       case SCI_CHARRIGHTEXTEND:
+       case SCI_WORDLEFT:
+       case SCI_WORDLEFTEXTEND:
+       case SCI_WORDRIGHT:
+       case SCI_WORDRIGHTEXTEND:
+       case SCI_HOME:
+       case SCI_HOMEEXTEND:
+       case SCI_LINEEND:
+       case SCI_LINEENDEXTEND:
+       case SCI_DOCUMENTSTART:
+       case SCI_DOCUMENTSTARTEXTEND:
+       case SCI_DOCUMENTEND:
+       case SCI_DOCUMENTENDEXTEND:
+       case SCI_PAGEUP:
+       case SCI_PAGEUPEXTEND:
+       case SCI_PAGEDOWN:
+       case SCI_PAGEDOWNEXTEND:
+       case SCI_EDITTOGGLEOVERTYPE:
+       case SCI_CANCEL:
+       case SCI_DELETEBACK:
+       case SCI_TAB:
+       case SCI_BACKTAB:
+       case SCI_NEWLINE:
+       case SCI_FORMFEED:
+       case SCI_VCHOME:
+       case SCI_VCHOMEEXTEND:
+       case SCI_DELWORDLEFT:
+       case SCI_DELWORDRIGHT:
+               break;
+
+       // Filter out all others (display changes, etc)
+       default:
+//             printf("Filtered out %ld of macro recording\n", iMessage);
+               return;
+       }
+
+       // Send notification
+       SCNotification scn;
+       scn.nmhdr.code = SCN_MACRORECORD;
+       scn.message = iMessage;
+       scn.wParam = wParam;
+       scn.lParam = lParam;
+       NotifyParent(scn);
+}
+#endif
+
+// Force scroll and keep position relative to top of window
+void Editor::PageMove(int direction, bool extend) {
+       Point pt = LocationFromPosition(currentPos);
+       int topLineNew = Platform::Clamp(
+                        topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+       int newPos = PositionFromLocation(
+                        Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll())));
+       if (topLineNew != topLine) {
+               SetTopLine(topLineNew);
+               MovePositionTo(newPos, extend);
+               Redraw();
+               SetVerticalScrollPos();
+       } else {
+               MovePositionTo(newPos, extend);
+       }
+}
+
+int Editor::KeyCommand(UINT iMessage) {
+       Point pt = LocationFromPosition(currentPos);
+
+       switch (iMessage) {
+       case SCI_LINEDOWN:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y + vs.lineHeight)));
+               break;
+       case SCI_LINEDOWNEXTEND:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y + vs.lineHeight)), true);
+               break;
+       case SCI_LINEUP:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y - vs.lineHeight)));
+               break;
+       case SCI_LINEUPEXTEND:
+               MovePositionTo(PositionFromLocation(
+                                  Point(lastXChosen, pt.y - vs.lineHeight)), true);
+               break;
+       case SCI_CHARLEFT:
+               if (SelectionEmpty()) {
+                       MovePositionTo(MovePositionSoVisible(currentPos - 1, -1));
+               } else {
+                       MovePositionTo(SelectionStart());
+               }
+               SetLastXChosen();
+               break;
+       case SCI_CHARLEFTEXTEND:
+               MovePositionTo(MovePositionSoVisible(currentPos - 1, -1), true);
+               SetLastXChosen();
+               break;
+       case SCI_CHARRIGHT:
+               if (SelectionEmpty()) {
+                       MovePositionTo(MovePositionSoVisible(currentPos + 1, 1));
+               } else {
+                       MovePositionTo(SelectionEnd());
+               }
+               SetLastXChosen();
+               break;
+       case SCI_CHARRIGHTEXTEND:
+               MovePositionTo(MovePositionSoVisible(currentPos + 1, 1), true);
+               SetLastXChosen();
+               break;
+       case SCI_WORDLEFT:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1));
+               SetLastXChosen();
+               break;
+       case SCI_WORDLEFTEXTEND:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, -1), -1), true);
+               SetLastXChosen();
+               break;
+       case SCI_WORDRIGHT:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1));
+               SetLastXChosen();
+               break;
+       case SCI_WORDRIGHTEXTEND:
+               MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(currentPos, 1), 1), true);
+               SetLastXChosen();
+               break;
+       case SCI_HOME:
+               MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)));
+               SetLastXChosen();
+               break;
+       case SCI_HOMEEXTEND:
+               MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(currentPos)), true);
+               SetLastXChosen();
+               break;
+       case SCI_LINEEND:
+               MovePositionTo(pdoc->LineEndPosition(currentPos));
+               SetLastXChosen();
+               break;
+       case SCI_LINEENDEXTEND:
+               MovePositionTo(pdoc->LineEndPosition(currentPos), true);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTSTART:
+               MovePositionTo(0);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTSTARTEXTEND:
+               MovePositionTo(0, true);
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTEND:
+               MovePositionTo(pdoc->Length());
+               SetLastXChosen();
+               break;
+       case SCI_DOCUMENTENDEXTEND:
+               MovePositionTo(pdoc->Length(), true);
+               SetLastXChosen();
+               break;
+       case SCI_PAGEUP:
+               PageMove( -1);
+               break;
+       case SCI_PAGEUPEXTEND:
+               PageMove( -1, true);
+               break;
+       case SCI_PAGEDOWN:
+               PageMove(1);
+               break;
+       case SCI_PAGEDOWNEXTEND:
+               PageMove(1, true);
+               break;
+       case SCI_EDITTOGGLEOVERTYPE:
+               inOverstrike = !inOverstrike;
+               DropCaret();
+               ShowCaretAtCurrentPosition();
+               break;
+       case SCI_CANCEL:        // Cancel any modes - handled in subclass
+               // Also unselect text
+               SetEmptySelection(currentPos);
+               break;
+       case SCI_DELETEBACK:
+               DelCharBack();
+               EnsureCaretVisible();
+               break;
+       case SCI_TAB:
+               Indent(true);
+               break;
+       case SCI_BACKTAB:
+               Indent(false);
+               break;
+       case SCI_NEWLINE:
+               ClearSelection();
+               if (pdoc->eolMode == SC_EOL_CRLF) {
+                       pdoc->InsertString(currentPos, "\r\n");
+                       SetEmptySelection(currentPos + 2);
+                       NotifyChar('\r');
+                       NotifyChar('\n');
+               } else if (pdoc->eolMode == SC_EOL_CR) {
+                       pdoc->InsertChar(currentPos, '\r');
+                       SetEmptySelection(currentPos + 1);
+                       NotifyChar('\r');
+               } else if (pdoc->eolMode == SC_EOL_LF) {
+                       pdoc->InsertChar(currentPos, '\n');
+                       SetEmptySelection(currentPos + 1);
+                       NotifyChar('\n');
+               }
+               SetLastXChosen();
+               EnsureCaretVisible();
+               break;
+       case SCI_FORMFEED:
+               AddChar('\f');
+               break;
+       case SCI_VCHOME:
+               MovePositionTo(pdoc->VCHomePosition(currentPos));
+               SetLastXChosen();
+               break;
+       case SCI_VCHOMEEXTEND:
+               MovePositionTo(pdoc->VCHomePosition(currentPos), true);
+               SetLastXChosen();
+               break;
+       case SCI_ZOOMIN:
+               if (vs.zoomLevel < 20)
+                       vs.zoomLevel++;
+               InvalidateStyleRedraw();
+               break;
+       case SCI_ZOOMOUT:
+               if (vs.zoomLevel > -10)
+                       vs.zoomLevel--;
+               InvalidateStyleRedraw();
+               break;
+       case SCI_DELWORDLEFT: {
+                       int startWord = pdoc->NextWordStart(currentPos, -1);
+                       pdoc->DeleteChars(startWord, currentPos - startWord);
+                       MovePositionTo(startWord);
+               }
+               break;
+       case SCI_DELWORDRIGHT: {
+                       int endWord = pdoc->NextWordStart(currentPos, 1);
+                       pdoc->DeleteChars(currentPos, endWord - currentPos);
+               }
+               break;
+       }
+       return 0;
+}
+
+int Editor::KeyDefault(int, int) {
+       return 0;
+}
+
+int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt) {
+       int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
+                       (alt ? SCI_ALT : 0);
+       int msg = kmap.Find(key, modifiers);
+       if (msg)
+               return WndProc(msg, 0, 0);
+       else
+               return KeyDefault(key, modifiers);
+}
+
+void Editor::SetWhitespaceVisible(bool view) {
+       vs.viewWhitespace = view;
+}
+
+bool Editor::GetWhitespaceVisible() {
+       return vs.viewWhitespace;
+}
+
+void Editor::Indent(bool forwards) {
+       //Platform::DebugPrintf("INdent %d\n", forwards);
+       int lineOfAnchor = pdoc->LineFromPosition(anchor);
+       int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+       if (lineOfAnchor == lineCurrentPos) {
+               ClearSelection();
+               pdoc->InsertChar(currentPos, '\t');
+               //pdoc->InsertChar(currentPos++, '\t');
+               SetEmptySelection(currentPos + 1);
+       } else {
+               int anchorPosOnLine = anchor - pdoc->LineStart(lineOfAnchor);
+               int currentPosPosOnLine = currentPos - pdoc->LineStart(lineCurrentPos);
+               // Multiple lines selected so indent / dedent
+               int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
+               int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
+               if (pdoc->LineStart(lineBottomSel) == anchor || pdoc->LineStart(lineBottomSel) == currentPos)
+                       lineBottomSel--;        // If not selecting any characters on a line, do not indent
+               pdoc->BeginUndoAction();
+               pdoc->Indent(forwards, lineBottomSel, lineTopSel);
+               pdoc->EndUndoAction();
+               if (lineOfAnchor < lineCurrentPos) {
+                       if (currentPosPosOnLine == 0)
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+                       else
+                               SetSelection(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
+               } else {
+                       if (anchorPosOnLine == 0)
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
+                       else
+                               SetSelection(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
+               }
+       }
+}
+
+long Editor::FindText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       FINDTEXTEX *ft = reinterpret_cast<FINDTEXTEX *>(lParam);
+       int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+                       wParam & FR_MATCHCASE, wParam & FR_WHOLEWORD);
+       if (pos != -1) {
+               if (iMessage == EM_FINDTEXTEX) {
+                       ft->chrgText.cpMin = pos;
+                       ft->chrgText.cpMax = pos + strlen(ft->lpstrText);
+               }
+       }
+       return pos;
+}
+
+// Relocatable search support : Searches relative to current selection 
+// point and sets the selection to the found text range with 
+// each search.
+
+// Anchor following searches at current selection start:  This allows
+// multiple incremental interactive searches to be macro recorded
+// while still setting the selection to found text so the find/select
+// operation is self-contained.
+void Editor::SearchAnchor() {
+       searchAnchor = SelectionStart();
+}
+
+// Find text from current search anchor:  Must call SearchAnchor first.
+// Accepts both SCI_SEARCHNEXT and SCI_SEARCHPREV.
+// wParam contains search modes : ORed FR_MATCHCASE and FR_WHOLEWORD.
+// lParam contains the text to search for.
+long Editor::SearchText(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       const char *txt = reinterpret_cast<char *>(lParam);
+       int pos;
+
+       if (iMessage == SCI_SEARCHNEXT) {
+               pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, 
+                                    wParam & FR_MATCHCASE,
+                                    wParam & FR_WHOLEWORD);
+       } else {
+               pos = pdoc->FindText(searchAnchor, 0, txt, 
+                                    wParam & FR_MATCHCASE,
+                                    wParam & FR_WHOLEWORD);
+       }
+
+       if (pos != -1) {
+               SetSelection(pos, pos + strlen(txt));
+       }
+
+       return pos;
+}
+
+void Editor::GoToLine(int lineNo) {
+       if (lineNo > pdoc->LinesTotal())
+               lineNo = pdoc->LinesTotal();
+       if (lineNo < 0)
+               lineNo = 0;
+       SetEmptySelection(pdoc->LineStart(lineNo));
+       ShowCaretAtCurrentPosition();
+       EnsureCaretVisible();
+}
+
+static bool Close(Point pt1, Point pt2) {
+       if (abs(pt1.x - pt2.x) > 3)
+               return false;
+       if (abs(pt1.y - pt2.y) > 3)
+               return false;
+       return true;
+}
+
+char *Editor::CopyRange(int start, int end) {
+       char *text = 0;
+       if (start < end) {
+               int len = end - start;
+               text = new char[len + 1];
+               if (text) {
+                       for (int i = 0; i < len; i++) {
+                               text[i] = pdoc->CharAt(start + i);
+                       }
+                       text[len] = '\0';
+               }
+       }
+       return text;
+}
+
+int Editor::SelectionRangeLength() {
+       if (selType == selRectangle) {
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int totalSize = 0;
+               for (int line=lineStart; line <= lineEnd; line++) {
+                       totalSize += SelectionEnd(line) - SelectionStart(line) + 1;
+                       if (pdoc->eolMode == SC_EOL_CRLF)
+                               totalSize++;
+               }
+               return totalSize;
+       } else {
+               return SelectionEnd() - SelectionStart();
+       }
+}
+
+char *Editor::CopySelectionRange() {
+       if (selType == selRectangle) {
+               char *text = 0;
+               int lineStart = pdoc->LineFromPosition(SelectionStart());
+               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+               int totalSize = SelectionRangeLength();
+               if (totalSize > 0) {
+                       text = new char[totalSize + 1];
+                       if (text) {
+                               int j = 0;
+                               for (int line=lineStart; line <= lineEnd; line++) {
+                                       for (int i=SelectionStart(line);i<SelectionEnd(line);i++) {
+                                               text[j++] = pdoc->CharAt(i);
+                                       }
+                                       if (pdoc->eolMode != SC_EOL_LF)
+                                               text[j++] = '\r';
+                                       if (pdoc->eolMode != SC_EOL_CR)
+                                               text[j++] = '\n';
+                               }
+                               text[totalSize] = '\0';
+                       }
+               }
+               return text;
+       } else {
+               return CopyRange(SelectionStart(), SelectionEnd());
+       }
+}
+
+void Editor::CopySelectionIntoDrag() {
+       delete []dragChars;
+       dragChars = 0;
+       lenDrag = SelectionRangeLength();
+       dragChars = CopySelectionRange();
+       dragIsRectangle = selType == selRectangle;
+       if (!dragChars) {
+               lenDrag = 0;
+       }
+}
+
+void Editor::SetDragPosition(int newPos) {
+       if (newPos >= 0) {
+               newPos = pdoc->MovePositionOutsideChar(newPos, 1);
+               posDrop = newPos;
+       }
+       if (posDrag != newPos) {
+               caret.on = true;
+               SetTicking(true);
+               InvalidateCaret();
+               posDrag = newPos;
+               InvalidateCaret();
+       }
+}
+
+void Editor::StartDrag() {
+       // Always handled by subclasses
+       //SetMouseCapture(true);
+       //wDraw.SetCursor(Window::cursorArrow);
+}
+
+void Editor::DropAt(int position, const char *value, bool moving, bool rectangular) {
+       //Platform::DebugPrintf("DropAt %d\n", inDragDrop);
+       if (inDragDrop)
+               dropWentOutside = false;
+
+       int positionWasInSelection = PositionInSelection(position);
+
+       if ((!inDragDrop) || !(0 == positionWasInSelection)) {
+
+               int selStart = SelectionStart();
+               int selEnd = SelectionEnd();
+               
+               pdoc->BeginUndoAction();
+
+               int positionAfterDeletion = position;
+               if (inDragDrop && moving) {
+                       // Remove dragged out text
+                       if (rectangular) {
+                               int lineStart = pdoc->LineFromPosition(SelectionStart());
+                               int lineEnd = pdoc->LineFromPosition(SelectionEnd());
+                               for (int line=lineStart; line <= lineEnd; line++) {
+                                       int startPos = SelectionStart(line);
+                                       int endPos = SelectionEnd(line);
+                                       if (position >= startPos) {
+                                               if (position > endPos) {
+                                                       positionAfterDeletion -= endPos - startPos;
+                                               } else {
+                                                       positionAfterDeletion -= position - startPos;
+                                               }
+                                       }
+                               }
+                       } else {
+                               if (position > selStart) {
+                                       positionAfterDeletion -= selEnd - selStart;
+                               }
+                       }
+                       ClearSelection();
+               }
+               position = positionAfterDeletion;
+               
+               if (rectangular) {
+                       PasteRectangular(position, value, strlen(value));
+                       pdoc->EndUndoAction();
+                       // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
+                       SetSelection(position, position);       
+               } else {
+                       position = pdoc->MovePositionOutsideChar(position, currentPos - position);
+                       pdoc->InsertString(position, value);
+                       pdoc->EndUndoAction();
+                       SetSelection(position + strlen(value), position);
+               }
+       } else if (inDragDrop) {
+               SetSelection(position, position);
+       }
+}
+
+static int BeforeInOrAfter(int val, int minim, int maxim) {
+       if (val < minim)
+               return -1;
+       else if (val > maxim)
+               return 1;
+       else
+               return 0;
+}
+
+int Editor::PositionInSelection(int pos) {
+       pos = pdoc->MovePositionOutsideChar(pos, currentPos - pos);
+       if (selType == selRectangle) {
+               if (pos < SelectionStart())
+                       return -1;
+               if (pos > SelectionEnd())
+                       return 1;
+               int linePos = pdoc->LineFromPosition(pos);
+               return BeforeInOrAfter(pos, SelectionStart(linePos), SelectionEnd(linePos));
+       } else {
+               if (currentPos > anchor) {
+                       return BeforeInOrAfter(pos, anchor, currentPos);
+               } else if (currentPos < anchor) {
+                       return BeforeInOrAfter(pos, currentPos, anchor);
+               }
+       }
+       return 1;
+}
+
+bool Editor::PointInSelection(Point pt) {
+       // TODO: fix up for rectangular selection
+       int pos = PositionFromLocation(pt);
+       if (0 == PositionInSelection(pos)) {
+               if (pos == SelectionStart()) {
+                       // see if just before selection
+                       Point locStart = LocationFromPosition(pos);
+                       if (pt.x < locStart.x)
+                               return false;
+               }
+               if (pos == SelectionEnd()) {
+                       // see if just after selection
+                       Point locEnd = LocationFromPosition(pos);
+                       if (pt.x > locEnd.x)
+                               return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+bool Editor::PointInSelMargin(Point pt) {
+       // Really means: "Point in a margin"
+       if (vs.fixedColumnWidth > 0) {  // There is a margin
+               PRectangle rcSelMargin = GetClientRectangle();
+               rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
+               return rcSelMargin.Contains(pt);
+       } else {
+               return false;
+       }
+}
+
+void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+       //Platform::DebugPrintf("Scintilla:ButtonDown %d %d = %d alt=%d\n", curTime, lastClickTime, curTime - lastClickTime, alt);
+       ptMouseLast = pt;
+       int newPos = PositionFromLocation(pt);
+       newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+       inDragDrop = false;
+       
+       bool processed = NotifyMarginClick(pt, shift, ctrl, alt);
+       if (processed)
+               return;
+               
+       if (shift) {
+               SetSelection(newPos);
+       }
+       if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+               //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
+               SetMouseCapture(true);
+               SetEmptySelection(newPos);
+               bool doubleClick = false;
+               // Stop mouse button bounce changing selection type
+               if (curTime != lastClickTime) {
+                       if (selectionType == selChar) {
+                               selectionType = selWord;
+                               doubleClick = true;
+                       } else if (selectionType == selWord) {
+                               selectionType = selLine;
+                       } else {
+                               selectionType = selChar;
+                               originalAnchorPos = currentPos;
+                       }
+               }
+
+               if (selectionType == selWord) {
+                       if (currentPos >= originalAnchorPos) {  // Moved forward
+                               SetSelection(pdoc->ExtendWordSelect(currentPos, 1),
+                                            pdoc->ExtendWordSelect(originalAnchorPos, -1));
+                       } else {        // Moved backward
+                               SetSelection(pdoc->ExtendWordSelect(currentPos, -1),
+                                            pdoc->ExtendWordSelect(originalAnchorPos, 1));
+                       }
+               } else if (selectionType == selLine) {
+                       lineAnchor = LineFromLocation(pt);
+                       SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+                       //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
+               }
+               else {
+                       SetEmptySelection(currentPos);
+               }
+               //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
+               if (doubleClick)
+                       NotifyDoubleClick(pt, shift);
+       } else {        // Single click
+               if (PointInSelMargin(pt)) {
+                       if (ctrl) {
+                               SelectAll();
+                               lastClickTime = curTime;
+                               return;
+                       }
+                       lineAnchor = LineFromLocation(pt);
+                       // While experimenting with folding turn off line selection
+                       if (!shift) {
+                               // Single click in margin: select whole line
+                               SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor));
+                       } else {
+                               // Single shift+click in margin: select from anchor to beginning of clicked line
+                               SetSelection(pdoc->LineStart(lineAnchor), anchor);
+                       }
+                       SetDragPosition(invalidPosition);
+                       SetMouseCapture(true);
+                       selectionType = selLine;
+               } else {
+                       if (!shift) {
+                               inDragDrop = PointInSelection(pt);
+                       }
+                       if (inDragDrop) {
+                               SetMouseCapture(false);
+                               SetDragPosition(newPos);
+                               CopySelectionIntoDrag();
+                               StartDrag();
+                       } else {
+                               selType = alt ? selRectangle : selStream;
+                               xStartSelect = pt.x - vs.fixedColumnWidth + xOffset;
+                               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+                               SetDragPosition(invalidPosition);
+                               SetMouseCapture(true);
+                               if (!shift)
+                                       SetEmptySelection(newPos);
+                               selectionType = selChar;
+                               originalAnchorPos = currentPos;
+                       }
+               }
+       }
+       lastClickTime = curTime;
+       lastXChosen = pt.x;
+       ShowCaretAtCurrentPosition();
+}
+
+void Editor::ButtonMove(Point pt) {
+       //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
+       if (HaveMouseCapture()) {
+               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+               ptMouseLast = pt;
+               int movePos = PositionFromLocation(pt);
+               movePos = pdoc->MovePositionOutsideChar(movePos, currentPos - movePos);
+               if (posDrag >= 0) {
+                       SetDragPosition(movePos);
+               } else {
+                       if (selectionType == selChar) {
+                               SetSelection(movePos);
+                       } else if (selectionType == selWord) {
+                               // Continue selecting by word
+                               if (currentPos > originalAnchorPos) {   // Moved forward
+                                       SetSelection(pdoc->ExtendWordSelect(movePos, 1),
+                                                    pdoc->ExtendWordSelect(originalAnchorPos, -1));
+                               } else {        // Moved backward
+                                       SetSelection(pdoc->ExtendWordSelect(movePos, -1),
+                                                    pdoc->ExtendWordSelect(originalAnchorPos, 1));
+                               }
+                       } else {
+                               // Continue selecting by line
+                               int lineMove = LineFromLocation(pt);
+                               if (lineAnchor < lineMove) {
+                                       SetSelection(pdoc->LineStart(lineMove + 1),
+                                                               pdoc->LineStart(lineAnchor));
+                               } else {
+                                       SetSelection(pdoc->LineStart(lineMove),
+                                                               pdoc->LineStart(lineAnchor + 1));
+                               }
+                       }
+               }
+               EnsureCaretVisible(false);
+       } else {
+               if (vs.fixedColumnWidth > 0) {  // There is a margin
+                       if (PointInSelMargin(pt)) {
+                               wDraw.SetCursor(Window::cursorReverseArrow);
+                               return;         // No need to test for selection
+                       }
+               }
+               // Display regular (drag) cursor over selection
+               if (PointInSelection(pt))
+                       wDraw.SetCursor(Window::cursorArrow);
+               else
+                       wDraw.SetCursor(Window::cursorText);
+       }
+
+}
+
+void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
+       //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+       if (HaveMouseCapture()) {
+               if (PointInSelMargin(pt)) {
+                       wDraw.SetCursor(Window::cursorReverseArrow);
+               } else {
+                       wDraw.SetCursor(Window::cursorText);
+               }
+               xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
+               ptMouseLast = pt;
+               SetMouseCapture(false);
+               int newPos = PositionFromLocation(pt);
+               newPos = pdoc->MovePositionOutsideChar(newPos, currentPos - newPos);
+               if (inDragDrop) {
+                       int selStart = SelectionStart();
+                       int selEnd = SelectionEnd();
+                       if (selStart < selEnd) {
+                               if (dragChars && lenDrag) {
+                                       if (ctrl) {
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else if (newPos < selStart) {
+                                               pdoc->DeleteChars(selStart, lenDrag);
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else if (newPos > selEnd) {
+                                               pdoc->DeleteChars(selStart, lenDrag);
+                                               newPos -= lenDrag;
+                                               pdoc->InsertString(newPos, dragChars, lenDrag);
+                                               SetSelection(newPos, newPos + lenDrag);
+                                       } else {
+                                               SetEmptySelection(newPos);
+                                       }
+                                       delete []dragChars;
+                                       dragChars = 0;
+                                       lenDrag = 0;
+                               }
+                               selectionType = selChar;
+                       }
+               } else {
+                       if (selectionType == selChar) {
+                               SetSelection(newPos);
+                       }
+               }
+               lastClickTime = curTime;
+               lastClick = pt;
+               lastXChosen = pt.x;
+               inDragDrop = false;
+               EnsureCaretVisible(false);
+       }
+}
+
+// Called frequently to perform background UI including
+// caret blinking and automatic scrolling.
+void Editor::Tick() {
+       if (HaveMouseCapture()) {
+               // Auto scroll
+               ButtonMove(ptMouseLast);
+       }
+       if (caret.period > 0) {
+               timer.ticksToWait -= timer.tickSize;
+               if (timer.ticksToWait <= 0) {
+                       caret.on = !caret.on;
+                       timer.ticksToWait = caret.period;
+                       InvalidateCaret();
+               }
+       }
+}
+
+static bool IsIn(int a, int minimum, int maximum) {
+       return (a >= minimum) && (a <= maximum);
+}
+
+static bool IsOverlap(int mina, int maxa, int minb, int maxb) {
+       return 
+               IsIn(mina, minb, maxb) ||
+               IsIn(maxa, minb, maxb) ||
+               IsIn(minb, mina, maxa) ||
+               IsIn(maxb, mina, maxa);
+}
+
+void Editor::CheckForChangeOutsidePaint(Range r) {
+       if (paintState == painting && !paintingAllText) {
+               //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
+               if (!r.Valid())
+                       return;
+                       
+               PRectangle rcText = GetTextRectangle();
+               // Determine number of lines displayed including a possible partially displayed last line
+               int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1;
+               int bottomLine = topLine + linesDisplayed - 1;
+               
+               int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start));
+               int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end));
+               if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+                       //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
+                       //              lineRangeStart, lineRangeEnd, topLine, bottomLine);
+                       return;
+               }
+               
+               // Assert rcPaint contained within or equal to rcText
+               if (rcPaint.top > rcText.top) {
+                       // does range intersect rcText.top .. rcPaint.top
+                       int paintTopLine = ((rcPaint.top - rcText.top-1) / vs.lineHeight) + topLine;
+                       // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
+                       if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) {
+                               //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n", 
+                               //      lineRangeStart, lineRangeEnd, topLine, paintTopLine);
+                               paintState = paintAbandoned;
+                               return;
+                       }
+               }
+               if (rcPaint.bottom < rcText.bottom) {
+                       // does range intersect rcPaint.bottom .. rcText.bottom
+                       int paintBottomLine = ((rcPaint.bottom - rcText.top-1) / vs.lineHeight + 1) + topLine;
+                       // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
+                       if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) {
+                               //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n", 
+                               //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
+                               paintState = paintAbandoned;
+                               return;
+                       }
+               }
+       }
+}
+
+char BraceOpposite(char ch) {
+       switch (ch) {
+                case '(': return ')';
+                case ')': return '(';
+                case '[': return ']';
+                case ']': return '[';
+                case '{': return '}';
+                case '}': return '{';
+                case '<': return '>';
+                case '>': return '<';
+                default: return '\0';
+       }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+// TODO: may need to make DBCS safe
+// so should be moved into Document
+int Editor::BraceMatch(int position, int maxReStyle) {
+       char chBrace = pdoc->CharAt(position);
+       char chSeek = BraceOpposite(chBrace);
+       if (!chSeek)
+               return - 1;
+       char styBrace = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+       int direction = -1;
+       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+               direction = 1;
+       int depth = 1;
+       position = position + direction;
+       while ((position >= 0) && (position < pdoc->Length())) {
+               char chAtPos = pdoc->CharAt(position);
+               char styAtPos = pdoc->StyleAt(position) & pdoc->stylingBitsMask;
+               if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
+                       if (chAtPos == chBrace)
+                               depth++;
+                       if (chAtPos == chSeek)
+                               depth--;
+                       if (depth == 0)
+                               return position;
+               }
+               position = position + direction;
+       }
+       return - 1;
+}
+
+void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
+       if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
+               if ((braces[0] != pos0)  || (matchStyle != bracesMatchStyle)) {
+                       CheckForChangeOutsidePaint(Range(braces[0]));
+                       CheckForChangeOutsidePaint(Range(pos0));
+                       braces[0] = pos0;
+               }
+               if ((braces[1] != pos1)  || (matchStyle != bracesMatchStyle)) {
+                       CheckForChangeOutsidePaint(Range(braces[1]));
+                       CheckForChangeOutsidePaint(Range(pos1));
+                       braces[1] = pos1;
+               }
+               bracesMatchStyle = matchStyle;
+               if (paintState == notPainting) {
+                       Redraw();
+               }
+       }
+}
+
+void Editor::SetDocPointer(Document *document) {
+       //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
+       pdoc->RemoveWatcher(this, 0);
+       pdoc->Release();
+       if (document == NULL) {
+               pdoc = new Document();
+       } else {
+               pdoc = document;
+       }
+       pdoc->AddRef();
+       pdoc->AddWatcher(this, 0);
+       Redraw();
+       SetScrollBars();
+}
+
+// Recursively expand a fold, making lines visible except where they have an unexpanded parent
+void Editor::Expand(int &line, bool doExpand) {
+       int lineMaxSubord = pdoc->GetLastChild(line);
+       line++;
+       while (line <= lineMaxSubord) {
+               if (doExpand)
+                       cs.SetVisible(line, line, true);
+               int level = pdoc->GetLevel(line);
+               if (level & SC_FOLDLEVELHEADERFLAG) {
+                       if (doExpand && cs.GetExpanded(line)) {
+                               Expand(line, true);
+                       } else {
+                               Expand(line, false);
+                       }
+               } else {
+                       line++;
+               }
+       }
+}
+
+void Editor::ToggleContraction(int line) {
+       if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) {
+               if (cs.GetExpanded(line)) {
+                       int lineMaxSubord = pdoc->GetLastChild(line);
+                       cs.SetExpanded(line, 0);
+                       if (lineMaxSubord > line) {
+                               cs.SetVisible(line+1, lineMaxSubord, false);
+                               SetScrollBars();
+                               Redraw();
+                       }
+               } else {
+                       cs.SetExpanded(line, 1);
+                       Expand(line, true);
+                       SetScrollBars();
+                       Redraw();
+               }
+       }
+}
+
+// Recurse up from this line to find any folds that prevent this line from being visible
+// and unfold them all.
+void Editor::EnsureLineVisible(int line) {
+       if (!cs.GetVisible(line)) {
+               int lineParent = pdoc->GetFoldParent(line);
+               if (lineParent >= 0) {
+                       if (line != lineParent)
+                               EnsureLineVisible(lineParent);
+                       if (!cs.GetExpanded(lineParent)) {
+                               cs.SetExpanded(lineParent, 1);
+                               Expand(lineParent, true);
+                       }
+               }
+               SetScrollBars();
+               Redraw();
+       }
+}
+
+LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
+
+       // Optional macro recording hook
+#ifdef MACRO_SUPPORT
+       if (recordingMacro)
+               NotifyMacroRecord(iMessage, wParam, lParam);
+#endif
+
+       switch (iMessage) {
+
+       case WM_GETTEXT:
+               {
+                       if (lParam == 0)
+                               return 0;
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       unsigned int iChar = 0;
+                       for (; iChar < wParam-1; iChar++)
+                               ptr[iChar] = pdoc->CharAt(iChar);
+                       ptr[iChar] = '\0';
+                       return iChar;
+               }
+
+       case WM_SETTEXT:
+               {
+                       if (lParam == 0)
+                               return FALSE;
+                       pdoc->DeleteChars(0, pdoc->Length());
+                       SetEmptySelection(0);
+                       pdoc->InsertString(0, reinterpret_cast<char *>(lParam));
+                       return TRUE;
+               }
+
+       case WM_GETTEXTLENGTH:
+               return pdoc->Length();
+
+       case WM_NOTIFY:
+               //Platform::DebugPrintf("S notify %d %d\n", wParam, lParam);
+               break;
+
+       case WM_CUT:
+               Cut();
+               SetLastXChosen();
+               break;
+
+       case WM_COPY:
+               Copy();
+               break;
+
+       case WM_PASTE:
+               Paste();
+               SetLastXChosen();
+               break;
+
+       case WM_CLEAR:
+               Clear();
+               SetLastXChosen();
+               break;
+
+       case WM_UNDO:
+               Undo();
+               SetLastXChosen();
+               break;
+
+               // Edit control mesages
+
+               // Not supported (no-ops):
+               //              EM_GETWORDBREAKPROC
+               //              EM_GETWORDBREAKPROCEX
+               //              EM_SETWORDBREAKPROC
+               //              EM_SETWORDBREAKPROCEX
+               //              EM_GETWORDWRAPMODE
+               //              EM_SETWORDWRAPMODE
+               //              EM_LIMITTEXT
+               //              EM_EXLIMITTEXT
+               //              EM_SETRECT
+               //              EM_SETRECTNP
+               //              EM_FMTLINES
+               //              EM_GETHANDLE
+               //              EM_SETHANDLE
+               //              EM_GETPASSWORDCHAR
+               //              EM_SETPASSWORDCHAR
+               //              EM_SETTABSTOPS
+               //              EM_FINDWORDBREAK
+               //              EM_GETCHARFORMAT
+               //              EM_SETCHARFORMAT
+               //              EM_GETOLEINTERFACE
+               //              EM_SETOLEINTERFACE
+               //              EM_SETOLECALLBACK
+               //              EM_GETPARAFORMAT
+               //              EM_SETPARAFORMAT
+               //              EM_PASTESPECIAL
+               //              EM_REQUESTRESIZE
+               //              EM_GETBKGNDCOLOR
+               //              EM_SETBKGNDCOLOR
+               //              EM_STREAMIN
+               //              EM_STREAMOUT
+               //              EM_GETIMECOLOR
+               //              EM_SETIMECOLOR
+               //              EM_GETIMEOPTIONS
+               //              EM_SETIMEOPTIONS
+               //              EM_GETOPTIONS
+               //              EM_SETOPTIONS
+               //              EM_GETPUNCTUATION
+               //              EM_SETPUNCTUATION
+               //              EM_GETTHUMB
+
+               // Not supported but should be:
+               //              EM_GETEVENTMASK
+               //              EM_SETEVENTMASK
+               //              For printing:
+               //                      EM_DISPLAYBAND
+               //                      EM_SETTARGETDEVICE
+
+       case EM_CANUNDO:
+               return pdoc->CanUndo() ? TRUE : FALSE;
+
+       case EM_UNDO:
+               Undo();
+               break;
+
+       case EM_EMPTYUNDOBUFFER:
+               pdoc->DeleteUndoHistory();
+               return 0;
+
+       case EM_GETFIRSTVISIBLELINE:
+               return topLine;
+
+       case EM_GETLINE: {
+                       if (lParam == 0)
+                               return 0;
+                       int lineStart = pdoc->LineStart(wParam);
+                       int lineEnd = pdoc->LineStart(wParam + 1);
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       WORD *pBufSize = reinterpret_cast<WORD *>(lParam);
+                       if (*pBufSize < lineEnd - lineStart) {
+                               ptr[0] = '\0';  // If no characters copied have to put a NUL into buffer
+                               return 0;
+                       }
+                       int iPlace = 0;
+                       for (int iChar = lineStart; iChar < lineEnd; iChar++)
+                               ptr[iPlace++] = pdoc->CharAt(iChar);
+                       return iPlace;
+               }
+
+       case EM_GETLINECOUNT:
+               if (pdoc->LinesTotal() == 0)
+                       return 1;
+               else
+                       return pdoc->LinesTotal();
+
+       case EM_GETMODIFY:
+               return !pdoc->IsSavePoint();
+
+       case EM_SETMODIFY:
+               // Not really supported now that there is the save point stuff
+               //pdoc->isModified = wParam;
+               //return pdoc->isModified;
+               return false;
+
+       case EM_GETRECT:
+               if (lParam == 0)
+                       return 0;
+               *(reinterpret_cast<PRectangle *>(lParam)) = GetClientRectangle();
+               break;
+
+       case EM_GETSEL:
+               if (wParam)
+                       *reinterpret_cast<int *>(wParam) = SelectionStart();
+               if (lParam)
+                       *reinterpret_cast<int *>(lParam) = SelectionEnd();
+               return MAKELONG(SelectionStart(), SelectionEnd());
+
+       case EM_EXGETSEL: {
+                       if (lParam == 0)
+                               return 0;
+                       CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+                       pCR->cpMin = SelectionStart();
+                       pCR->cpMax = SelectionEnd();
+               }
+               break;
+
+       case EM_SETSEL: {
+                       int nStart = static_cast<int>(wParam);
+                       int nEnd = static_cast<int>(lParam);
+                       if (nEnd < 0)
+                               nEnd = pdoc->Length();
+                       if (nStart < 0)
+                               nStart = nEnd;  // Remove selection
+                       SetSelection(nEnd, nStart);
+                       EnsureCaretVisible();
+               }
+               break;
+
+       case EM_EXSETSEL: {
+                       if (lParam == 0)
+                               return 0;
+                       CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
+                       if (pCR->cpMax == -1) {
+                               SetSelection(pCR->cpMin, pdoc->Length());
+                       } else {
+                               SetSelection(pCR->cpMin, pCR->cpMax);
+                       }
+                       EnsureCaretVisible();
+                       return pdoc->LineFromPosition(SelectionStart());
+               }
+
+       case EM_GETSELTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       int selSize = SelectionRangeLength();
+                       char *text = CopySelectionRange();
+                       int iChar = 0;
+                       if (text) {
+                               for (; iChar < selSize; iChar++)
+                                       ptr[iChar] = text[iChar];
+                               ptr[iChar] = '\0';
+                               delete []text;
+                       }
+                       return iChar;
+               }
+
+       case EM_GETWORDBREAKPROC:
+               return 0;
+
+       case EM_SETWORDBREAKPROC:
+               break;
+
+       case EM_LIMITTEXT:
+               // wParam holds the number of characters control should be limited to
+               break;
+
+       case EM_GETLIMITTEXT:
+               return 0xffffffff;
+
+       case EM_GETOLEINTERFACE:
+               return 0;
+
+       case EM_LINEFROMCHAR:
+               if (static_cast<int>(wParam) < 0)
+                       wParam = SelectionStart();
+               return pdoc->LineFromPosition(wParam);
+
+       case EM_EXLINEFROMCHAR:
+               if (static_cast<int>(lParam) < 0)
+                       lParam = SelectionStart();      // Not specified, but probably OK
+               return pdoc->LineFromPosition(lParam);
+
+       case EM_LINEINDEX:
+               if (static_cast<int>(wParam) < 0)
+                       wParam = pdoc->LineFromPosition(SelectionStart());
+               if (wParam == 0)
+                       return 0;       // Even if there is no text, there is a first line that starts at 0
+               if (static_cast<int>(wParam) > pdoc->LinesTotal())
+                       return - 1;
+               //if (wParam > pdoc->LineFromPosition(pdoc->Length()))  // Useful test, anyway...
+               //      return -1;
+               return pdoc->LineStart(wParam);
+
+       case EM_LINELENGTH:
+               {
+                       if (static_cast<int>(wParam) < 0)       // Who use this anyway?
+                               return 0;       // Should be... Too complex to describe here, see MS specs!
+                       if (static_cast<int>(wParam) > pdoc->Length())  // Useful test, anyway...
+                               return 0;
+                       int line = pdoc->LineFromPosition(wParam);
+                       int charsOnLine = 0;
+                       for (int pos = pdoc->LineStart(line); pos < pdoc->LineStart(line + 1); pos++) {
+                               if ((pdoc->CharAt(pos) != '\r') && (pdoc->CharAt(pos) != '\n'))
+                                       charsOnLine++;
+                       }
+                       return charsOnLine;
+               }
+
+               // Replacement of the old Scintilla interpretation of EM_LINELENGTH
+       case SCI_LINELENGTH:
+               if ((static_cast<int>(wParam) < 0) ||
+                       (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
+                       return 0;
+               return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
+
+       case EM_REPLACESEL: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->BeginUndoAction();
+                       ClearSelection();
+                       char *replacement = reinterpret_cast<char *>(lParam);
+                       pdoc->InsertString(currentPos, replacement);
+                       pdoc->EndUndoAction();
+                       SetEmptySelection(currentPos + strlen(replacement));
+                       EnsureCaretVisible();
+               }
+               break;
+
+       case EM_LINESCROLL:
+               ScrollTo(topLine + lParam);
+               HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
+               return TRUE;
+
+       case EM_SCROLLCARET:
+               EnsureCaretVisible();
+               break;
+
+       case EM_SETREADONLY:
+               pdoc->SetReadOnly(wParam);
+               return TRUE;
+
+       case EM_SETRECT:
+               break;
+
+       case EM_CANPASTE:
+               return 1;
+
+       case EM_CHARFROMPOS: {
+                       if (lParam == 0)
+                               return 0;
+                       Point *ppt = reinterpret_cast<Point *>(lParam);
+                       int pos = PositionFromLocation(*ppt);
+                       int line = pdoc->LineFromPosition(pos);
+                       return MAKELONG(pos, line);
+               }
+
+       case EM_POSFROMCHAR: {
+                       // The MS specs for this have changed 3 times: using the RichEdit 3 version
+                       if (wParam == 0)
+                               return 0;
+                       Point *ppt = reinterpret_cast<Point *>(wParam);
+                       if (lParam < 0) {
+                               *ppt = Point(0, 0);
+                       } else {
+                               *ppt = LocationFromPosition(lParam);
+                       }
+                       return 0;
+               }
+
+       case EM_FINDTEXT:
+               return FindText(iMessage, wParam, lParam);
+
+       case EM_FINDTEXTEX:
+               return FindText(iMessage, wParam, lParam);
+
+       case EM_GETTEXTRANGE: {
+                       if (lParam == 0)
+                               return 0;
+                       TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+                       int cpMax = tr->chrg.cpMax;
+                       if (cpMax == -1)
+                               cpMax = pdoc->Length();
+                       int len = cpMax - tr->chrg.cpMin;       // No -1 as cpMin and cpMax are referring to inter character positions
+                       pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+                       // Spec says copied text is terminated with a NUL
+                       tr->lpstrText[len] = '\0';
+                       return len;     // Not including NUL
+               }
+
+       case EM_SELECTIONTYPE:
+               if (currentPos == anchor)
+                       return SEL_EMPTY;
+               else
+                       return SEL_TEXT;
+
+       case EM_HIDESELECTION:
+               hideSelection = wParam;
+               Redraw();
+               break;
+
+       case EM_FORMATRANGE:
+               return FormatRange(wParam, reinterpret_cast<FORMATRANGE *>(lParam));
+
+       case EM_GETMARGINS:
+               return MAKELONG(vs.leftMarginWidth, vs.rightMarginWidth);
+               
+       case EM_SETMARGINS:
+               if (wParam & EC_LEFTMARGIN) {
+                       vs.leftMarginWidth = LOWORD(lParam);
+               }
+               if (wParam & EC_RIGHTMARGIN) {
+                       vs.rightMarginWidth = HIWORD(lParam);
+               }
+               if (wParam == EC_USEFONTINFO) {
+                       vs.leftMarginWidth = vs.aveCharWidth / 2;
+                       vs.rightMarginWidth = vs.aveCharWidth / 2;
+               }
+               InvalidateStyleRedraw();
+               break;
+       
+               // Control specific mesages
+
+       case SCI_ADDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->InsertString(CurrentPosition(), reinterpret_cast<char *>(lParam), wParam);
+                       SetEmptySelection(currentPos + wParam);
+                       return 0;
+               }
+
+       case SCI_ADDSTYLEDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->InsertStyledString(CurrentPosition() * 2, reinterpret_cast<char *>(lParam), wParam);
+                       SetEmptySelection(currentPos + wParam / 2);
+                       return 0;
+               }
+
+       case SCI_INSERTTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       int insertPos = wParam;
+                       if (static_cast<short>(wParam) == -1)
+                               insertPos = CurrentPosition();
+                       int newCurrent = CurrentPosition();
+                       int newAnchor = anchor;
+                       char *sz = reinterpret_cast<char *>(lParam);
+                       pdoc->InsertString(insertPos, sz);
+                       if (newCurrent > insertPos)
+                               newCurrent += strlen(sz);
+                       if (newAnchor > insertPos)
+                               newAnchor += strlen(sz);
+                       SetEmptySelection(newCurrent);
+                       return 0;
+               }
+
+       case SCI_CLEARALL:
+               ClearAll();
+               return 0;
+
+       case SCI_SETUNDOCOLLECTION:
+               pdoc->SetUndoCollection(static_cast<enum undoCollectionType>(wParam));
+               return 0;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_APPENDUNDOSTARTACTION:
+               pdoc->AppendUndoStartAction();
+               return 0;
+#endif
+
+       case SCI_BEGINUNDOACTION:
+               pdoc->BeginUndoAction();
+               return 0;
+
+       case SCI_ENDUNDOACTION:
+               pdoc->EndUndoAction();
+               return 0;
+
+       case SCI_GETCARETPERIOD:
+               return caret.period;
+
+       case SCI_SETCARETPERIOD:
+               caret.period = wParam;
+               break;
+
+       case SCI_SETWORDCHARS: {
+                       if (lParam == 0)
+                               return 0;
+                       pdoc->SetWordChars(reinterpret_cast<unsigned char *>(lParam));
+               }
+               break;
+
+       case SCI_GETLENGTH:
+               return pdoc->Length();
+
+       case SCI_GETCHARAT:
+               return pdoc->CharAt(wParam);
+
+       case SCI_GETCURRENTPOS:
+               return currentPos;
+
+       case SCI_GETANCHOR:
+               return anchor;
+
+       case SCI_GETSTYLEAT:
+               if (static_cast<short>(wParam) >= pdoc->Length())
+                       return 0;
+               else
+                       return pdoc->StyleAt(wParam);
+
+       case SCI_REDO:
+               Redo();
+               break;
+
+       case SCI_SELECTALL:
+               SelectAll();
+               break;
+
+       case SCI_SETSAVEPOINT:
+               pdoc->SetSavePoint();
+               NotifySavePoint(true);
+               break;
+
+       case SCI_GETSTYLEDTEXT: {
+                       if (lParam == 0)
+                               return 0;
+                       TEXTRANGE *tr = reinterpret_cast<TEXTRANGE *>(lParam);
+                       int iPlace = 0;
+                       for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
+                               tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
+                               tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
+                       }
+                       tr->lpstrText[iPlace] = '\0';
+                       tr->lpstrText[iPlace + 1] = '\0';
+                       return iPlace;
+               }
+
+       case SCI_CANREDO:
+               return pdoc->CanRedo() ? TRUE : FALSE;
+
+       case SCI_MARKERLINEFROMHANDLE:
+               return pdoc->LineFromHandle(wParam);
+
+       case SCI_MARKERDELETEHANDLE:
+               pdoc->DeleteMarkFromHandle(wParam);
+               break;
+
+       case SCI_GETVIEWWS:
+               return vs.viewWhitespace;
+
+       case SCI_SETVIEWWS:
+               vs.viewWhitespace = wParam;
+               Redraw();
+               break;
+
+       case SCI_GOTOLINE:
+               GoToLine(wParam);
+               break;
+
+       case SCI_GOTOPOS:
+               SetEmptySelection(wParam);
+               EnsureCaretVisible();
+               Redraw();
+               break;
+
+       case SCI_SETANCHOR:
+               SetSelection(currentPos, wParam);
+               break;
+
+       case SCI_GETCURLINE: {
+                       if (lParam == 0)
+                               return 0;
+                       int lineCurrentPos = pdoc->LineFromPosition(currentPos);
+                       int lineStart = pdoc->LineStart(lineCurrentPos);
+                       unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
+                       char *ptr = reinterpret_cast<char *>(lParam);
+                       unsigned int iPlace = 0;
+                       for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam; iChar++)
+                               ptr[iPlace++] = pdoc->CharAt(iChar);
+                       ptr[iPlace] = '\0';
+                       return currentPos - lineStart;
+               }
+
+       case SCI_GETENDSTYLED:
+               return pdoc->GetEndStyled();
+
+       case SCI_GETEOLMODE:
+               return pdoc->eolMode;
+
+       case SCI_SETEOLMODE:
+               pdoc->eolMode = wParam;
+               break;
+
+       case SCI_STARTSTYLING:
+               pdoc->StartStyling(wParam, lParam);
+               break;
+
+       case SCI_SETSTYLING:
+               pdoc->SetStyleFor(wParam, lParam);
+               break;
+
+       case SCI_SETSTYLINGEX:   // Specify a complete styling buffer
+               if (lParam == 0)
+                       return 0;
+               pdoc->SetStyles(wParam, reinterpret_cast<char *>(lParam));
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETMARGINWIDTH:
+               if (wParam < 100) {
+                       vs.ms[1].width = wParam;
+               }
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETBUFFEREDDRAW:
+               bufferedDraw = wParam;
+               break;
+
+       case SCI_SETTABWIDTH:
+               if (wParam > 0)
+                       pdoc->tabInChars = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETCODEPAGE:
+               pdoc->dbcsCodePage = wParam;
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETLINENUMBERWIDTH:
+               if (wParam < 200) {
+                       vs.ms[0].width = wParam;
+               }
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETUSEPALETTE:
+               palette.allowRealization = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+               // Marker definition and setting
+       case SCI_MARKERDEFINE:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].markType = lParam;
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERSETFORE:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].fore.desired = Colour(lParam);
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERSETBACK:
+               if (wParam <= MARKER_MAX)
+                       vs.markers[wParam].back.desired = Colour(lParam);
+               InvalidateStyleData();
+               RedrawSelMargin();
+               break;
+       case SCI_MARKERADD: {
+                       int markerID = pdoc->AddMark(wParam, lParam);
+                       RedrawSelMargin();
+                       return markerID;
+               }
+
+       case SCI_MARKERDELETE:
+               pdoc->DeleteMark(wParam, lParam);
+               RedrawSelMargin();
+               break;
+
+       case SCI_MARKERDELETEALL:
+               pdoc->DeleteAllMarks(static_cast<int>(wParam));
+               RedrawSelMargin();
+               break;
+
+       case SCI_MARKERGET:
+               return pdoc->GetMark(wParam);
+
+       case SCI_MARKERNEXT: {
+                       int lt = pdoc->LinesTotal();
+                       for (int iLine = wParam; iLine < lt; iLine++) {
+                               if ((pdoc->GetMark(iLine) & lParam) != 0)
+                                       return iLine;
+                       }
+               }
+               return -1;
+
+       case SCI_MARKERPREVIOUS: {
+                       for (int iLine = wParam; iLine >= 0; iLine--) {
+                               if ((pdoc->GetMark(iLine) & lParam) != 0)
+                                       return iLine;
+                       }
+               }
+               return -1;
+
+       case SCI_SETMARGINTYPEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].symbol = (lParam == SC_MARGIN_SYMBOL);
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINTYPEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].symbol ? SC_MARGIN_SYMBOL : SC_MARGIN_NUMBER;
+               else
+                       return 0;
+                       
+       case SCI_SETMARGINWIDTHN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].width = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINWIDTHN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].width;
+               else
+                       return 0;
+                       
+       case SCI_SETMARGINMASKN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].mask = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINMASKN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].mask;
+               else
+                       return 0;
+               
+       case SCI_SETMARGINSENSITIVEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) {
+                       vs.ms[wParam].sensitive = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_GETMARGINSENSITIVEN:
+               if (wParam >= 0 && wParam < ViewStyle::margins) 
+                       return vs.ms[wParam].sensitive ? 1 : 0;
+               else
+                       return 0;
+
+       case SCI_STYLECLEARALL:
+               vs.ClearStyles();
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_STYLESETFORE:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].fore.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETBACK:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].back.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETBOLD:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].bold = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETITALIC:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].italic = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETEOLFILLED:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].eolFilled = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETSIZE:
+               if (wParam <= STYLE_MAX) {
+                       vs.styles[wParam].size = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+       case SCI_STYLESETFONT:
+               if (lParam == 0)
+                       return 0;
+               if (wParam <= STYLE_MAX) {
+                       strcpy(vs.styles[wParam].fontName, reinterpret_cast<char *>(lParam));
+                       InvalidateStyleRedraw();
+               }
+               break;
+               
+       case SCI_STYLERESETDEFAULT:
+               vs.ResetDefaultStyle();
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSTYLEBITS:
+               pdoc->SetStylingBits(wParam);
+               break;
+               
+       case SCI_GETSTYLEBITS:
+               return pdoc->stylingBits;
+               
+       case SCI_SETLINESTATE:
+               return pdoc->SetLineState(wParam, lParam);
+               
+       case SCI_GETLINESTATE:
+               return pdoc->GetLineState(wParam);
+               
+       case SCI_GETMAXLINESTATE:
+               return pdoc->GetMaxLineState();
+               
+       // Folding messages
+               
+       case SCI_VISIBLEFROMDOCLINE:
+               return cs.DisplayFromDoc(wParam);
+               
+       case SCI_DOCLINEFROMVISIBLE:
+               return cs.DocFromDisplay(wParam);
+
+       case SCI_SETFOLDLEVEL: {
+                       int prev = pdoc->SetLevel(wParam, lParam);
+                       if (prev != lParam)
+                               RedrawSelMargin();
+                       return prev;
+               }
+               
+       case SCI_GETFOLDLEVEL:
+               return pdoc->GetLevel(wParam);
+               
+       case SCI_GETLASTCHILD:
+               return pdoc->GetLastChild(wParam, lParam);
+               
+       case SCI_GETFOLDPARENT:
+               return pdoc->GetFoldParent(wParam);
+               
+       case SCI_SHOWLINES:
+               cs.SetVisible(wParam, lParam, true);
+               SetScrollBars();
+               Redraw();
+               break;
+               
+       case SCI_HIDELINES:
+               cs.SetVisible(wParam, lParam, false);
+               SetScrollBars();
+               Redraw();
+               break;
+               
+       case SCI_GETLINEVISIBLE:
+               return cs.GetVisible(wParam);
+               
+       case SCI_SETFOLDEXPANDED:
+               if (cs.SetExpanded(wParam, lParam)) {
+                       RedrawSelMargin();
+               }
+               break;
+       
+       case SCI_GETFOLDEXPANDED:
+               return cs.GetExpanded(wParam);
+               
+       case SCI_SETFOLDFLAGS:
+               foldFlags = wParam;
+               Redraw();
+               break;
+
+       case SCI_TOGGLEFOLD:
+               ToggleContraction(wParam);
+               break;
+               
+       case SCI_ENSUREVISIBLE:
+               EnsureLineVisible(wParam);
+               break;
+               
+       case SCI_SEARCHANCHOR:
+               SearchAnchor();
+               break;
+
+       case SCI_SEARCHNEXT:
+       case SCI_SEARCHPREV:
+               return SearchText(iMessage, wParam, lParam);
+               break;
+
+       case SCI_SETCARETPOLICY:
+               caretPolicy = wParam;
+               caretSlop = lParam;
+               break;
+
+#ifdef INCLUDE_DEPRECATED_FEATURES
+       case SCI_SETFORE:
+               vs.styles[STYLE_DEFAULT].fore.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETBACK:
+               vs.styles[STYLE_DEFAULT].back.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETBOLD:
+               vs.styles[STYLE_DEFAULT].bold = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETITALIC:
+               vs.styles[STYLE_DEFAULT].italic = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSIZE:
+               vs.styles[STYLE_DEFAULT].size = wParam;
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETFONT:
+               if (wParam == 0)
+                       return 0;
+               strcpy(vs.styles[STYLE_DEFAULT].fontName, reinterpret_cast<char *>(wParam));
+               InvalidateStyleRedraw();
+               break;
+#endif
+
+       case SCI_SETSELFORE:
+               vs.selforeset = wParam;
+               vs.selforeground.desired = Colour(lParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETSELBACK:
+               vs.selbackset = wParam;
+               vs.selbackground.desired = Colour(lParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_SETCARETFORE:
+               vs.caretcolour.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+
+       case SCI_ASSIGNCMDKEY:
+               kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), lParam);
+               break;
+
+       case SCI_CLEARCMDKEY:
+               kmap.AssignCmdKey(LOWORD(wParam), HIWORD(wParam), WM_NULL);
+               break;
+
+       case SCI_CLEARALLCMDKEYS:
+               kmap.Clear();
+               break;
+
+       case SCI_INDICSETSTYLE:
+               if (wParam <= INDIC_MAX) {
+                       vs.indicators[wParam].style = lParam;
+                       InvalidateStyleRedraw();
+               }
+               break;
+
+       case SCI_INDICGETSTYLE:
+               return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
+
+       case SCI_INDICSETFORE:
+               if (wParam <= INDIC_MAX) {
+                       vs.indicators[wParam].fore.desired = Colour(lParam);
+                       InvalidateStyleRedraw();
+               }
+               break;
+
+       case SCI_INDICGETFORE:
+               return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.desired.AsLong() : 0;
+
+       case SCI_LINEDOWN:
+       case SCI_LINEDOWNEXTEND:
+       case SCI_LINEUP:
+       case SCI_LINEUPEXTEND:
+       case SCI_CHARLEFT:
+       case SCI_CHARLEFTEXTEND:
+       case SCI_CHARRIGHT:
+       case SCI_CHARRIGHTEXTEND:
+       case SCI_WORDLEFT:
+       case SCI_WORDLEFTEXTEND:
+       case SCI_WORDRIGHT:
+       case SCI_WORDRIGHTEXTEND:
+       case SCI_HOME:
+       case SCI_HOMEEXTEND:
+       case SCI_LINEEND:
+       case SCI_LINEENDEXTEND:
+       case SCI_DOCUMENTSTART:
+       case SCI_DOCUMENTSTARTEXTEND:
+       case SCI_DOCUMENTEND:
+       case SCI_DOCUMENTENDEXTEND:
+       case SCI_PAGEUP:
+       case SCI_PAGEUPEXTEND:
+       case SCI_PAGEDOWN:
+       case SCI_PAGEDOWNEXTEND:
+       case SCI_EDITTOGGLEOVERTYPE:
+       case SCI_CANCEL:
+       case SCI_DELETEBACK:
+       case SCI_TAB:
+       case SCI_BACKTAB:
+       case SCI_NEWLINE:
+       case SCI_FORMFEED:
+       case SCI_VCHOME:
+       case SCI_VCHOMEEXTEND:
+       case SCI_ZOOMIN:
+       case SCI_ZOOMOUT:
+       case SCI_DELWORDLEFT:
+       case SCI_DELWORDRIGHT:
+               return KeyCommand(iMessage);
+
+       case SCI_BRACEHIGHLIGHT:
+               SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
+               break;
+               
+       case SCI_BRACEBADLIGHT:
+               SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
+               break;
+
+       case SCI_BRACEMATCH:
+               // wParam is position of char to find brace for,
+               // lParam is maximum amount of text to restyle to find it
+               return BraceMatch(wParam, lParam);
+
+       case SCI_GETVIEWEOL:
+               return vs.viewEOL;
+
+       case SCI_SETVIEWEOL:
+               vs.viewEOL = wParam;
+               Redraw();
+               break;
+
+       case SCI_GETEDGECOLUMN:
+               return theEdge;
+               
+       case SCI_SETEDGECOLUMN:
+               theEdge = wParam;
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETEDGEMODE:
+               return edgeState;
+               
+       case SCI_SETEDGEMODE:
+               edgeState = wParam;
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETEDGECOLOUR:
+               return vs.edgecolour.desired.AsLong();
+               
+       case SCI_SETEDGECOLOUR:
+               vs.edgecolour.desired = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+               
+       case SCI_GETDOCPOINTER:
+               return reinterpret_cast<LRESULT>(pdoc);
+
+       case SCI_SETDOCPOINTER:
+               SetDocPointer(reinterpret_cast<Document *>(lParam));
+               return 0;
+
+       case SCI_SETMODEVENTMASK:
+               modEventMask = wParam;
+               return 0;
+               
+       case SCI_CONVERTEOLS:
+               pdoc->ConvertLineEnds(wParam);
+               SetSelection(currentPos, anchor);       // Ensure selection inside document
+               return 0;
+
+#ifdef MACRO_SUPPORT
+       case SCI_STARTRECORD:
+               recordingMacro = 1;
+               return 0;
+
+       case SCI_STOPRECORD:
+               recordingMacro = 0;
+               return 0;
+#endif
+               
+       default:
+               return DefWndProc(iMessage, wParam, lParam);
+       }
+       //Platform::DebugPrintf("end wnd proc\n");
+       return 0l;
+}
diff --git a/src/stc/scintilla/src/Editor.h b/src/stc/scintilla/src/Editor.h
new file mode 100644 (file)
index 0000000..4ff3347
--- /dev/null
@@ -0,0 +1,281 @@
+// Scintilla source code edit control
+// Editor.h - defines the main editor class
+// Copyright 1998-2000 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
+
+class Caret {
+public:
+       bool active;
+       bool on;
+       int period;
+               
+       Caret();
+};
+
+class Timer {
+
+public:
+       bool ticking;
+       int ticksToWait;
+       enum {tickSize = 100};
+       int tickerID;
+               
+       Timer();
+};
+
+class LineLayout {
+public:
+       // Drawing is only performed for maxLineLength characters on each line.
+       enum {maxLineLength = 4000};
+       int numCharsInLine;
+       char chars[maxLineLength];
+       char styles[maxLineLength];
+       char indicators[maxLineLength];
+       int positions[maxLineLength];
+};
+
+class Editor : public DocWatcher {
+protected:     // ScintillaBase subclass needs access to much of Editor
+
+       // On GTK+, Scintilla is a container widget holding two scroll bars and a drawing area
+       // whereas on Windows there is just one window with both scroll bars turned on.
+       // Therefore, on GTK+ the following are separate windows but only one window on Windows.
+       Window wMain;   // The Scintilla parent window
+       Window wDraw;   // The text drawing area
+
+       // 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;
+       
+       bool hideSelection;
+       bool inOverstrike;
+
+       // 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;
+
+       int xOffset;                            // Horizontal scrolled amount in pixels
+       int xCaretMargin;       // Ensure this many pixels visible on both sides of caret
+       
+       Surface pixmapLine;
+       Surface pixmapSelMargin;
+       Surface pixmapSelPattern;
+       // Intellimouse support - currently only implemented for Windows
+       unsigned int ucWheelScrollLines;
+       short cWheelDelta; //wheel delta from roll
+
+       KeyMap kmap;
+
+       Caret caret;
+       Timer timer;
+
+       Point lastClick;
+       unsigned int lastClickTime;
+       enum { selChar, selWord, selLine } selectionType;
+       Point ptMouseLast;
+       bool firstExpose;
+       bool inDragDrop;
+       bool dropWentOutside;
+       int posDrag;
+       int posDrop;
+       int lastXChosen;
+       int lineAnchor;
+       int originalAnchorPos;
+       int currentPos;
+       int anchor;
+       int topLine;
+       int posTopLine;
+       
+       bool needUpdateUI;
+       Position braces[2];
+       int bracesMatchStyle;
+       
+       int edgeState;
+       int theEdge;
+
+       enum { notPainting, painting, paintAbandoned } paintState;
+       PRectangle rcPaint;
+       bool paintingAllText;
+       
+       int modEventMask;
+       
+       char *dragChars;
+       int lenDrag;
+       bool dragIsRectangle;
+       enum { selStream, selRectangle, selRectangleFixed } selType;
+       int xStartSelect;
+       int xEndSelect;
+       
+       int caretPolicy;
+       int caretSlop;
+
+       int searchAnchor;
+
+#ifdef MACRO_SUPPORT
+       int recordingMacro;
+#endif
+
+       int foldFlags;
+       ContractionState cs;
+
+       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();
+
+       PRectangle GetClientRectangle();
+       PRectangle GetTextRectangle();
+       
+       int LinesOnScreen();
+       int LinesToScroll();
+       int MaxScrollPos();
+       Point LocationFromPosition(unsigned int pos);
+       int XFromPosition(unsigned int pos);
+       int PositionFromLocation(Point pt);
+       int PositionFromLineX(int line, int x);
+       int LineFromLocation(Point pt);
+       void SetTopLine(int topLineNew);
+       
+       void RedrawRect(PRectangle rc);
+       void Redraw();
+       void RedrawSelMargin();
+       PRectangle RectangleFromRange(int start, int end);
+       void InvalidateRange(int start, int end);
+       
+       int CurrentPosition();
+       bool SelectionEmpty();
+       int SelectionStart(int line=-1);
+       int SelectionEnd(int line=-1);
+       void SetSelection(int currentPos_, int anchor_);
+       void SetSelection(int currentPos_);
+       void SetEmptySelection(int currentPos_);
+       int MovePositionTo(int newPos, bool extend = false);
+       int MovePositionSoVisible(int pos, int moveDir);
+       void SetLastXChosen();
+
+       void ScrollTo(int line);
+       virtual void ScrollText(int linesToMove);
+       void HorizontalScrollTo(int xPos);
+       void EnsureCaretVisible(bool useMargin=true);
+       void ShowCaretAtCurrentPosition();
+       void DropCaret();
+       void InvalidateCaret();
+
+       void PaintSelMargin(Surface *surface, PRectangle &rc);
+        void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll);
+       void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, 
+               PRectangle rcLine, LineLayout &ll);
+       void Paint(Surface *surfaceWindow, PRectangle rcArea);
+       long FormatRange(bool draw, FORMATRANGE *pfr);
+
+       virtual void SetVerticalScrollPos() = 0;
+       virtual void SetHorizontalScrollPos() = 0;
+       virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
+       void SetScrollBarsTo(PRectangle rsClient);
+       void SetScrollBars();
+
+       virtual void AddChar(char ch);
+       void ClearSelection();
+       void ClearAll();
+       void Cut();
+       void PasteRectangular(int pos, const char *ptr, int len);
+       virtual void Copy() = 0;
+       virtual void Paste() = 0;
+       void Clear();
+       void SelectAll();
+       void Undo();
+       void Redo();
+       void DelChar();
+       void DelCharBack();
+       virtual void ClaimSelection() = 0;
+
+       virtual void NotifyChange() = 0;
+       virtual void NotifyFocus(bool focus);
+       virtual void NotifyParent(SCNotification scn) = 0;
+       virtual void NotifyStyleNeeded(int endStyleNeeded);
+       void NotifyChar(char ch);
+       void NotifySavePoint(bool isSavePoint);
+       void NotifyModifyAttempt();
+       virtual void NotifyDoubleClick(Point pt, bool shift);
+       void NotifyUpdateUI();
+       bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
+       void NotifyNeedShown(int pos, int len);
+       
+       void NotifyModifyAttempt(Document *document, void *userData);
+       void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
+       void NotifyModified(Document *document, DocModification mh, void *userData);
+       void NotifyDeleted(Document *document, void *userData);
+       
+#ifdef MACRO_SUPPORT
+       void NotifyMacroRecord(UINT iMessage, WPARAM wParam, LPARAM lParam);
+#endif
+
+       void PageMove(int direction, bool extend=false);
+       virtual int KeyCommand(UINT iMessage);
+       virtual int KeyDefault(int /* key */, int /*modifiers*/);
+       int KeyDown(int key, bool shift, bool ctrl, bool alt);
+
+       bool GetWhitespaceVisible();
+       void SetWhitespaceVisible(bool view);
+
+       void Indent(bool forwards);
+
+       long FindText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+       void SearchAnchor();
+       long SearchText(UINT iMessage,WPARAM wParam,LPARAM lParam);
+       void GoToLine(int lineNo);
+
+       char *CopyRange(int start, int end);
+       int SelectionRangeLength();
+       char *CopySelectionRange();
+       void CopySelectionIntoDrag();
+       void SetDragPosition(int newPos);
+       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);
+       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();
+       virtual void SetTicking(bool on) = 0;
+       virtual void SetMouseCapture(bool on) = 0;
+       virtual bool HaveMouseCapture() = 0;
+
+       void CheckForChangeOutsidePaint(Range r);
+       int BraceMatch(int position, int maxReStyle);
+       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 line);
+
+       virtual LRESULT DefWndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) = 0;
+       
+public:
+       // Public so scintilla_send_message can use it
+       virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+       // Public so scintilla_set_id can use it
+       int ctrlID;     
+};
+
+#endif
diff --git a/src/stc/scintilla/src/Indicator.cxx b/src/stc/scintilla/src/Indicator.cxx
new file mode 100644 (file)
index 0000000..fb6ad09
--- /dev/null
@@ -0,0 +1,45 @@
+// Scintilla source code edit control
+// Indicator.cxx - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 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"
+
+void Indicator::Draw(Surface *surface, PRectangle &rc) {
+       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 {        // Either INDIC_PLAIN or unknown
+               surface->MoveTo(rc.left, ymid);
+               surface->LineTo(rc.right, ymid);
+       }
+}
+
diff --git a/src/stc/scintilla/src/Indicator.h b/src/stc/scintilla/src/Indicator.h
new file mode 100644 (file)
index 0000000..2472ced
--- /dev/null
@@ -0,0 +1,18 @@
+// Scintilla source code edit control
+// Indicator.h - defines the style of indicators which are text decorations such as underlining
+// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef INDICATOR_H
+#define INDICATOR_H
+
+class Indicator {
+public:
+       int style;
+       ColourPair fore;
+       Indicator() : style(INDIC_PLAIN), fore(Colour(0,0,0)) {
+       }
+       void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/KeyMap.cxx b/src/stc/scintilla/src/KeyMap.cxx
new file mode 100644 (file)
index 0000000..f339cd2
--- /dev/null
@@ -0,0 +1,111 @@
+// Scintilla source code edit control
+// KeyMap.cxx  - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 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"
+
+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, UINT 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++;
+}
+
+UINT 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;
+}
+
+KeyToCommand KeyMap::MapDefault[] = {
+    VK_DOWN,   SCI_NORM,       SCI_LINEDOWN,
+    VK_DOWN,   SCI_SHIFT,      SCI_LINEDOWNEXTEND,
+    VK_UP,             SCI_NORM,       SCI_LINEUP,
+    VK_UP,             SCI_SHIFT,      SCI_LINEUPEXTEND,
+    VK_LEFT,           SCI_NORM,       SCI_CHARLEFT,
+    VK_LEFT,           SCI_SHIFT,      SCI_CHARLEFTEXTEND,
+    VK_LEFT,           SCI_CTRL,       SCI_WORDLEFT,
+    VK_LEFT,           SCI_CSHIFT,     SCI_WORDLEFTEXTEND,
+    VK_RIGHT,  SCI_NORM,       SCI_CHARRIGHT,
+    VK_RIGHT,  SCI_SHIFT,      SCI_CHARRIGHTEXTEND,
+    VK_RIGHT,  SCI_CTRL,       SCI_WORDRIGHT,
+    VK_RIGHT,  SCI_CSHIFT,     SCI_WORDRIGHTEXTEND,
+    VK_HOME,   SCI_NORM,       SCI_VCHOME,
+    VK_HOME,   SCI_SHIFT,      SCI_VCHOMEEXTEND,
+    VK_HOME,   SCI_CTRL,       SCI_DOCUMENTSTART,
+    VK_HOME,   SCI_CSHIFT,     SCI_DOCUMENTSTARTEXTEND,
+    VK_END,            SCI_NORM,       SCI_LINEEND,
+    VK_END,            SCI_SHIFT,      SCI_LINEENDEXTEND,
+    VK_END,            SCI_CTRL,       SCI_DOCUMENTEND,
+    VK_END,            SCI_CSHIFT,     SCI_DOCUMENTENDEXTEND,
+    VK_PRIOR,  SCI_NORM,       SCI_PAGEUP,
+    VK_PRIOR,  SCI_SHIFT,      SCI_PAGEUPEXTEND,
+    VK_NEXT,   SCI_NORM,       SCI_PAGEDOWN,
+    VK_NEXT,   SCI_SHIFT,      SCI_PAGEDOWNEXTEND,
+    VK_DELETE,         SCI_NORM,       WM_CLEAR,
+    VK_DELETE,         SCI_SHIFT,      WM_CUT,
+    VK_DELETE,         SCI_CTRL,       SCI_DELWORDRIGHT,
+    VK_INSERT,         SCI_NORM,       SCI_EDITTOGGLEOVERTYPE,
+    VK_INSERT,         SCI_SHIFT,      WM_PASTE,
+    VK_INSERT,         SCI_CTRL,       WM_COPY,
+    VK_ESCAPE,         SCI_NORM,       SCI_CANCEL,
+    VK_BACK,           SCI_NORM,       SCI_DELETEBACK,
+    VK_BACK,           SCI_CTRL,       SCI_DELWORDLEFT,
+    'Z',                       SCI_CTRL,       WM_UNDO,
+    'Y',                       SCI_CTRL,       SCI_REDO,
+    'X',                       SCI_CTRL,       WM_CUT,
+    'C',                       SCI_CTRL,       WM_COPY,
+    'V',                       SCI_CTRL,       WM_PASTE,
+    'A',                       SCI_CTRL,       SCI_SELECTALL,
+    VK_TAB,            SCI_NORM,       SCI_TAB,
+    VK_TAB,            SCI_SHIFT,      SCI_BACKTAB,
+    VK_RETURN,         SCI_NORM,       SCI_NEWLINE,
+    'L',                       SCI_CTRL,       SCI_FORMFEED,
+    VK_ADD,            SCI_CTRL,       SCI_ZOOMIN,
+    VK_SUBTRACT,       SCI_CTRL,       SCI_ZOOMOUT,
+    0,0,0,
+};
+
diff --git a/src/stc/scintilla/src/KeyMap.h b/src/stc/scintilla/src/KeyMap.h
new file mode 100644 (file)
index 0000000..814f3aa
--- /dev/null
@@ -0,0 +1,35 @@
+// Scintilla source code edit control
+// KeyMap.h - defines a mapping between keystrokes and commands
+// Copyright 1998-2000 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
+
+#define SCI_NORM 0
+#define SCI_SHIFT SHIFT_PRESSED
+#define SCI_CTRL LEFT_CTRL_PRESSED
+#define SCI_ALT LEFT_ALT_PRESSED
+#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
+
+class KeyToCommand {
+public:
+       int key;
+       int modifiers;
+       UINT msg;
+};
+
+class KeyMap {
+       KeyToCommand *kmap;
+       int len;
+       int alloc;
+       static KeyToCommand MapDefault[];
+public:
+       KeyMap();
+       ~KeyMap();
+       void Clear();
+       void AssignCmdKey(int key, int modifiers, UINT msg);
+       UINT Find(int key, int modifiers);      // 0 returned on failure
+};
+
+#endif
diff --git a/src/stc/scintilla/src/KeyWords.cxx b/src/stc/scintilla/src/KeyWords.cxx
new file mode 100644 (file)
index 0000000..20f6762
--- /dev/null
@@ -0,0 +1,2217 @@
+// SciTE - Scintilla based Text Editor
+// KeyWords.cxx - colourise for particular languages
+// Copyright 1998-2000 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"
+
+inline bool IsLeadByte(int codePage, char ch) {
+#if PLAT_GTK
+       // TODO: support DBCS under GTK+
+       return false;
+#elif PLAT_WIN 
+       return codePage && IsDBCSLeadByteEx(codePage, ch);
+#elif PLAT_WX 
+       return false;
+#endif 
+}
+
+inline bool iswordchar(char ch) {
+       return isalnum(ch) || ch == '.' || ch == '_';
+}
+
+inline bool iswordstart(char ch) {
+       return isalnum(ch) || ch == '_';
+}
+
+enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
+
+static int IndentAmount(StylingContext &styler, int line, int *flags) {
+       int end = styler.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 = styler.LineStart(line);
+       char ch = styler[pos];
+       int indent = 0;
+       bool inPrevPrefix = line > 0;
+       int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
+       while ((ch == ' ' || ch == '\t') && (pos < end)) {
+               if (inPrevPrefix) {
+                       char chPrev = styler[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 = styler[++pos];
+       }
+       
+       *flags = spaceFlags;
+       indent += SC_FOLDLEVELBASE;
+       if (isspace(ch)) // Completely empty line
+               return indent | SC_FOLDLEVELWHITEFLAG;
+       else
+               return indent;
+}
+
+inline bool isoperator(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 == '>' || ch == ',' || ch == '/' ||
+               ch == '?' || ch == '!' || ch == '.' || ch == '~')
+               return true;
+       return false;
+}
+
+static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_C_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseCppDoc(int codePage, int startPos, int length,
+                            int initStyle, WordList &keywords, StylingContext &styler) {
+
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+
+       int state = initStyle;
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       int visChars = 0;
+       for (unsigned int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((fold) && ((ch == '\r' && chNext != '\n') || (ch == '\n'))) {
+                       int lev = levelPrev;
+                       if (visChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       styler.SetLevel(lineCurrent, lev);
+                       lineCurrent++;
+                       visChars = 0;
+                       levelPrev = levelCurrent;
+               }
+               if (!isspace(ch))
+                       visChars++;
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_STRINGEOL) {
+                       if (ch != '\r' && ch != '\n') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                       }
+               }
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (styler.SafeGetCharAt(i + 2) == '*')
+                                       state = SCE_C_COMMENTDOC;
+                               else
+                                       state = SCE_C_COMMENT;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '/') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_CHARACTER;
+                               startSeg = i;
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_PREPROCESSOR;
+                               startSeg = i;
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_C_OPERATOR);
+                               startSeg = i + 1;
+                               if ((ch == '{') || (ch == '}')) {
+                                       levelCurrent += (ch == '{') ? 1 : -1;
+                               }
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordCpp(startSeg, i - 1, keywords, styler);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                               if (ch == '/' && chNext == '*') {
+                                       if (styler.SafeGetCharAt(i + 2) == '*')
+                                               state = SCE_C_COMMENTDOC;
+                                       else
+                                               state = SCE_C_COMMENT;
+                               } else if (ch == '/' && chNext == '/') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_CHARACTER;
+                               } else if (ch == '#') {
+                                       state = SCE_C_PREPROCESSOR;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                                       if ((ch == '{') || (ch == '}')) {
+                                               levelCurrent += (ch == '{') ? 1 : -1;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_PREPROCESSOR) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_COMMENT) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTDOC) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 3) || ((initStyle == SCE_C_COMMENTDOC) && (startSeg == startPos)))) {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_STRINGEOL;
+                                       startSeg = i;
+                               } else if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_CHARACTER) {
+                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_STRINGEOL;
+                                       startSeg = i;
+                               } else if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '/' && chNext == '*') {
+                                       if (styler.SafeGetCharAt(i + 2) == '*')
+                                               state = SCE_C_COMMENTDOC;
+                                       else
+                                               state = SCE_C_COMMENT;
+                               } else if (ch == '/' && chNext == '/') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_CHARACTER;
+                               } else if (ch == '#') {
+                                       state = SCE_C_PREPROCESSOR;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                                       if ((ch == '{') || (ch == '}')) {
+                                               levelCurrent += (ch == '{') ? 1 : -1;
+                                       }
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, 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);
+               
+       }
+}
+
+inline bool isPerlOperator(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 == '<' || ch == '>' || ch == ',' || ch == '/' ||
+               ch == '?' || ch == '!' || ch == '.' || ch == '~')
+               return true;
+       return false;
+}
+
+static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_PL_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_PL_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_PL_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+       return chAttr;
+}
+
+static bool isEndVar(char ch) {
+       return !isalnum(ch) && ch != '#' && ch != '$' &&
+              ch != '_' && ch != '\'';
+}
+
+static bool isMatch(StylingContext &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;
+}
+
+static bool isOKQuote(char ch) {
+       if (isalnum(ch))
+               return false;
+       if (isspace(ch))
+               return false;
+       if (iscntrl(ch))
+               return false;
+       return true;
+}
+
+static char opposite(char ch) {
+       if (ch == '(')
+               return ')';
+       if (ch == '[')
+               return ']';
+       if (ch == '{')
+               return '}';
+       if (ch == '<')
+               return '>';
+       return ch;
+}
+
+static void ColourisePerlDoc(int codePage, int startPos, int length, int initStyle,
+                             WordList &keywords, StylingContext &styler) {
+       char sooked[100];
+       int quotes = 0;
+       char quoteDown = 'd';
+       char quoteUp = 'd';
+       int quoteRep = 1;
+       int sookedpos = 0;
+       bool preferRE = true;
+       sooked[sookedpos] = '\0';
+       int state = initStyle;
+       int lengthDoc = startPos + length;
+       // If in a long distance lexical state, seek to the beginning  to find quote characters
+       if (state == SCE_PL_HERE || state == SCE_PL_REGEX || 
+               state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) {
+               while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
+                       startPos--;
+               }
+               state = SCE_PL_DEFAULT;
+       }
+       styler.StartAt(startPos);
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               char chNext2 = styler.SafeGetCharAt(i + 2);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_PL_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (ch == 's' && !isalnum(chNext)) {
+                                       state = SCE_PL_REGSUBST;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 2;
+                                       startSeg = i;
+                               } else if (ch == 'm' && !isalnum(chNext)) {
+                                       state = SCE_PL_REGEX;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 1;
+                                       startSeg = i;
+                               } else if (ch == 't' && chNext == 'r' && !isalnum(chNext2)) {
+                                       state = SCE_PL_REGSUBST;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 2;
+                                       startSeg = i;
+                                       i++;
+                                       chNext = chNext2;
+                               } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isalnum(chNext2)) {
+                                       state = SCE_PL_LONGQUOTE;
+                                       startSeg = i;
+                                       i++;
+                                       chNext = chNext2;
+                                       quotes = 0;
+                                       quoteUp = '\0';
+                                       quoteDown = '\0';
+                                       quoteRep = 1;
+                               } else {
+                                       state = SCE_PL_WORD;
+                                       startSeg = i;
+                                       preferRE = false;
+                               }
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_STRING;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               if (chPrev == '&') {
+                                       // Archaic call
+                                       styler.ColourSegment(i, i, state);
+                                       startSeg = i + 1;
+                               } else {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_PL_CHARACTER;
+                                       startSeg = i;
+                               }
+                       } else if (ch == '`') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_BACKTICKS;
+                               startSeg = i;
+                       } else if (ch == '$') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalnum(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_SCALAR;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_SCALAR);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                                       chNext = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_SCALAR);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '@') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_ARRAY;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_ARRAY);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_ARRAY);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '%') {
+                               preferRE = false;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                                       state = SCE_PL_HASH;
+                                       startSeg = i;
+                               } else if (chNext != '{' && chNext != '[') {
+                                       styler.ColourSegment(i - 1, i, SCE_PL_HASH);
+                                       i++;
+                                       startSeg = i + 1;
+                                       ch = ' ';
+                               } else {
+                                       styler.ColourSegment(i, i, SCE_PL_HASH);
+                                       startSeg = i + 1;
+                               }
+                       } else if (ch == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_SYMBOLTABLE;
+                               startSeg = i;
+                       } else if (ch == '/' && preferRE) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_REGEX;
+                               quoteUp = '/';
+                               quoteDown = '/';
+                               quotes = 1;
+                               quoteRep = 1;
+                               startSeg = i;
+                       } else if (ch == '<' && chNext == '<') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_HERE;
+                               startSeg = i;
+                               i++;
+                               ch = chNext;
+                               chNext = chNext2;
+                               quotes = 0;
+                               sookedpos = 0;
+                               sooked[sookedpos] = '\0';
+                       } else if (ch == '=' && isalpha(chNext)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_PL_POD;
+                               startSeg = i;
+                               quotes = 0;
+                               sookedpos = 0;
+                               sooked[sookedpos] = '\0';
+                       } else if (isPerlOperator(ch)) {
+                               if (ch == ')' || ch == ']')
+                                       preferRE = false;
+                               else
+                                       preferRE = true;
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_PL_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_PL_WORD) {
+                       if (!iswordchar(ch) && ch != '\'') {    // Archaic Perl has quotes inside names
+                               if (isMatch(styler, lengthDoc, startSeg, "__DATA__")) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+                                       state = SCE_PL_DATASECTION;
+                               } else if (isMatch(styler, lengthDoc, startSeg, "__END__")) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
+                                       state = SCE_PL_DATASECTION;
+                               } else {
+                                       if (classifyWordPerl(startSeg, i - 1, keywords, styler) == SCE_PL_WORD)
+                                               preferRE = true;
+                                       state = SCE_PL_DEFAULT;
+                                       startSeg = i;
+                                       if (ch == '#') {
+                                               state = SCE_PL_COMMENTLINE;
+                                       } else if (ch == '\"') {
+                                               state = SCE_PL_STRING;
+                                       } else if (ch == '\'') {
+                                               state = SCE_PL_CHARACTER;
+                                       } else if (ch == '<' && chNext == '<') {
+                                               state = SCE_PL_HERE;
+                                               quotes = 0;
+                                               startSeg = i;
+                                               sookedpos = 0;
+                                               sooked[sookedpos] = '\0';
+                                       } else if (isPerlOperator(ch)) {
+                                               if (ch == ')' || ch == ']')
+                                                       preferRE = false;
+                                               else
+                                                       preferRE = true;
+                                               styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+                                               state = SCE_PL_DEFAULT;
+                                               startSeg = i + 1;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_PL_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_PL_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_HERE) {
+                               if (isalnum(ch) && quotes < 2) {
+                                       sooked[sookedpos++] = ch;
+                                       sooked[sookedpos] = '\0';
+                                       if (quotes == 0)
+                                               quotes = 1;
+                               } else {
+                                       quotes++;
+                               }
+
+                               if (quotes > 1 && isMatch(styler, lengthDoc, i, sooked)) {
+                                       styler.ColourSegment(startSeg, i + sookedpos - 1, SCE_PL_HERE);
+                                       state = SCE_PL_DEFAULT;
+                                       i += sookedpos;
+                                       startSeg = i;
+                                       chNext = ' ';
+                               }
+                       } else if (state == SCE_PL_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_BACKTICKS) {
+                               if (ch == '`') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_PL_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_PL_POD) {
+                               if (ch == '=') {
+                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
+                                               styler.ColourSegment(startSeg, i - 1 + 4, state);
+                                               i += 4;
+                                               startSeg = i;
+                                               state = SCE_PL_DEFAULT;
+                                               chNext = ' ';
+                                               ch = ' ';
+                                       }
+                               }
+                       } else if (state == SCE_PL_SCALAR) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_ARRAY) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_HASH) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_SYMBOLTABLE) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_REF) {
+                               if (isEndVar(ch)) {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       startSeg = i;
+                                       state = SCE_PL_DEFAULT;
+                               }
+                       } else if (state == SCE_PL_REGEX) {
+                               if (!quoteUp && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(ch);
+                                       quotes++;
+                               } else {
+                                       if (ch == quoteDown && chPrev != '\\') {
+                                               quotes--;
+                                               if (quotes == 0) {
+                                                       quoteRep--;
+                                                       if (quoteUp == quoteDown) {
+                                                               quotes++;
+                                                       }
+                                               }
+                                               if (!isalpha(chNext)) {
+                                                       if (quoteRep <= 0) {
+                                                               styler.ColourSegment(startSeg, i, state);
+                                                               startSeg = i + 1;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = ' ';
+                                                       }
+                                               }
+                                       } else if (ch == quoteUp && chPrev != '\\') {
+                                               quotes++;
+                                       } else if (!isalpha(chNext)) {
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                       }
+                               }
+                       } else if (state == SCE_PL_REGSUBST) {
+                               if (!quoteUp && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(ch);
+                                       quotes++;
+                               } else {
+                                       if (ch == quoteDown && chPrev != '\\') {
+                                               quotes--;
+                                               if (quotes == 0) {
+                                                       quoteRep--;
+                                               }
+                                               if (!isalpha(chNext)) {
+                                                       if (quoteRep <= 0) {
+                                                               styler.ColourSegment(startSeg, i, state);
+                                                               startSeg = i + 1;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = ' ';
+                                                       }
+                                               }
+                                               if (quoteUp == quoteDown) {
+                                                       quotes++;
+                                               }
+                                       } else if (ch == quoteUp && chPrev != '\\') {
+                                               quotes++;
+                                       } else if (!isalpha(chNext)) {
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                       }
+                               }
+                       } else if (state == SCE_PL_LONGQUOTE) {
+                               if (!quoteDown && !isspace(ch)) {
+                                       quoteUp = ch;
+                                       quoteDown = opposite(quoteUp);
+                                       quotes++;
+                               } else if (ch == quoteDown) {
+                                       quotes--;
+                                       if (quotes == 0) {
+                                               quoteRep--;
+                                               if (quoteRep <= 0) {
+                                                       styler.ColourSegment(startSeg, i, state);
+                                                       startSeg = i + 1;
+                                                       state = SCE_PL_DEFAULT;
+                                                       ch = ' ';
+                                               }
+                                               if (quoteUp == quoteDown) {
+                                                       quotes++;
+                                               }
+                                       }
+                               } else if (ch == quoteUp) {
+                                       quotes++;
+                               }
+                       }
+
+                       if (state == SCE_PL_DEFAULT) {    // One of the above succeeded
+                               if (ch == '#') {
+                                       state = SCE_PL_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_PL_STRING;
+                               } else if (ch == '\'') {
+                                       state = SCE_PL_CHARACTER;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_PL_WORD;
+                                       preferRE = false;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+
+static int classifyWordVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_DEFAULT;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_C_WORD;
+                       if (strcmp(s, "rem") == 0)
+                               chAttr = SCE_C_COMMENTLINE;
+               }
+       }
+       styler.ColourSegment(start, end, chAttr);
+       if (chAttr == SCE_C_COMMENTLINE)
+               return SCE_C_COMMENTLINE;
+       else
+               return SCE_C_DEFAULT;
+}
+
+static void ColouriseVBDoc(int codePage, int startPos, int length, int initStyle,
+                           WordList &keywords, StylingContext &styler) {
+       int state = initStyle;
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       for (int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               state = classifyWordVB(startSeg, i - 1, keywords, styler);
+                               if (state == SCE_C_DEFAULT) {
+                                       startSeg = i;
+                                       if (ch == '\'') {
+                                               state = SCE_C_COMMENTLINE;
+                                       } else if (ch == '\"') {
+                                               state = SCE_C_STRING;
+                                       }
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               // VB doubles quotes to preserve them
+                               if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_C_DEFAULT;
+                                       i++;
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       startSeg = i;
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '\'') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       state = SCE_C_STRING;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               }
+                       }
+               }
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc, state);
+}
+
+static void classifyWordPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]);
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_P_IDENTIFIER;
+       if (0 == strcmp(prevWord, "class"))
+               chAttr = SCE_P_CLASSNAME;
+       else if (0 == strcmp(prevWord, "def"))
+               chAttr = SCE_P_DEFNAME;
+       else if (wordIsNumber)
+               chAttr = SCE_P_NUMBER;
+       else if (keywords.InList(s))
+               chAttr = SCE_P_WORD;
+       styler.ColourSegment(start, end, chAttr);
+       strcpy(prevWord, s);
+}
+
+static void ColourisePyDoc(int codePage, int startPos, int length, int initStyle, WordList &keywords, StylingContext &styler) {
+       //Platform::DebugPrintf("Python coloured\n");
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int whingeLevel = styler.GetPropSet().GetInt("tab.timmy.whinge.level");
+       char prevWord[200];
+       prevWord[0] = '\0';
+       if (length == 0)
+               return ;
+       int lineCurrent = styler.GetLine(startPos);
+       int spaceFlags = 0;
+       // TODO: Need to check previous line for indentation for both folding and bad indentation
+       int indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
+
+       int state = initStyle & 31;
+       char chPrev = ' ';
+       char chPrev2 = ' ';
+       char chNext = styler[startPos];
+       char chNext2 = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       bool atStartLine = true;
+       for (int i = startPos; i <= lengthDoc; i++) {
+       
+               if (atStartLine) {
+                       if (whingeLevel == 1) {
+                               styler.SetFlags((spaceFlags & wsInconsistent) ? 64 : 0, state);
+                       } else if (whingeLevel == 2) {
+                               styler.SetFlags((spaceFlags & wsSpaceTab) ? 64 : 0, state);
+                       } else if (whingeLevel == 3) {
+                               styler.SetFlags((spaceFlags & wsSpace) ? 64 : 0, state);
+                       } else if (whingeLevel == 4) {
+                               styler.SetFlags((spaceFlags & wsTab) ? 64 : 0, state);
+                       }
+                       atStartLine = false;
+               }
+               
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               chNext2 = styler.SafeGetCharAt(i + 2);
+               
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
+                               // Perform colourisation of white space and triple quoted strings at end of each line to allow
+                               // tab marking to work inside white space and triple quoted strings
+                               styler.ColourSegment(startSeg, i, state);
+                               startSeg = i + 1;
+                       }
+
+                       int lev = indentCurrent;
+                       int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               }
+                       }
+                       indentCurrent = indentNext;
+                       if (fold) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       atStartLine = true;
+               }
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       chPrev2 = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_P_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_P_WORD;
+                               startSeg = i;
+                       } else if (ch == '#') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_P_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\"') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               startSeg = i;
+                               if (chNext == '\"' && chNext2 == '\"') {
+                                       i += 2;
+                                       state = SCE_P_TRIPLEDOUBLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_P_STRING;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               startSeg = i;
+                               if (chNext == '\'' && chNext2 == '\'') {
+                                       i += 2;
+                                       state = SCE_P_TRIPLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_P_CHARACTER;
+                               }
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_P_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_P_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordPy(startSeg, i - 1, keywords, styler, prevWord);
+                               state = SCE_P_DEFAULT;
+                               startSeg = i;
+                               if (ch == '#') {
+                                       state = SCE_P_COMMENTLINE;
+                               } else if (ch == '\"') {
+                                       if (chNext == '\"' && chNext2 == '\"') {
+                                               i += 2;
+                                               state = SCE_P_TRIPLEDOUBLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_P_STRING;
+                                       }
+                               } else if (ch == '\'') {
+                                       if (chNext == '\'' && chNext2 == '\'') {
+                                               i += 2;
+                                               state = SCE_P_TRIPLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_P_CHARACTER;
+                                       }
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_P_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               } else {
+                       if (state == SCE_P_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_P_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_TRIPLE) {
+                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_P_TRIPLEDOUBLE) {
+                               if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+                                       styler.ColourSegment(startSeg, i, state);
+                                       state = SCE_P_DEFAULT;
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev2 = chPrev;
+               chPrev = ch;
+       }
+       if (startSeg <= lengthDoc) {
+               if (state == SCE_P_DEFAULT) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_WORD) {
+                       classifyWordPy(startSeg, lengthDoc, keywords, styler, prevWord);
+               } else if (state == SCE_P_COMMENTLINE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_STRING) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_CHARACTER) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_TRIPLE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               } else if (state == SCE_P_TRIPLEDOUBLE) {
+                       styler.ColourSegment(startSeg, lengthDoc, state);
+               }
+       }
+}
+
+static void ColouriseBatchLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       if (0 == strncmp(lineBuffer, "REM", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "rem", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "SET", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (0 == strncmp(lineBuffer, "set", 3)) {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (lineBuffer[0] == ':') {
+               styler.ColourSegment(0, lengthLine - 1, 3);
+       } else {
+               styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColouriseBatchDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i < startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseBatchLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseBatchLine(lineBuffer, linePos, styler);
+}
+
+enum { eScriptNone, eScriptJS, eScriptVBS, eScriptPython };
+static int segIsScriptingIndicator(StylingContext &styler, unsigned int start, unsigned int end, int prevValue) {
+       char s[100];
+       s[0] = '\0';
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+Platform::DebugPrintf("Scripting indicator [%s]\n", s);
+       if (strstr(s, "vbs"))
+               return eScriptVBS;
+       if (strstr(s, "pyth"))
+               return eScriptPython;
+       if (strstr(s, "javas"))
+               return eScriptJS;
+       if (strstr(s, "jscr"))
+               return eScriptJS;
+               
+       return prevValue;
+}
+
+static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.') ||
+                           (styler[start] == '-') || (styler[start] == '#');
+       char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
+       if (wordIsNumber) {
+               chAttr = SCE_H_NUMBER;
+       } else {
+               char s[100];
+               s[0] = '\0';
+               for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+                       s[i] = tolower(styler[start + i]);
+                       s[i + 1] = '\0';
+               }
+               if (keywords.InList(s))
+                       chAttr = SCE_H_ATTRIBUTE;
+       }
+       styler.ColourTo(end, chAttr);
+}
+
+static int classifyTagHTML(unsigned int start, unsigned int end,
+                         WordList &keywords, StylingContext &styler) {
+       char s[100];
+       // Copy after the '<'
+       unsigned int i = 0;
+       for (int cPos=start; cPos <= end && i < 30; cPos++) {
+               char ch = styler[cPos];
+               if (ch != '<')
+                       s[i++] = tolower(ch);
+       }
+       s[i] = '\0';
+       char chAttr = SCE_H_TAGUNKNOWN;
+       if (s[0] == '!' && s[1] == '-' && s[2] == '-') {        //Comment
+               chAttr = SCE_H_COMMENT;
+       } else if (s[0] == '/') {       // Closing tag
+               if (keywords.InList(s + 1))
+                       chAttr = SCE_H_TAG;
+       } else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_H_TAG;
+                       if (0 == strcmp(s, "script"))
+                               chAttr = SCE_H_SCRIPT;
+               }
+       }
+       styler.ColourTo(end, chAttr);
+       return chAttr;
+}
+
+static void classifyWordHTJS(unsigned int start, unsigned int end,
+                             WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_HJ_WORD;
+       if (wordIsNumber)
+               chAttr = SCE_HJ_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_HJ_KEYWORD;
+       }
+       styler.ColourTo(end, chAttr);
+}
+
+static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = tolower(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_HB_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_HB_NUMBER;
+       else {
+               if (keywords.InList(s)) {
+                       chAttr = SCE_HB_WORD;
+                       if (strcmp(s, "rem") == 0)
+                               chAttr = SCE_HB_COMMENTLINE;
+               }
+       }
+       styler.ColourTo(end, chAttr);
+       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, StylingContext &styler, char *prevWord) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]);
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = styler[start + i];
+               s[i + 1] = '\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, chAttr);
+       strcpy(prevWord, s);
+}
+
+inline bool ishtmlwordchar(char ch) {
+       return isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || 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 isLineEnd(char ch) {
+       return ch == '\r' || ch == '\n';
+}
+
+static void ColouriseHyperTextDoc(int codePage, int startPos, int length,
+                                  int initStyle, WordList &keywords, WordList &keywords2, WordList &keywords3, WordList &keywords4, 
+                                 StylingContext &styler) {
+       
+       styler.StartAt(startPos, 63);
+       bool lastTagWasScript = false;
+       char prevWord[200];
+       prevWord[0] = '\0';
+       int scriptLanguage = eScriptJS;
+       int state = initStyle;
+       // If inside a tag, it may be a script tage, so reread from the start to ensure any language tas are seen
+       if (InTagState(state)) {
+               while ((startPos > 1) && (InTagState(styler.StyleAt(startPos - 1)))) {
+                       startPos--;
+               }
+               state = SCE_H_DEFAULT;
+       }
+       styler.StartAt(startPos, 63);
+
+       int lineState = eScriptVBS;
+       int lineCurrent = styler.GetLine(startPos);
+       if (lineCurrent > 0)
+               lineState = styler.GetLineState(lineCurrent);
+       int defaultScript = lineState &0xff;
+       int beforeASP = (lineState >> 8) &0xff;
+       int inASP = (lineState >> 16) &0xff;
+       
+       char chPrev = ' ';
+       char chPrev2 = ' ';
+       styler.StartSegment(startPos);
+       int lengthDoc = startPos + length;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = styler[i];
+               char chNext = styler.SafeGetCharAt(i + 1);
+               char chNext2 = styler.SafeGetCharAt(i + 2);
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chPrev2 = ' ';
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       // New line -> record any line state onto /next/ line
+                       lineCurrent++;
+                       styler.SetLineState(lineCurrent, 
+                               defaultScript | (beforeASP << 8) | (inASP << 16));
+               }
+               
+               // Handle ASP even within other constructs as it is a preprocessor
+               if ((ch == '<') && (chNext == '%')) {
+                       beforeASP = state;
+                       styler.ColourTo(i - 1, state);
+                       if (chNext2 == '@') {
+                               styler.ColourTo(i + 2, SCE_H_ASP);
+                               state = SCE_H_ASPAT;
+                               i+=2;
+                       } else {
+                               if (defaultScript == eScriptVBS)
+                                       state = SCE_HB_START;
+                               else if  (defaultScript == eScriptPython)
+                                       state = SCE_HP_START;
+                               else
+                                       state = SCE_HJ_START;
+                               if (chNext2 == '=') {
+                                       styler.ColourTo(i + 2, SCE_H_ASP);
+                                       i+=2;
+                               } else {
+                                       styler.ColourTo(i + 1, SCE_H_ASP);
+                                       i++;
+                               }
+                       }
+                       inASP = 1;
+                       continue;
+               }
+               if (inASP && (ch == '%') && (chNext == '>')) {
+                       if (state == SCE_H_ASPAT)
+                               defaultScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, defaultScript);
+                       // Bounce out of any ASP mode
+                       styler.ColourTo(i - 1, state);
+                       //if (state == SCE_H_ASPAT)
+                       //      styler.ColourTo(i+1, SCE_H_ASPAT);
+                       //else
+                               styler.ColourTo(i+1, SCE_H_ASP);
+                       i++;
+                       state = beforeASP;
+                       beforeASP = SCE_H_DEFAULT;
+                       inASP = 0;
+                       continue;
+               }
+               
+               if (state == SCE_H_DEFAULT) {
+                       if (ch == '<') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                               if (chNext == '?') {
+                                       styler.ColourTo(i + 1, SCE_H_XMLSTART);
+                                       i++;
+                                       ch = chNext;
+                               }
+                       } else if (ch == '&') {
+                               styler.ColourTo(i - 1, SCE_H_DEFAULT);
+                               state = SCE_H_ENTITY;
+                       }
+               } else if (state == SCE_H_COMMENT) {
+                       if ((ch == '>') && (chPrev == '-')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_ENTITY) {
+                       if (ch == ';') {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_TAGUNKNOWN) {
+                       if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+                               int eClass = classifyTagHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+                               lastTagWasScript = eClass == SCE_H_SCRIPT;
+                               if (lastTagWasScript) {
+                                       scriptLanguage = eScriptJS;
+                                       eClass = SCE_H_TAG;
+                               }
+                               if (ch == '>') {
+                                       styler.ColourTo(i, SCE_H_TAG);
+                                       if (lastTagWasScript) {
+                                               if (scriptLanguage == eScriptVBS)
+                                                       state = SCE_HB_START;
+                                               else if  (scriptLanguage == eScriptPython)
+                                                       state = SCE_HP_START;
+                                               else
+                                                       state = SCE_HJ_START;
+                                       } else {
+                                               state = SCE_H_DEFAULT;
+                                       }
+                               } else {
+                                       if (eClass == SCE_H_COMMENT) {
+                                               state = SCE_H_COMMENT;
+                                       } else {
+                                               state = SCE_H_OTHER;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_H_ATTRIBUTE) {
+                       if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, scriptLanguage);
+                               classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
+                               if (ch == '>') {
+                                       styler.ColourTo(i, SCE_H_TAG);
+                                       if (lastTagWasScript) {
+                                               if (scriptLanguage == eScriptVBS)
+                                                       state = SCE_HB_START;
+                                               else if  (scriptLanguage == eScriptPython)
+                                                       state = SCE_HP_START;
+                                               else
+                                                       state = SCE_HJ_START;
+                                       } else {
+                                               state = SCE_H_DEFAULT;
+                                       }
+                               } else {
+                                       state = SCE_H_OTHER;
+                               }
+                       }
+               } else if (state == SCE_H_ASP) {
+                       if ((ch == '>') && (chPrev == '%')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_ASPAT) {
+                       if ((ch == '>') && (chPrev == '%')) {
+                               styler.ColourTo(i, state);
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_H_OTHER) {
+                       if (ch == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_H_TAG);
+                               if (lastTagWasScript) {
+                                       if (scriptLanguage == eScriptVBS)
+                                               state = SCE_HB_START;
+                                       else if  (scriptLanguage == eScriptPython)
+                                               state = SCE_HP_START;
+                                       else
+                                               state = SCE_HJ_START;
+                               } else {
+                                       state = SCE_H_DEFAULT;
+                               }
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_SINGLESTRING;
+                       } else if (ch == '/' && chNext == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       } else if (ch == '?' && chNext == '>') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_XMLEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       } else if (ishtmlwordchar(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_ATTRIBUTE;
+                       }
+               } else if (state == SCE_H_DOUBLESTRING) {
+                       if (ch == '\"') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+                               styler.ColourTo(i, SCE_H_DOUBLESTRING);
+                               state = SCE_H_OTHER;
+                       }
+               } else if (state == SCE_H_SINGLESTRING) {
+                       if (ch == '\'') {
+                               if (lastTagWasScript)
+                                       scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
+                               styler.ColourTo(i, SCE_H_SINGLESTRING);
+                               state = SCE_H_OTHER;
+                       }
+               } else if (state == SCE_HJ_DEFAULT || state == SCE_HJ_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_WORD;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext2 == '*')
+                                       state = SCE_HJ_COMMENTDOC;
+                               else
+                                       state = SCE_HJ_COMMENT;
+                       } else if (ch == '/' && chNext == '/') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_SINGLESTRING;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_COMMENTLINE;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                               state = SCE_HJ_DEFAULT;
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HJ_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HJ_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HJ_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler);
+                               //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 (isoperator(ch)) {
+                                       styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                                       state = SCE_HJ_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HJ_COMMENT) {
+                       if (ch == '/' && chPrev == '*') {
+                               state = SCE_HJ_DEFAULT;
+                               styler.ColourTo(i, SCE_HJ_COMMENT);
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_HJ_COMMENTDOC) {
+                       if (ch == '/' && chPrev == '*') {
+                               state = SCE_HJ_DEFAULT;
+                               styler.ColourTo(i, SCE_HJ_COMMENTDOC);
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i + 1, SCE_H_TAGEND);
+                               i++;
+                               ch = chNext;
+                               state = SCE_H_DEFAULT;
+                       }
+               } else if (state == SCE_HJ_COMMENTLINE) {
+                       if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+                               state = SCE_HJ_DEFAULT;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               // Common to hide end script tag in comment
+                               styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
+                               state = SCE_H_TAGUNKNOWN;
+                       }
+               } else if (state == SCE_HJ_DOUBLESTRING) {
+                       if (ch == '\\') {
+                               if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                       i++;
+                               }
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i, SCE_HJ_DOUBLESTRING);
+                               state = SCE_HJ_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (isLineEnd(ch)) {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HJ_STRINGEOL;
+                       }
+               } else if (state == SCE_HJ_SINGLESTRING) {
+                       if (ch == '\\') {
+                               if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                       i++;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i, SCE_HJ_SINGLESTRING);
+                               state = SCE_HJ_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (isLineEnd(ch)) {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HJ_STRINGEOL;
+                       }
+               } else if (state == SCE_HJ_STRINGEOL) {
+                       if (!isLineEnd(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HJ_DEFAULT;
+                       }
+               } else if (state == SCE_HB_DEFAULT || state == SCE_HB_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_WORD;
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_STRING;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HB_DEFAULT);
+                               state = SCE_HB_DEFAULT;
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HB_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HB_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HB_WORD) {
+                       if (!iswordchar(ch)) {
+                               state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler);
+                               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, SCE_HB_DEFAULT);
+                                               state = SCE_HB_DEFAULT;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_HB_STRING) {
+                       if (ch == '\"') {
+                               styler.ColourTo(i, state);
+                               state = SCE_HB_DEFAULT;
+                               i++;
+                               ch = chNext;
+                       } else if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i-1, state);
+                               state = SCE_HB_STRINGEOL;
+                       }
+               } else if (state == SCE_HB_COMMENTLINE) {
+                       if (ch == '\r' || ch == '\n') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_DEFAULT;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               // Common to hide end script tag in comment
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       }
+               } else if (state == SCE_HB_STRINGEOL) {
+                       if (!isLineEnd(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HB_DEFAULT;
+                       }
+               } else if (state == SCE_HP_DEFAULT || state == SCE_HP_START) {
+                       if (iswordstart(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_WORD;
+                       } else if ((ch == '<') && (chNext == '/')) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_H_TAGUNKNOWN;
+                       } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
+                               styler.SafeGetCharAt(i + 3) == '-') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_COMMENTLINE;
+                       } else if (ch == '#') {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_HP_COMMENTLINE;
+                       } else if (ch == '\"') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext == '\"' && chNext2 == '\"') {
+                                       i += 2;
+                                       state = SCE_HP_TRIPLEDOUBLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_HP_STRING;
+                               }
+                       } else if (ch == '\'') {
+                               styler.ColourTo(i - 1, state);
+                               if (chNext == '\'' && chNext2 == '\'') {
+                                       i += 2;
+                                       state = SCE_HP_TRIPLE;
+                                       ch = ' ';
+                                       chPrev = ' ';
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               } else {
+                                       state = SCE_HP_CHARACTER;
+                               }
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_HP_OPERATOR);
+                       } else if ((ch == ' ') || (ch == '\t')) {
+                               if (state == SCE_HP_START) {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       }
+               } else if (state == SCE_HP_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
+                               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 = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_HP_STRING;
+                                       }
+                               } else if (ch == '\'') {
+                                       if (chNext == '\'' && chNext2 == '\'') {
+                                               i += 2;
+                                               state = SCE_HP_TRIPLE;
+                                               ch = ' ';
+                                               chPrev = ' ';
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       } else {
+                                               state = SCE_HP_CHARACTER;
+                                       }
+                               } else if (isoperator(ch)) {
+                                       styler.ColourTo(i, SCE_HP_OPERATOR);
+                               }
+                       }
+               } else {
+                       if (state == SCE_HP_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourTo(i - 1, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_STRING) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\"') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_CHARACTER) {
+                               if (ch == '\\') {
+                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               } else if (ch == '\'') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_TRIPLE) {
+                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       } else if (state == SCE_HP_TRIPLEDOUBLE) {
+                               if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
+                                       styler.ColourTo(i, state);
+                                       state = SCE_HP_DEFAULT;
+                               }
+                       }
+               }
+               if (state == SCE_HB_DEFAULT) {    // One of the above succeeded
+                       if (ch == '\"') {
+                               state = SCE_HB_STRING;
+                       } else if (ch == '\'') {
+                               state = SCE_HB_COMMENTLINE;
+                       } else if (iswordstart(ch)) {
+                               state = SCE_HB_WORD;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i, SCE_HB_DEFAULT);
+                       }
+               }
+               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 == '\"') {
+                               state = SCE_HJ_DOUBLESTRING;
+                       } else if (ch == '\'') {
+                               state = SCE_HJ_SINGLESTRING;
+                       } else if (iswordstart(ch)) {
+                               state = SCE_HJ_WORD;
+                       } else if (isoperator(ch)) {
+                               styler.ColourTo(i, SCE_HJ_SYMBOLS);
+                       }
+               }
+               chPrev2 = chPrev;
+               chPrev = ch;
+       }
+       styler.ColourTo(lengthDoc - 1, state);
+}
+
+static void ColourisePropsLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       int i = 0;
+       while (isspace(lineBuffer[i]) && (i < lengthLine))      // Skip initial spaces
+               i++;
+       if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (lineBuffer[i] == '[') {
+               styler.ColourSegment(0, lengthLine - 1, 2);
+       } else if (lineBuffer[i] == '@') {
+               styler.ColourSegment(0, i, 4);
+               if (lineBuffer[++i] == '=')
+                       styler.ColourSegment(i, i, 3);
+               if (++i < lengthLine)
+                       styler.ColourSegment(i, lengthLine - 1, 0);
+       } else {
+               while (lineBuffer[i] != '=' && (i < lengthLine))        // Search the '=' character
+                       i++;
+               if (lineBuffer[i] == '=') {
+                       styler.ColourSegment(0, i - 1, 0);
+                       styler.ColourSegment(i, i, 3);
+                       if (++i < lengthLine)
+                               styler.ColourSegment(i, lengthLine - 1, 0);
+               } else
+                       styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColourisePropsDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       lineBuffer[linePos] = '\0';
+                       ColourisePropsLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColourisePropsLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseMakeLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       int i = 0;
+       while (isspace(lineBuffer[i]) && (i < lengthLine))
+               i++;
+       if (lineBuffer[i] == '#' || lineBuffer[i] == '!') {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else {
+               styler.ColourSegment(0, lengthLine - 1, 0);
+       }
+}
+
+static void ColouriseMakeDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseMakeLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseMakeLine(lineBuffer, linePos, styler);
+}
+
+static void ColouriseErrorListLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
+       if (lineBuffer[0] == '>') {
+               // Command or return status
+               styler.ColourSegment(0, lengthLine - 1, 4);
+       } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
+               styler.ColourSegment(0, lengthLine - 1, 1);
+       } else if (0 == strncmp(lineBuffer, "Error ", strlen("Error "))) {
+               // Borland error message
+               styler.ColourSegment(0, lengthLine - 1, 5);
+       } else if (0 == strncmp(lineBuffer, "Warning ", strlen("Warning "))) {
+               // Borland warning message
+               styler.ColourSegment(0, lengthLine - 1, 5);
+       } else {
+               // Look for <filename>:<line>:message
+               // Look for <filename>(line)message
+               // Look for <filename>(line,pos)message
+               int state = 0;
+               for (int i = 0; i < lengthLine; i++) {
+                       if (state == 0 && lineBuffer[i] == ':' && isdigit(lineBuffer[i + 1])) {
+                               state = 1;
+                       } else if (state == 0 && lineBuffer[i] == '(') {
+                               state = 10;
+                       } else if (state == 1 && isdigit(lineBuffer[i])) {
+                               state = 2;
+                       } else if (state == 2 && lineBuffer[i] == ':') {
+                               state = 3;
+                               break;
+                       } else if (state == 2 && !isdigit(lineBuffer[i])) {
+                               state = 99;
+                       } else if (state == 10 && isdigit(lineBuffer[i])) {
+                               state = 11;
+                       } else if (state == 11 && lineBuffer[i] == ',') {
+                               state = 14;
+                       } else if (state == 11 && lineBuffer[i] == ')') {
+                               state = 12;
+                               break;
+                       } else if (state == 12 && lineBuffer[i] == ':') {
+                               state = 13;
+                       } else if (state == 14 && lineBuffer[i] == ')') {
+                               state = 15;
+                               break;
+                       } else if (((state == 11) || (state == 14)) && !((lineBuffer[i] == ' ') || isdigit(lineBuffer[i]))) {
+                               state = 99;
+                       }
+               }
+               if (state == 3) {
+                       styler.ColourSegment(0, lengthLine - 1, 2);
+               } else if ((state == 14) || (state == 15)) {
+                       styler.ColourSegment(0, lengthLine - 1, 3);
+               } else {
+                       styler.ColourSegment(0, lengthLine - 1, 0);
+               }
+       }
+}
+
+static void ColouriseErrorListDoc(int startPos, int length, int, StylingContext &styler) {
+       char lineBuffer[1024];
+       unsigned int linePos = 0;
+       for (int i = startPos; i <= startPos + length; i++) {
+               lineBuffer[linePos++] = styler[i];
+               if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
+                       ColouriseErrorListLine(lineBuffer, linePos, styler);
+                       linePos = 0;
+               }
+       }
+       if (linePos > 0)
+               ColouriseErrorListLine(lineBuffer, linePos, styler);
+}
+
+static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
+       char s[100];
+       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
+       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
+               s[i] = toupper(styler[start + i]);
+               s[i + 1] = '\0';
+       }
+       char chAttr = SCE_C_IDENTIFIER;
+       if (wordIsNumber)
+               chAttr = SCE_C_NUMBER;
+       else {
+               if (keywords.InList(s))
+                       chAttr = SCE_C_WORD;
+       }
+       styler.ColourSegment(start, end, chAttr);
+}
+
+static void ColouriseSQLDoc(int codePage, int startPos, int length,
+                            int initStyle, WordList &keywords, StylingContext &styler) {
+
+       bool fold = styler.GetPropSet().GetInt("fold");
+       int lineCurrent = styler.GetLine(startPos);
+       int spaceFlags = 0;
+       int indentCurrent = 0;
+
+       int state = initStyle;
+       char chPrev = ' ';
+       char chNext = styler[startPos];
+       int startSeg = startPos;
+       int lengthDoc = startPos + length;
+       bool prevCr = false;
+       for (int i = startPos; i <= lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+                       indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
+                       int lev = indentCurrent;
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
+                               if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               }
+                       }
+                       if (fold) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+               }
+
+               if (IsLeadByte(codePage, ch)) { // dbcs
+                       chNext = styler.SafeGetCharAt(i + 2);
+                       chPrev = ' ';
+                       i += 1;
+                       continue;
+               }
+
+               if (state == SCE_C_DEFAULT) {
+                       if (iswordstart(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_WORD;
+                               startSeg = i;
+                       } else if (ch == '/' && chNext == '*') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENT;
+                               startSeg = i;
+                       } else if (ch == '-' && chNext == '-') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_COMMENTLINE;
+                               startSeg = i;
+                       } else if (ch == '\'') {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               state = SCE_C_STRING;
+                               startSeg = i;
+                       } else if (isoperator(ch)) {
+                               styler.ColourSegment(startSeg, i - 1, state);
+                               styler.ColourSegment(i, i, SCE_C_OPERATOR);
+                               startSeg = i + 1;
+                       }
+               } else if (state == SCE_C_WORD) {
+                       if (!iswordchar(ch)) {
+                               classifyWordSQL(startSeg, i - 1, keywords, styler);
+                               state = SCE_C_DEFAULT;
+                               startSeg = i;
+                               if (ch == '/' && chNext == '*') {
+                                       state = SCE_C_COMMENT;
+                               } else if (ch == '-' && chNext == '-') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_STRING;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               } else {
+                       if (state == SCE_C_COMMENT) {
+                               if (ch == '/' && chPrev == '*' && (
+                                           (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
+                                       state = SCE_C_DEFAULT;
+                                       styler.ColourSegment(startSeg, i, state);
+                                       startSeg = i + 1;
+                               }
+                       } else if (state == SCE_C_COMMENTLINE) {
+                               if (ch == '\r' || ch == '\n') {
+                                       styler.ColourSegment(startSeg, i - 1, state);
+                                       state = SCE_C_DEFAULT;
+                                       startSeg = i;
+                               }
+                       } else if (state == SCE_C_STRING) {
+                               if (ch == '\'') {
+                                       if ( chNext == '\'' ) {
+                                               i++;
+                                       } else {
+                                               styler.ColourSegment(startSeg, i, state);
+                                               state = SCE_C_DEFAULT;
+                                               i++;
+                                               startSeg = i;
+                                       }
+                                       ch = chNext;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                               }
+                       }
+                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
+                               if (ch == '/' && chNext == '*') {
+                                       state = SCE_C_COMMENT;
+                               } else if (ch == '-' && chNext == '-') {
+                                       state = SCE_C_COMMENTLINE;
+                               } else if (ch == '\'') {
+                                       state = SCE_C_STRING;
+                               } else if (iswordstart(ch)) {
+                                       state = SCE_C_WORD;
+                               } else if (isoperator(ch)) {
+                                       styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
+                                       startSeg = i + 1;
+                               }
+                       }
+               }
+               chPrev = ch;
+       }
+       if (startSeg < lengthDoc)
+               styler.ColourSegment(startSeg, lengthDoc - 1, state);
+}
+
+void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle,
+                  int language, WordList *keywordlists[], StylingContext &styler) {
+       //Platform::DebugPrintf("ColouriseDoc <%s>\n", language);
+       if (language == SCLEX_PYTHON) {
+               // Python uses a different mask because bad indentation is marked by oring with 32
+               styler.StartAt(startPos, 127);
+               ColourisePyDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+       } else if (language == SCLEX_PERL) {
+               // 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
+               ColourisePerlDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+       } else if ((language == SCLEX_HTML) || (language == SCLEX_XML)) {
+               // Lexer for HTML requires more lexical states (6 bits worth) than most lexers
+               ColouriseHyperTextDoc(codePage, startPos, lengthDoc, initStyle, 
+                       *keywordlists[0], *keywordlists[1], *keywordlists[2], *keywordlists[3], styler);
+       } else {
+               styler.StartAt(startPos);
+               if (language == SCLEX_CPP) {
+                       ColouriseCppDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_SQL) {
+                       ColouriseSQLDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_VB) {
+                       ColouriseVBDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
+               } else if (language == SCLEX_PROPERTIES) {
+                       ColourisePropsDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_ERRORLIST) {
+                       ColouriseErrorListDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_MAKEFILE) {
+                       ColouriseMakeDoc(startPos, lengthDoc, initStyle, styler);
+               } else if (language == SCLEX_BATCH) {
+                       ColouriseBatchDoc(startPos, lengthDoc, initStyle, styler);
+               } else {
+                       // Null language means all style bytes are 0 so just mark the end - no need to fill in.
+                       styler.StartAt(startPos + lengthDoc - 1);
+                       styler.ColourSegment(0, 0, 0);
+               }
+       }
+}
diff --git a/src/stc/scintilla/src/LineMarker.cxx b/src/stc/scintilla/src/LineMarker.cxx
new file mode 100644 (file)
index 0000000..9afccb8
--- /dev/null
@@ -0,0 +1,125 @@
+// Scintilla source code edit control
+// LineMarker.cxx - defines the look of a line marker in the margin 
+// Copyright 1998-2000 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 "LineMarker.h"
+
+void LineMarker::Draw(Surface *surface, PRectangle &rc) {
+       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;
+       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) {
+               int armSize = dimOn2-2;
+               Point xpts[] = {
+               Point(centreX - armSize, centreY),
+               Point(centreX, centreY),
+               Point(centreX, centreY - armSize),
+               Point(centreX, centreY - armSize),
+               Point(centreX, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX, centreY),
+               Point(centreX, centreY + armSize),
+               Point(centreX, centreY + armSize),
+               Point(centreX, centreY),
+               Point(centreX - armSize, centreY),
+               };
+               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) {
+               int armSize = dimOn2-2;
+               Point pts[] = {
+               Point(centreX - armSize, centreY - 1),
+               Point(centreX + armSize, centreY -1),
+               Point(centreX + armSize, centreY +1),
+               Point(centreX - armSize, centreY + 1),
+               };
+               Point xpts[] = {
+               Point(centreX - armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX + armSize, centreY),
+               Point(centreX - armSize, centreY),
+               };
+               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) {
+               // An invisible marker so don't draw anything
+       } else { // 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);
+       }
+}
diff --git a/src/stc/scintilla/src/LineMarker.h b/src/stc/scintilla/src/LineMarker.h
new file mode 100644 (file)
index 0000000..f22241b
--- /dev/null
@@ -0,0 +1,22 @@
+// Scintilla source code edit control
+// LineMarker.h - defines the look of a line marker in the margin 
+// Copyright 1998-2000 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
+
+class LineMarker {
+public:
+       int markType;
+       ColourPair fore;
+       ColourPair back;
+       LineMarker() {
+               markType = SC_MARK_CIRCLE;
+               fore = Colour(0,0,0);
+               back = Colour(0xff,0xff,0xff);
+       }
+       void Draw(Surface *surface, PRectangle &rc);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/PropSet.cxx b/src/stc/scintilla/src/PropSet.cxx
new file mode 100644 (file)
index 0000000..7e2a906
--- /dev/null
@@ -0,0 +1,399 @@
+// SciTE - Scintilla based Text Editor
+// PropSet.cxx - a java style properties file module
+// Copyright 1998-2000 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 <ctype.h>
+#include <stdio.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+
+bool EqualCaseInsensitive(const char *a, const char *b) {
+#if PLAT_GTK
+       return 0 == strcasecmp(a, b);
+#elif PLAT_WIN
+       return 0 == stricmp(a, b);
+#elif PLAT_WX
+       return 0 == wxStricmp(a, b);
+#endif
+}
+
+// Get a line of input. If end of line escaped with '\\' then continue reading.
+static bool GetFullLine(const char *&fpc, int &lenData, char *s, int len) {
+       bool continuation = true;
+       while ((len > 1) && lenData > 0) {
+               char ch = *fpc;
+               fpc++;
+               lenData--;
+               if ((ch == '\r') || (ch == '\n')) {
+                       if (!continuation) {
+                               if ((lenData > 0) && (ch == '\r') && ((*fpc) == '\n')) {
+                                       // munch the second half of a crlf
+                                       fpc++;
+                                       lenData--;
+                               }
+                               *s++ = '\0';
+                               return true;
+                       }
+               } else if ((ch == '\\') && (lenData > 0) && ((*fpc == '\r') || (*fpc == '\n'))) {
+                       continuation = true;
+               } else {
+                       continuation = false;
+                       *s++ = ch;
+                       len--;
+               }
+       }
+       return false;
+}
+
+PropSet::PropSet() {
+       superPS = 0;
+       size = 10;
+       used = 0;
+       vals = new char * [size];
+}
+
+PropSet::~PropSet() {
+       superPS = 0;
+       Clear();
+       delete []vals;
+}
+
+void PropSet::EnsureCanAddEntry() {
+       if (used >= size - 2) {
+               int newsize = size + 10;
+               char **newvals = new char * [newsize];
+
+               for (int i = 0; i < used; i++) {
+                       newvals[i] = vals[i];
+               }
+               delete []vals;
+               vals = newvals;
+               size = newsize;
+       }
+}
+
+void PropSet::Set(const char *key, const char *val) {
+       EnsureCanAddEntry();
+       for (int i = 0; i < used; i += 2) {
+               if (EqualCaseInsensitive(vals[i], key)) {
+                       // Replace current value
+                       delete [](vals[i + 1]);
+                       vals[i + 1] = StringDup(val);
+                       return;
+               }
+       }
+       // Not found
+       vals[used++] = StringDup(key);
+       vals[used++] = StringDup(val);
+}
+
+void PropSet::Set(char *keyval) {
+       char *eqat = strchr(keyval, '=');
+       if (eqat) {
+               *eqat = '\0';
+               Set(keyval, eqat + 1);
+               *eqat = '=';
+       }
+}
+
+SString PropSet::Get(const char *key) {
+       for (int i = 0; i < used; i += 2) {
+               if (EqualCaseInsensitive(vals[i], key)) {
+                       return vals[i + 1];
+               }
+       }
+       if (superPS) {
+               // Failed here, so try in base property set
+               return superPS->Get(key);
+       } else {
+               return "";
+       }
+}
+
+int PropSet::GetInt(const char *key, int defaultValue) {
+       SString val = Get(key);
+       if (val.length())
+               return Get(key).value();
+       else
+               return defaultValue;
+}
+
+bool isprefix(const char *target, const char *prefix) {
+       while (*target && *prefix) {
+               if (toupper(*target) != toupper(*prefix))
+                       return false;
+               target++;
+               prefix++;
+       }
+       if (*prefix)
+               return false;
+       else
+               return true;
+}
+
+bool issuffix(const char *target, const char *suffix) {
+       int lentarget = strlen(target);
+       int lensuffix = strlen(suffix);
+       if (lensuffix > lentarget)
+               return false;
+       for (int i = lensuffix - 1; i >= 0; i--) {
+               if (toupper(target[i + lentarget - lensuffix]) != toupper(suffix[i]))
+                       return false;
+       }
+       return true;
+}
+
+SString PropSet::GetWild(const char *keybase, const char *filename) {
+       for (int i = 0; i < used; i += 2) {
+               if (isprefix(vals[i], keybase)) {
+                       char *orgkeyfile = vals[i] + strlen(keybase);
+                       char *keyfile = NULL;
+
+                       if (strstr(orgkeyfile, "$(") == orgkeyfile) {
+                               char *cpendvar = strchr(orgkeyfile, ')');
+                               if (cpendvar) {
+                                       int lenvar = cpendvar - orgkeyfile - 2;         // Subtract the $()
+                                       char *var = static_cast<char *>(malloc(lenvar + 1));
+                                       strncpy(var, orgkeyfile + 2, lenvar);
+                                       var[lenvar] = '\0';
+                                       SString s = Get(var);
+                                       free(var);
+                                       keyfile = strdup(s.c_str());
+                               }
+                       }
+                       char *keyptr = keyfile;
+
+                       if (keyfile == NULL)
+                               keyfile = orgkeyfile;
+
+                       for (; ; ) {
+                               char *del = strchr(keyfile, ';');
+                               if (del == NULL)
+                                       del = keyfile + strlen(keyfile);
+                               char delchr = *del;
+                               *del = '\0';
+                               if (*keyfile == '*') {
+                                       if (issuffix(filename, keyfile + 1)) {
+                                               *del = delchr;
+                                               free(keyptr);
+                                               return vals[i + 1];
+                                       }
+                               } else if (EqualCaseInsensitive(keyfile, filename)) {
+                                       *del = delchr;
+                                       free(keyptr);
+                                       return vals[i + 1];
+                               }
+                               if (delchr == '\0')
+                                       break;
+                               *del = delchr;
+                               keyfile = del + 1;
+                       }
+                       free(keyptr);
+
+                       if (EqualCaseInsensitive(vals[i], keybase)) {
+                               return vals[i + 1];
+                       }
+               }
+       }
+       if (superPS) {
+               // Failed here, so try in base property set
+               return superPS->GetWild(keybase, filename);
+       } else {
+               return "";
+       }
+}
+
+SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
+       char *base = StringDup(GetWild(keybase, filename).c_str());
+       char *cpvar = strstr(base, "$(");
+       while (cpvar) {
+               char *cpendvar = strchr(cpvar, ')');
+               if (cpendvar) {
+                       int lenvar = cpendvar - cpvar - 2;      // Subtract the $()
+                       char *var = new char[lenvar + 1];
+                       strncpy(var, cpvar + 2, lenvar);
+                       var[lenvar] = '\0';
+                       SString val = GetWild(var, filename);
+                       int newlenbase = strlen(base) + val.length() - lenvar;
+                       char *newbase = new char[newlenbase];
+                       strncpy(newbase, base, cpvar - base);
+                       strcpy(newbase + (cpvar - base), val.c_str());
+                       strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
+                       delete []var;
+                       delete []base;
+                       base = newbase;
+               }
+               cpvar = strstr(base, "$(");
+       }
+       SString sret = base;
+       delete []base;
+       return sret;
+}
+
+void PropSet::Clear() {
+       for (int i = 0; i < used; i++) {
+               delete [](vals[i]);
+               vals[i] = 0;
+       }
+       used = 0;
+}
+
+void PropSet::ReadFromMemory(const char *data, int len) {
+       if (len > 0) {
+               const char *pd = data;
+               char linebuf[60000];
+               while (GetFullLine(pd, len, linebuf, sizeof(linebuf))) {
+                       if (isalpha(linebuf[0]))
+                               Set(linebuf);
+               }
+       }
+}
+
+void PropSet::Read(const char *filename) {
+       //printf("Opening properties <%s>\n", filename);
+       Clear();
+       char propsData[60000];
+       FILE *rcfile = fopen(filename, "rb");
+       if (rcfile) {
+               int lenFile = fread(propsData, 1, sizeof(propsData), rcfile);
+               fclose(rcfile);
+               ReadFromMemory(propsData, lenFile);
+       } else {
+               //printf("Could not open <%s>\n", filename);
+       }
+}
+
+static bool iswordsep(char ch, bool onlyLineEnds) {
+       if (!isspace(ch))
+               return false;
+       if (!onlyLineEnds)
+               return true;
+       return ch == '\r' || ch == '\n';
+}
+
+// Creates an array that points into each word in the string and puts \0 terminators
+// after each word.
+static char **ArrayFromWordList(char *wordlist, bool onlyLineEnds = false) {
+       char prev = '\n';
+       int words = 0;
+       for (int j = 0; wordlist[j]; j++) {
+               if (!iswordsep(wordlist[j], onlyLineEnds) && iswordsep(prev, onlyLineEnds))
+                       words++;
+               prev = wordlist[j];
+       }
+       char **keywords = new char * [words + 1];
+       if (keywords) {
+               words = 0;
+               prev = '\0';
+               int len = strlen(wordlist);
+               for (int k = 0; k < len; k++) {
+                       if (!iswordsep(wordlist[k], onlyLineEnds)) {
+                               if (!prev) {
+                                       keywords[words] = &wordlist[k];
+                                       words++;
+                               }
+                       } else {
+                               wordlist[k] = '\0';
+                       }
+                       prev = wordlist[k];
+               }
+               keywords[words] = &wordlist[len];
+       }
+       return keywords;
+}
+
+void WordList::Clear() {
+       if (words) {
+               delete []words;
+               delete []list;
+       }
+       words = 0;
+       list = 0;
+       len = 0;
+}
+
+void WordList::Set(const char *s) {
+       len = 0;
+       list = StringDup(s);
+       words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+char *WordList::Allocate(int size) {
+       list = new char[size + 1];
+       list[size] = '\0';
+       return list;
+}
+
+void WordList::SetFromAllocated() {
+       len = 0;
+       words = ArrayFromWordList(list, onlyLineEnds);
+}
+
+// Shell sort based upon public domain C implementation by Raymond Gardner 1991
+// Used here because of problems with mingw qsort.
+static void SortWordList(char **words, unsigned int len) {
+       unsigned int gap = len / 2;
+
+       while (gap > 0) {
+               unsigned int i = gap;
+               while (i < len) {
+                       unsigned int j = i;
+                       char **a = words + j;
+                       do {
+                               j -= gap;
+                               char **b = a;
+                               a -= gap;
+                               if (strcmp(*a, *b) > 0) {
+                                       char *tmp = *a;
+                                       *a = *b;
+                                       *b = tmp;
+                               } else {
+                                       break;
+                               }
+                       } while (j >= gap);
+                       i++;
+               }
+               gap = gap / 2;
+       }
+}
+
+bool WordList::InList(const char *s) {
+       if (0 == words)
+               return false;
+       if (len == 0) {
+               for (int i = 0; words[i][0]; i++)
+                       len++;
+               SortWordList(words, len);
+               for (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) {
+                       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++;
+               }
+       }
+       return false;
+}
diff --git a/src/stc/scintilla/src/SVector.h b/src/stc/scintilla/src/SVector.h
new file mode 100644 (file)
index 0000000..7bc9487
--- /dev/null
@@ -0,0 +1,110 @@
+// Scintilla source code edit control
+// SVector.h - a simple expandable vector
+// Copyright 1998-1999 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
+
+// A simple expandable vector. 
+// T must support assignment.
+// 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.
+template<class T, int sizeIncrement>
+class SVector {
+       T *v;
+       unsigned int size;      // Number of elements allocated
+       unsigned int len;       // Number of elements in vector
+       bool allocFailure;      // A memory allocation call has failed
+       
+       // Internally allocate more elements than the user wants to avoid 
+       // thrashng the memory allocator
+       void SizeTo(int newSize) {
+               if (newSize < sizeIncrement)
+                       newSize += sizeIncrement;
+               else 
+                       newSize = (newSize * 3) / 2;
+               T* newv = new T[newSize];
+               if (!newv) {
+                       allocFailure = true;
+                       return;
+               }
+               size = newSize;
+               for (int i=0; i<len; i++) {
+                       newv[i] = v[i];
+               }
+               delete []v;
+               v = newv;
+       }
+       
+public:
+       SVector() {
+               allocFailure = false;
+               v = 0;
+               len = 0;
+               size = 0;
+       }
+       ~SVector() {
+               Free();
+       }
+       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();
+                       }
+               }
+       }
+       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;
+       }
+       T &operator[](unsigned int i) {
+               if (i >= len) {
+                       if (i >= size) {
+                               SizeTo(i);
+                       }
+                       len = i+1;
+               }
+               return v[i];
+       }
+       void Free() {
+               delete []v;
+               v = 0;
+               size = 0;
+               len = 0;
+       }
+       void SetLength(int newLen) {
+               if (newLength > len) {
+                       if (newLength >= size) {
+                               SizeTo(newLength);
+                       }
+               }
+               len = newLen;
+       }
+       int Length() const {
+               return len;
+       }
+};
+
+#endif
diff --git a/src/stc/scintilla/src/ScintillaBase.cxx b/src/stc/scintilla/src/ScintillaBase.cxx
new file mode 100644 (file)
index 0000000..eb68904
--- /dev/null
@@ -0,0 +1,399 @@
+// Scintilla source code edit control
+// ScintillaBase.cxx - an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 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"
+#ifdef SCI_LEXER
+#include "SciLexer.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#endif
+#include "ContractionState.h"
+#include "SVector.h"
+#include "CellBuffer.h"
+#include "CallTip.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "AutoComplete.h"
+#include "Document.h"
+#include "Editor.h"
+#include "ScintillaBase.h"
+
+ScintillaBase::ScintillaBase() {
+#ifdef SCI_LEXER       
+       lexLanguage = SCLEX_CONTAINER;
+       for (int wl=0;wl<numWordLists;wl++)
+               keyWordLists[wl] = new WordList;
+#endif
+}
+
+ScintillaBase::~ScintillaBase() {}
+
+void ScintillaBase::Finalise() {
+       popup.Destroy();
+}
+
+void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
+       Editor::RefreshColourPalette(pal, want);
+       ct.RefreshColourPalette(pal, want);
+}
+
+void ScintillaBase::AddChar(char ch) {
+       bool acActiveBeforeCharAdded = ac.Active();
+       Editor::AddChar(ch);
+       if (acActiveBeforeCharAdded)
+               AutoCompleteChanged(ch);
+}
+
+void ScintillaBase::Command(int cmdId) {
+
+       switch (cmdId) {
+
+       case idAutoComplete:    // Nothing to do
+               break;
+
+       case idCallTip:         // Nothing to do
+               break;
+
+       case idcmdUndo:
+               WndProc(WM_UNDO, 0, 0);
+               break;
+
+       case idcmdRedo:
+               WndProc(SCI_REDO, 0, 0);
+               break;
+
+       case idcmdCut:
+               WndProc(WM_CUT, 0, 0);
+               break;
+
+       case idcmdCopy:
+               WndProc(WM_COPY, 0, 0);
+               break;
+
+       case idcmdPaste:
+               WndProc(WM_PASTE, 0, 0);
+               break;
+
+       case idcmdDelete:
+               WndProc(WM_CLEAR, 0, 0);
+               break;
+
+       case idcmdSelectAll:
+               WndProc(SCI_SELECTALL, 0, 0);
+               break;
+       }
+}
+
+int ScintillaBase::KeyCommand(UINT 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();
+                       AutoCompleteChanged();
+                       EnsureCaretVisible();
+                       return 0;
+               case SCI_TAB:
+                       AutoCompleteCompleted();
+                       return 0;
+
+               default:
+                       ac.Cancel();
+               }
+       }
+
+       if (ct.inCallTipMode) {
+               if (
+                   (iMessage != SCI_CHARLEFT) &&
+                   (iMessage != SCI_CHARLEFTEXTEND) &&
+                   (iMessage != SCI_CHARRIGHT) &&
+                   (iMessage != SCI_CHARLEFTEXTEND) &&
+                   (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
+                   (iMessage != SCI_DELETEBACK)
+               ) {
+                       ct.CallTipCancel();
+               }
+               if (iMessage == SCI_DELETEBACK) {
+                       if (currentPos <= ct.posStartCallTip) {
+                               ct.CallTipCancel();
+                       }
+               }
+       }
+       return Editor::KeyCommand(iMessage);
+}
+
+void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
+       //Platform::DebugPrintf("AutoCOmplete %s\n", list);
+       ct.CallTipCancel();
+
+       ac.Start(wDraw, idAutoComplete, currentPos, lenEntered);
+
+       PRectangle rcClient = GetClientRectangle();
+       Point pt = LocationFromPosition(currentPos-lenEntered);
+
+       //Platform::DebugPrintf("Auto complete %x\n", lbAutoComplete);
+       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 - 5;
+       if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+           pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
+               rcac.top = pt.y - heightLB;
+               if (rcac.top < 0) {
+                       heightLB += rcac.top;
+                       rcac.top = 0;
+               }
+       } else {
+               rcac.top = pt.y + vs.lineHeight;
+       }
+       rcac.right = rcac.left + widthLB;
+       rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
+       ac.lb.SetPositionRelative(rcac, wMain);
+       ac.lb.SetFont(vs.styles[0].font);
+
+       int maxStrLen = 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.GetPosition();
+       int heightAlloced = rcList.bottom - rcList.top;
+       // Make an allowance for large strings in list
+       rcList.left = pt.x - 5;
+       rcList.right = rcList.left + Platform::Maximum(widthLB, maxStrLen * 8 + 16);
+       if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
+           pt.y >= (rcClient.bottom + rcClient.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);
+       //lbAutoComplete.SetPosition(rcList);
+       ac.Show();
+}
+
+void ScintillaBase::AutoCompleteCancel() {
+       ac.Cancel();
+}
+
+void ScintillaBase::AutoCompleteMove(int delta) {
+       ac.Move(delta);
+}
+
+void ScintillaBase::AutoCompleteChanged(char ch) {
+       if (currentPos <= ac.posStart) {
+               ac.Cancel();
+       } else if (ac.IsStopChar(ch)) {
+               ac.Cancel();
+       } else {
+               char wordCurrent[1000];
+               int i;
+               int startWord = ac.posStart - ac.startLen;
+               for (i = startWord; i < currentPos; i++)
+                       wordCurrent[i - startWord] = pdoc->CharAt(i);
+               wordCurrent[i - startWord] = '\0';
+               ac.Select(wordCurrent);
+       }
+}
+
+void ScintillaBase::AutoCompleteCompleted() {
+       int item = ac.lb.GetSelection();
+       char selected[200];
+       if (item != -1) {
+               ac.lb.GetValue(item, selected, sizeof(selected));
+       }
+       ac.Cancel();
+       if (currentPos != ac.posStart) {
+               pdoc->DeleteChars(ac.posStart, currentPos - ac.posStart);
+       }
+       SetEmptySelection(ac.posStart);
+       if (item != -1) {
+               pdoc->InsertString(currentPos, selected + ac.startLen);
+               SetEmptySelection(currentPos + strlen(selected + ac.startLen));
+       }
+}
+
+void ScintillaBase::ContextMenu(Point pt) {
+       popup.CreatePopUp();
+       AddToPopUp("Undo", idcmdUndo, pdoc->CanUndo());
+       AddToPopUp("Redo", idcmdRedo, pdoc->CanRedo());
+       AddToPopUp("");
+       AddToPopUp("Cut", idcmdCut, currentPos != anchor);
+       AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
+       AddToPopUp("Paste", idcmdPaste, WndProc(EM_CANPASTE, 0, 0));
+       AddToPopUp("Delete", idcmdDelete, currentPos != anchor);
+       AddToPopUp("");
+       AddToPopUp("Select All", idcmdSelectAll);
+       popup.Show(pt, wMain);
+}
+
+void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
+       AutoCompleteCancel();
+       ct.CallTipCancel();
+       Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
+}
+
+#ifdef SCI_LEXER
+void ScintillaBase::Colourise(int start, int end) {
+       int lengthDoc = Platform::SendScintilla(wMain.GetID(), SCI_GETLENGTH, 0, 0);
+       if (end == -1)
+               end = lengthDoc;
+       int len = end - start;
+
+       PropSet props;
+       
+       StylingContext styler(wMain.GetID(), props);
+
+       int styleStart = 0;
+       if (start > 0)
+               styleStart = styler.StyleAt(start - 1);
+
+       ColouriseDoc(pdoc->dbcsCodePage, start, len, styleStart, lexLanguage, keyWordLists, styler);
+       styler.Flush();
+}
+#endif
+
+void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) {
+#ifdef SCI_LEXER
+       if (lexLanguage != SCLEX_CONTAINER) {
+               int endStyled = Platform::SendScintilla(wMain.GetID(), SCI_GETENDSTYLED, 0, 0);
+               int lineEndStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEFROMCHAR, endStyled, 0);
+               endStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEINDEX, lineEndStyled, 0);
+               Colourise(endStyled, endStyleNeeded);
+               return;
+       }
+#endif
+       Editor::NotifyStyleNeeded(endStyleNeeded);
+}
+
+LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
+       switch (iMessage) {
+       case SCI_AUTOCSHOW:
+               AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
+               break;
+
+       case SCI_AUTOCCANCEL:
+               AutoCompleteCancel();
+               break;
+
+       case SCI_AUTOCACTIVE:
+               return ac.Active();
+
+       case SCI_AUTOCPOSSTART:
+               return ac.posStart;
+
+       case SCI_AUTOCCOMPLETE:
+               AutoCompleteCompleted();
+               break;
+
+       case SCI_AUTOCSTOPS:
+               ac.SetStopChars(reinterpret_cast<char *>(lParam));
+               break;
+
+       case SCI_CALLTIPSHOW: {
+                       AutoCompleteCancel();
+                       if (!ct.wCallTip.Created()) {
+                               PRectangle rc = ct.CallTipStart(currentPos, LocationFromPosition(wParam),
+                                                               reinterpret_cast<char *>(lParam),
+                                                               vs.styles[0].fontName, vs.styles[0].size);
+                               // 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, wDraw);
+                               ct.wCallTip.Show();
+                       }
+               }
+               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 = Colour(wParam);
+               InvalidateStyleRedraw();
+               break;
+               
+#ifdef SCI_LEXER
+       case SCI_SETLEXER:
+               lexLanguage = wParam;
+               break;
+               
+       case SCI_GETLEXER:
+               return lexLanguage;
+               
+       case SCI_COLOURISE:
+               Colourise(wParam, lParam);
+               break;
+               
+       case SCI_SETPROPERTY:
+               props.Set(reinterpret_cast<const char *>(wParam), 
+                       reinterpret_cast<const char *>(lParam));
+               break;
+               
+       case SCI_SETKEYWORDS:
+               if ((wParam >= 0) && (wParam < numWordLists)) {
+                       keyWordLists[wParam]->Clear();
+                       keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
+               }
+               break;
+#endif
+
+       default:
+               return Editor::WndProc(iMessage, wParam, lParam);
+       }
+       return 0l;
+}
diff --git a/src/stc/scintilla/src/ScintillaBase.h b/src/stc/scintilla/src/ScintillaBase.h
new file mode 100644 (file)
index 0000000..e9f8f28
--- /dev/null
@@ -0,0 +1,68 @@
+// Scintilla source code edit control
+// ScintillaBase.h - defines an enhanced subclass of Editor with calltips, autocomplete and context menu
+// Copyright 1998-2000 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
+
+class ScintillaBase : public Editor {
+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
+       };
+
+       Menu popup;
+       AutoComplete ac;
+
+       CallTip ct;
+
+#ifdef SCI_LEXER
+       int lexLanguage;
+       PropSet props;
+       enum {numWordLists=5};
+       WordList *keyWordLists[numWordLists];
+       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 AddChar(char ch);
+       void Command(int cmdId);
+       virtual int KeyCommand(UINT iMessage);
+       
+       void AutoCompleteStart(int lenEntered, const char *list);
+       void AutoCompleteCancel();
+       void AutoCompleteMove(int delta);
+       void AutoCompleteChanged(char ch=0);
+       void AutoCompleteCompleted();
+
+       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 NotifyStyleNeeded(int endStyleNeeded);
+public:
+       // Public so scintilla_send_message can use it
+       virtual LRESULT WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/Style.cxx b/src/stc/scintilla/src/Style.cxx
new file mode 100644 (file)
index 0000000..5631231
--- /dev/null
@@ -0,0 +1,63 @@
+// Scintilla source code edit control
+// Style.cxx - defines the font and colour style for a class of text
+// Copyright 1998-2000 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 "Style.h"
+
+Style::Style() {
+       Clear();
+}
+
+Style::~Style() {
+       font.Release();
+}
+
+Style &Style::operator=(const Style &source) {
+       if (this == &source)
+               return *this;
+       Clear();
+       fore.desired = source.fore.desired;
+       back.desired = source.back.desired;
+       bold = source.bold;
+       italic = source.italic;
+       size = source.size;
+       strcpy(fontName, source.fontName);
+       eolFilled = source.eolFilled;
+       return *this;
+}
+
+void Style::Clear(Colour fore_, Colour back_, int size_, const char *fontName_, 
+       bool bold_, bool italic_, bool eolFilled_) {
+       fore.desired = fore_;
+       back.desired = back_;
+       bold = bold_;
+       italic = italic_;
+       size = size_;
+       strcpy(fontName, fontName_);
+       eolFilled = eolFilled_;
+       font.Release();
+}
+
+void Style::Realise(Surface &surface, int zoomLevel) {
+       int sizeZoomed = size + zoomLevel;
+       if (sizeZoomed <= 2)    // Hangs if sizeZoomed <= 1
+               sizeZoomed = 2;
+               
+       int deviceHeight = (sizeZoomed * surface.LogPixelsY()) / 72;
+       font.Create(fontName, deviceHeight, bold, italic);
+
+       ascent = surface.Ascent(font);
+       descent = surface.Descent(font);
+       // Probably more typographically correct to include leading
+       // but that means more complex drawing as leading must be erased
+       //lineHeight = surface.ExternalLeading() + surface.Height();
+       externalLeading = surface.ExternalLeading(font);
+       lineHeight = surface.Height(font);
+       aveCharWidth = surface.AverageCharWidth(font);
+       spaceWidth = surface.WidthChar(font, ' ');
+}
diff --git a/src/stc/scintilla/src/Style.h b/src/stc/scintilla/src/Style.h
new file mode 100644 (file)
index 0000000..916b646
--- /dev/null
@@ -0,0 +1,37 @@
+// Scintilla source code edit control
+// Style.h - defines the font and colour style for a class of text
+// Copyright 1998-2000 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
+
+class Style {
+public:
+       ColourPair fore;
+       ColourPair back;
+       bool bold;
+       bool italic;
+       int size;
+       char fontName[100];
+       bool eolFilled;
+
+       Font font;
+       unsigned int lineHeight;
+       unsigned int ascent;
+       unsigned int descent;
+       unsigned int externalLeading;
+       unsigned int aveCharWidth;
+       unsigned int spaceWidth;
+
+       Style();
+       ~Style();
+       Style &operator=(const Style &source);
+       void Clear(Colour fore_=Colour(0,0,0), Colour back_=Colour(0xff,0xff,0xff),
+               int size_=Platform::DefaultFontSize(), 
+               const char *fontName_=Platform::DefaultFont(), 
+               bool bold_=false, bool italic_=false, bool eolFilled_=false);
+       void Realise(Surface &surface, int zoomLevel);
+};
+
+#endif
diff --git a/src/stc/scintilla/src/ViewStyle.cxx b/src/stc/scintilla/src/ViewStyle.cxx
new file mode 100644 (file)
index 0000000..001ecdb
--- /dev/null
@@ -0,0 +1,183 @@
+// Scintilla source code edit control
+// ViewStyle.cxx - store information on how the document is to be viewed
+// Copyright 1998-2000 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 "Indicator.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+
+MarginStyle::MarginStyle() : 
+       symbol(false), width(16), mask(0xffffffff), sensitive(false) {
+}
+
+ViewStyle::ViewStyle() {
+       Init();
+}
+
+ViewStyle::ViewStyle(const ViewStyle &source) {
+       Init();
+       for (int sty=0;sty<=STYLE_MAX;sty++) {
+               styles[sty] = source.styles[sty];
+       }
+       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;
+       selbar.desired = source.selbar.desired;
+       selbarlight.desired = source.selbarlight.desired;
+       caretcolour.desired = source.caretcolour.desired;
+       edgecolour.desired = source.edgecolour.desired;
+       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;
+       viewEOL = source.viewEOL;
+       showMarkedLines = source.showMarkedLines;               
+}
+
+ViewStyle::~ViewStyle() {
+}
+
+void ViewStyle::Init() {
+       indicators[0].style = INDIC_SQUIGGLE;
+       indicators[0].fore = Colour(0, 0x7f, 0);
+       indicators[1].style = INDIC_TT;
+       indicators[1].fore = Colour(0, 0, 0xff);
+       indicators[2].style = INDIC_PLAIN;
+       indicators[2].fore = Colour(0xff, 0, 0);
+
+       lineHeight = 1;
+       maxAscent = 1;
+       maxDescent = 1;
+       aveCharWidth = 8;
+       spaceWidth = 8;
+
+       selforeset = false;
+       selforeground.desired = Colour(0xff, 0, 0);
+       selbackset = true;
+       selbackground.desired = Colour(0xc0, 0xc0, 0xc0);
+       selbar.desired = Platform::Chrome();
+       selbarlight.desired = Platform::ChromeHighlight();
+       styles[STYLE_LINENUMBER].fore.desired = Colour(0, 0, 0);
+       styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+       //caretcolour.desired = Colour(0xff, 0, 0);
+       caretcolour.desired = Colour(0, 0, 0);
+       edgecolour.desired = Colour(0xc0, 0xc0, 0xc0);
+       
+       leftMarginWidth = 1;
+       rightMarginWidth = 1;
+       ms[0].symbol = false;
+       ms[0].width = 0;
+       ms[0].mask = 0;
+       ms[1].symbol = true;
+       ms[1].width = 16;
+       ms[1].mask = ~SC_MASK_FOLDERS;
+       ms[2].symbol = true;
+       ms[2].width = 14;       // Nice width for arrows
+       ms[2].mask = SC_MASK_FOLDERS;
+       ms[2].width = 0;        // Nice width for arrows
+       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].symbol;
+               if (ms[margin].width > 0)
+                       maskInLine &= ~ms[margin].mask;
+       }
+       zoomLevel = 0;
+       viewWhitespace = false;
+       viewEOL = false;
+       showMarkedLines = true;
+}
+
+void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
+       unsigned int i;
+       for (i=0;i<(sizeof(styles)/sizeof(styles[0]));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++) {
+               pal.WantFind(markers[i].fore, want);
+               pal.WantFind(markers[i].back, want);
+       }
+       pal.WantFind(selforeground, want);
+       pal.WantFind(selbackground, want);
+       pal.WantFind(selbar, want);
+       pal.WantFind(selbarlight, want);
+       pal.WantFind(caretcolour, want);
+       pal.WantFind(edgecolour, want);
+}
+
+void ViewStyle::Refresh(Surface &surface) {
+       selbar.desired = Platform::Chrome();
+       selbarlight.desired = Platform::ChromeHighlight();
+       maxAscent = 1;
+       maxDescent = 1;
+       for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
+               styles[i].Realise(surface, zoomLevel);
+               if (maxAscent < styles[i].ascent)
+                       maxAscent = styles[i].ascent;
+               if (maxDescent < styles[i].descent)
+                       maxDescent = styles[i].descent;
+       }
+       
+       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].symbol;
+               if (ms[margin].width > 0)
+                       maskInLine &= ~ms[margin].mask;
+       }
+}
+
+void ViewStyle::ResetDefaultStyle() {
+       styles[STYLE_DEFAULT].Clear();
+}
+
+void ViewStyle::ClearStyles() {
+       // Reset all styles to be like the default style
+       for (int i=0; i<=STYLE_MAX; i++) {
+               if (i != STYLE_DEFAULT) {
+                       styles[i].Clear(
+                               styles[STYLE_DEFAULT].fore.desired, 
+                               styles[STYLE_DEFAULT].back.desired, 
+                               styles[STYLE_DEFAULT].size, 
+                               styles[STYLE_DEFAULT].fontName, 
+                               styles[STYLE_DEFAULT].bold, 
+                               styles[STYLE_DEFAULT].italic);
+               }
+       }
+       styles[STYLE_LINENUMBER].back.desired = Platform::Chrome();
+}
+
diff --git a/src/stc/scintilla/src/ViewStyle.h b/src/stc/scintilla/src/ViewStyle.h
new file mode 100644 (file)
index 0000000..9448720
--- /dev/null
@@ -0,0 +1,59 @@
+// Scintilla source code edit control
+// ViewStyle.h - store information on how the document is to be viewed
+// Copyright 1998-2000 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
+
+class MarginStyle {
+public:
+       bool symbol;
+       int width;
+       int mask;
+       bool sensitive;
+       MarginStyle();
+};
+
+class ViewStyle {
+public:
+       Style styles[STYLE_MAX + 1];
+       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 selbar;
+       ColourPair selbarlight;
+       // Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
+       int leftMarginWidth;            // Spacing margin on left of text
+       int rightMarginWidth;   // Spacing margin on left of text
+       enum { margins=3 };
+       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;
+       bool viewWhitespace;
+       bool viewEOL;
+       bool showMarkedLines;
+       ColourPair caretcolour;
+       ColourPair edgecolour;
+       
+       ViewStyle();
+       ViewStyle(const ViewStyle &source);
+       ~ViewStyle();
+       void Init();
+       void RefreshColourPalette(Palette &pal, bool want);
+       void Refresh(Surface &surface);
+       void ResetDefaultStyle();
+       void ClearStyles();
+};
+
+#endif
diff --git a/src/stc/stc.cpp b/src/stc/stc.cpp
new file mode 100644 (file)
index 0000000..d4b02e8
--- /dev/null
@@ -0,0 +1,1386 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        stc.cpp
+// Purpose:     A wxWindows implementation of Scintilla.  This class is the
+//              one meant to be used directly by wx applications.  It does not
+//              derive directly from the Scintilla classes, but instead
+//              delegates most things to the real Scintilla class.
+//              This allows the use of Scintilla without polluting the
+//              namespace with all the classes and itentifiers from Scintilla.
+//
+// Author:      Robin Dunn
+//
+// Created:     13-Jan-2000
+// RCS-ID:      $Id$
+// Copyright:   (c) 2000 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/stc/stc.h"
+#include "ScintillaWX.h"
+
+#include <wx/tokenzr.h>
+
+//----------------------------------------------------------------------
+
+const wxChar* wxSTCNameStr = "stcwindow";
+
+BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl)
+    EVT_PAINT                   (wxStyledTextCtrl::OnPaint)
+    EVT_SCROLLWIN               (wxStyledTextCtrl::OnScrollWin)
+    EVT_SIZE                    (wxStyledTextCtrl::OnSize)
+    EVT_LEFT_DOWN               (wxStyledTextCtrl::OnMouseLeftDown)
+    EVT_MOTION                  (wxStyledTextCtrl::OnMouseMove)
+    EVT_LEFT_UP                 (wxStyledTextCtrl::OnMouseLeftUp)
+    EVT_RIGHT_UP                (wxStyledTextCtrl::OnMouseRightUp)
+    EVT_CHAR                    (wxStyledTextCtrl::OnChar)
+    EVT_KILL_FOCUS              (wxStyledTextCtrl::OnLoseFocus)
+    EVT_SET_FOCUS               (wxStyledTextCtrl::OnGainFocus)
+    EVT_SYS_COLOUR_CHANGED      (wxStyledTextCtrl::OnSysColourChanged)
+    EVT_ERASE_BACKGROUND        (wxStyledTextCtrl::OnEraseBackground)
+    EVT_MENU_RANGE              (-1, -1, wxStyledTextCtrl::OnMenu)
+END_EVENT_TABLE()
+
+//----------------------------------------------------------------------
+// Constructor and Destructor
+
+wxStyledTextCtrl::wxStyledTextCtrl(wxWindow *parent,
+                                   wxWindowID id,
+                                   const wxPoint& pos,
+                                   const wxSize& size,
+                                   long style,
+                                   const wxString& name) :
+    wxControl(parent, id, pos, size,
+              style | wxVSCROLL | wxHSCROLL | wxWANTS_CHARS,
+              wxDefaultValidator, name)
+{
+    m_swx = new ScintillaWX(this);
+    // m_keywords = new WordList;
+    m_stopWatch.Start();
+    m_readOnly = false;
+    m_undoType = wxSTC_UndoCollectAutoStart;
+}
+
+
+wxStyledTextCtrl::~wxStyledTextCtrl() {
+    delete m_swx;
+    // delete m_keywords;
+}
+
+
+//----------------------------------------------------------------------
+
+inline long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
+
+    return m_swx->WndProc(msg, wp, lp);
+}
+
+
+//----------------------------------------------------------------------
+// Text retrieval and modification
+
+wxString wxStyledTextCtrl::GetText() {
+    wxString text;
+    int   len  = GetTextLength();
+    char* buff = text.GetWriteBuf(len);
+
+    SendMsg(WM_GETTEXT, len, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+bool wxStyledTextCtrl::SetText(const wxString& text) {
+    return SendMsg(WM_SETTEXT, 0, (long)text.c_str()) != 0;
+}
+
+
+wxString wxStyledTextCtrl::GetLine(int line) {
+    wxString text;
+    int   len  = GetLineLength(line);
+    char* buff = text.GetWriteBuf(len+1);
+
+    *((WORD*)buff) = len+1;
+    SendMsg(EM_GETLINE, line, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::ReplaceSelection(const wxString& text) {
+    SendMsg(EM_REPLACESEL, 0, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::SetReadOnly(bool readOnly) {
+    SendMsg(EM_SETREADONLY, (long)readOnly);
+    m_readOnly = readOnly;
+}
+
+
+bool wxStyledTextCtrl::GetReadOnly() {
+    // TODO: need support in Scintilla to do this right,
+    //       until then we'll track it ourselves
+    return m_readOnly;
+}
+
+
+void wxStyledTextCtrl::GetTextRange(int startPos, int endPos, char* buff) {
+    TEXTRANGE tr;
+    tr.lpstrText = buff;
+    tr.chrg.cpMin = startPos;
+    tr.chrg.cpMax = endPos;
+    SendMsg(EM_GETTEXTRANGE, 0, (long)&tr);
+}
+
+
+wxString wxStyledTextCtrl::GetTextRange(int startPos, int endPos) {
+    wxString  text;
+    int       len  = endPos - startPos;
+    char*     buff = text.GetWriteBuf(len);
+    GetTextRange(startPos, endPos, buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::GetStyledTextRange(int startPos, int endPos, char* buff) {
+    TEXTRANGE tr;
+    tr.lpstrText = buff;
+    tr.chrg.cpMin = startPos;
+    tr.chrg.cpMax = endPos;
+    SendMsg(SCI_GETSTYLEDTEXT, 0, (long)&tr);
+}
+
+
+wxString wxStyledTextCtrl::GetStyledTextRange(int startPos, int endPos) {
+    wxString  text;
+    int       len  = endPos - startPos;
+    char*     buff = text.GetWriteBuf(len*2);
+    GetStyledTextRange(startPos, endPos, buff);
+    text.UngetWriteBuf(len*2);
+    return text;
+}
+
+
+void wxStyledTextCtrl::AddText(const wxString& text) {
+    SendMsg(SCI_ADDTEXT, text.Len(), (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::AddStyledText(const wxString& text) {
+    SendMsg(SCI_ADDSTYLEDTEXT, text.Len(), (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::InsertText(int pos, const wxString& text) {
+    SendMsg(SCI_INSERTTEXT, pos, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::ClearAll() {
+    SendMsg(SCI_CLEARALL);
+}
+
+
+char wxStyledTextCtrl::GetCharAt(int pos) {
+    return SendMsg(SCI_GETCHARAT, pos);
+}
+
+
+char wxStyledTextCtrl::GetStyleAt(int pos) {
+    return SendMsg(SCI_GETSTYLEAT, pos);
+}
+
+
+void wxStyledTextCtrl::SetStyleBits(int bits) {
+    SendMsg(SCI_SETSTYLEBITS, bits);
+}
+
+
+int  wxStyledTextCtrl::GetStyleBits() {
+    return SendMsg(SCI_GETSTYLEBITS);
+}
+
+
+//----------------------------------------------------------------------
+// Clipboard
+
+
+void wxStyledTextCtrl::Cut() {
+    SendMsg(WM_CUT);
+}
+
+
+void wxStyledTextCtrl::Copy() {
+    SendMsg(WM_COPY);
+}
+
+
+void wxStyledTextCtrl::Paste() {
+    SendMsg(WM_PASTE);
+}
+
+
+bool wxStyledTextCtrl::CanPaste() {
+    return SendMsg(EM_CANPASTE) != 0;
+}
+
+
+void wxStyledTextCtrl::ClearClipbrd() {
+    SendMsg(WM_CLEAR);
+}
+
+
+
+//----------------------------------------------------------------------
+// Undo and Redo
+
+void wxStyledTextCtrl::Undo() {
+    SendMsg(WM_UNDO);
+}
+
+
+bool wxStyledTextCtrl::CanUndo() {
+    return SendMsg(EM_CANUNDO) != 0;
+}
+
+
+void wxStyledTextCtrl::EmptyUndoBuffer() {
+    SendMsg(EM_EMPTYUNDOBUFFER);
+}
+
+
+void wxStyledTextCtrl::Redo() {
+    SendMsg(SCI_REDO);
+}
+
+
+bool wxStyledTextCtrl::CanRedo() {
+    return SendMsg(SCI_CANREDO) != 0;
+}
+
+
+void wxStyledTextCtrl::SetUndoCollection(wxSTC_UndoType type) {
+    SendMsg(SCI_SETUNDOCOLLECTION, type);
+    m_undoType = type;
+}
+
+
+wxSTC_UndoType wxStyledTextCtrl::GetUndoCollection() {
+    // TODO: need support in Scintilla to do this right,
+    //       until then we'll track it ourselves
+    return m_undoType;
+}
+
+
+void wxStyledTextCtrl::BeginUndoAction() {
+    SendMsg(SCI_BEGINUNDOACTION);
+}
+
+
+void wxStyledTextCtrl::EndUndoAction() {
+    SendMsg(SCI_ENDUNDOACTION);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Selection and information
+
+
+void wxStyledTextCtrl::GetSelection(int* startPos, int* endPos) {
+    SendMsg(EM_GETSEL, (long)startPos, (long)endPos);
+}
+
+
+void wxStyledTextCtrl::SetSelection(int  startPos, int  endPos) {
+    SendMsg(EM_SETSEL, startPos, endPos);
+}
+
+
+wxString wxStyledTextCtrl::GetSelectedText() {
+    wxString text;
+    int   start;
+    int   end;
+
+    GetSelection(&start, &end);
+    int   len  = end - start;
+    char* buff = text.GetWriteBuf(len);
+
+    SendMsg(EM_GETSELTEXT, 0, (long)buff);
+    text.UngetWriteBuf();
+    return text;
+}
+
+
+void wxStyledTextCtrl::HideSelection(bool hide) {
+    SendMsg(EM_HIDESELECTION, hide);
+}
+
+
+bool wxStyledTextCtrl::GetHideSelection() {
+    return m_swx->GetHideSelection();
+}
+
+
+int wxStyledTextCtrl::GetTextLength() {
+    return SendMsg(WM_GETTEXTLENGTH);
+}
+
+
+int wxStyledTextCtrl::GetFirstVisibleLine() {
+    return SendMsg(EM_GETFIRSTVISIBLELINE);
+}
+
+
+int wxStyledTextCtrl::GetLineCount() {
+    return SendMsg(EM_GETLINECOUNT);
+}
+
+
+bool wxStyledTextCtrl::GetModified() {
+    return SendMsg(EM_GETMODIFY) != 0;
+}
+
+
+wxRect wxStyledTextCtrl::GetRect() {
+    PRectangle pr;
+    SendMsg(EM_GETRECT, 0, (long)&pr);
+
+    wxRect rect = wxRectFromPRectangle(pr);
+    return rect;
+}
+
+
+int wxStyledTextCtrl::GetLineFromPos(int pos) {
+    return SendMsg(EM_LINEFROMCHAR, pos);
+}
+
+
+int wxStyledTextCtrl::GetLineStartPos(int line) {
+    return SendMsg(EM_LINEINDEX, line);
+}
+
+
+int wxStyledTextCtrl::GetLineLengthAtPos(int pos) {
+    return SendMsg(EM_LINELENGTH, pos);
+}
+
+
+int wxStyledTextCtrl::GetLineLength(int line) {
+    return SendMsg(SCI_LINELENGTH, line);
+}
+
+
+int wxStyledTextCtrl::GetCurrentLine() {
+    int line = GetLineFromPos(GetCurrentPos());
+    return line;
+}
+
+
+wxString wxStyledTextCtrl::GetCurrentLineText(int* linePos) {
+    wxString text;
+    int   len  = GetLineLength(GetCurrentLine());
+    char* buff = text.GetWriteBuf(len+1);
+
+    int pos = SendMsg(SCI_GETCURLINE, len+1, (long)buff);
+    text.UngetWriteBuf();
+
+    if (linePos)
+        *linePos = pos;
+
+    return text;
+}
+
+
+int wxStyledTextCtrl::PositionFromPoint(wxPoint pt) {
+    Point spt(pt.x, pt.y);
+    long rv = SendMsg(EM_CHARFROMPOS, 0, (long)&spt);
+    return LOWORD(rv);
+}
+
+
+int wxStyledTextCtrl::LineFromPoint(wxPoint pt) {
+    Point spt(pt.x, pt.y);
+    long rv = SendMsg(EM_CHARFROMPOS, 0, (long)&spt);
+    return HIWORD(rv);
+}
+
+
+wxPoint wxStyledTextCtrl::PointFromPosition(int pos) {
+    Point pt;
+    SendMsg(EM_POSFROMCHAR, pos, (long)&pt);
+    return wxPoint(pt.x, pt.y);
+}
+
+
+int wxStyledTextCtrl::GetCurrentPos() {
+    return SendMsg(SCI_GETCURRENTPOS);
+}
+
+
+int wxStyledTextCtrl::GetAnchor() {
+    return SendMsg(SCI_GETANCHOR);
+}
+
+
+void wxStyledTextCtrl::SelectAll() {
+    SendMsg(SCI_SELECTALL);
+}
+
+
+void wxStyledTextCtrl::SetCurrentPosition(int pos) {
+    SendMsg(SCI_GOTOPOS, pos);
+}
+
+
+void wxStyledTextCtrl::SetAnchor(int pos) {
+    SendMsg(SCI_SETANCHOR, pos);
+}
+
+
+void wxStyledTextCtrl::GotoPos(int pos) {
+    SendMsg(SCI_GOTOPOS, pos);
+}
+
+
+void wxStyledTextCtrl::GotoLine(int line) {
+    SendMsg(SCI_GOTOLINE, line);
+}
+
+
+void wxStyledTextCtrl::ChangePosition(int delta, bool extendSelection) {
+    // TODO:  Is documented but doesn't seem to be implemented
+    //SendMsg(SCI_CHANGEPOSITION, delta, extendSelection);
+}
+
+
+void wxStyledTextCtrl::PageMove(int cmdKey, bool extendSelection) {
+    // TODO:  Is documented but doesn't seem to be implemented
+    //SendMsg(SCI_PAGEMOVE, cmdKey, extendSelection);
+}
+
+
+void wxStyledTextCtrl::ScrollBy(int columnDelta, int lineDelta) {
+    SendMsg(EM_LINESCROLL, columnDelta, lineDelta);
+}
+
+void wxStyledTextCtrl::ScrollToLine(int line) {
+    m_swx->DoScrollToLine(line);
+}
+
+
+void wxStyledTextCtrl::ScrollToColumn(int column) {
+    m_swx->DoScrollToColumn(column);
+}
+
+
+void wxStyledTextCtrl::EnsureCaretVisible() {
+    SendMsg(EM_SCROLLCARET);
+}
+
+
+void wxStyledTextCtrl::SetCaretPolicy(int policy, int slop) {
+    SendMsg(SCI_SETCARETPOLICY, policy, slop);
+}
+
+
+int wxStyledTextCtrl::GetSelectionType() {
+    return SendMsg(EM_SELECTIONTYPE);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Searching
+
+int wxStyledTextCtrl::FindText(int minPos, int maxPos,
+                                     const wxString& text,
+                                     bool caseSensitive, bool wholeWord) {
+    FINDTEXTEX  ft;
+    int         flags = 0;
+
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+    ft.chrg.cpMin = minPos;
+    ft.chrg.cpMax = maxPos;
+    ft.lpstrText = (char*)text.c_str();
+
+    return SendMsg(EM_FINDTEXT, flags, (long)&ft);
+}
+
+
+void wxStyledTextCtrl::SearchAnchor() {
+    SendMsg(SCI_SEARCHANCHOR);
+}
+
+
+int wxStyledTextCtrl::SearchNext(const wxString& text, bool caseSensitive, bool wholeWord) {
+    int flags = 0;
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+
+    return SendMsg(SCI_SEARCHNEXT, flags, (long)text.c_str());
+}
+
+
+int wxStyledTextCtrl::SearchPrev(const wxString& text, bool caseSensitive, bool wholeWord) {
+    int flags = 0;
+    flags |= caseSensitive ? FR_MATCHCASE : 0;
+    flags |= wholeWord     ? FR_WHOLEWORD : 0;
+
+    return SendMsg(SCI_SEARCHPREV, flags, (long)text.c_str());
+}
+
+//----------------------------------------------------------------------
+// Visible whitespace
+
+
+bool wxStyledTextCtrl::GetViewWhitespace() {
+    return SendMsg(SCI_GETVIEWWS) != 0;
+}
+
+
+void wxStyledTextCtrl::SetViewWhitespace(bool visible) {
+    SendMsg(SCI_SETVIEWWS, visible);
+}
+
+
+
+//----------------------------------------------------------------------
+// Line endings
+
+wxSTC_EOL wxStyledTextCtrl::GetEOLMode() {
+    return (wxSTC_EOL)SendMsg(SCI_GETEOLMODE);
+}
+
+
+void wxStyledTextCtrl::SetEOLMode(wxSTC_EOL mode) {
+    SendMsg(SCI_SETEOLMODE, mode);
+}
+
+
+bool wxStyledTextCtrl::GetViewEOL() {
+    return SendMsg(SCI_GETVIEWEOL) != 0;
+}
+
+
+void wxStyledTextCtrl::SetViewEOL(bool visible) {
+    SendMsg(SCI_SETVIEWEOL, visible);
+}
+
+void wxStyledTextCtrl::ConvertEOL(wxSTC_EOL mode) {
+    SendMsg(SCI_CONVERTEOLS, mode);
+}
+
+//----------------------------------------------------------------------
+// Styling
+
+int wxStyledTextCtrl::GetEndStyled() {
+    return SendMsg(SCI_GETENDSTYLED);
+}
+
+
+void wxStyledTextCtrl::StartStyling(int pos, int mask) {
+    SendMsg(SCI_STARTSTYLING, pos, mask);
+}
+
+
+void wxStyledTextCtrl::SetStyleFor(int length, int style) {
+    SendMsg(SCI_SETSTYLING, length, style);
+}
+
+
+void wxStyledTextCtrl::SetStyleBytes(int length, char* styleBytes) {
+    SendMsg(SCI_SETSTYLINGEX, length, (long)styleBytes);
+}
+
+
+//----------------------------------------------------------------------
+// Style Definition
+
+
+static long wxColourAsLong(const wxColour& co) {
+    return (((long)co.Blue()  << 16) |
+            ((long)co.Green() <<  8) |
+            ((long)co.Red()));
+}
+
+static wxColour wxColourFromLong(long c) {
+    wxColour clr;
+    clr.Set(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
+    return clr;
+}
+
+
+static wxColour wxColourFromSpec(const wxString& spec) {
+    // spec should be #RRGGBB
+    char* junk;
+    int red   = strtol(spec.Mid(1,2), &junk, 16);
+    int green = strtol(spec.Mid(3,2), &junk, 16);
+    int blue  = strtol(spec.Mid(5,2), &junk, 16);
+    return wxColour(red, green, blue);
+}
+
+
+void wxStyledTextCtrl::StyleClearAll() {
+    SendMsg(SCI_STYLECLEARALL);
+}
+
+
+void wxStyledTextCtrl::StyleResetDefault() {
+    SendMsg(SCI_STYLERESETDEFAULT);
+}
+
+
+
+// Extract style settings from a spec-string which is composed of one or
+// more of the following comma separated elements:
+//
+//      bold                    turns on bold
+//      italic                  turns on italics
+//      fore:#RRGGBB            sets the foreground colour
+//      back:#RRGGBB            sets the background colour
+//      face:[facename]         sets the font face name to use
+//      size:[num]              sets the font size in points
+//      eol                     turns on eol filling
+//
+
+void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
+
+    wxStringTokenizer tkz(spec, ",");
+    while (tkz.HasMoreTokens()) {
+        wxString token = tkz.GetNextToken();
+
+        wxString option = token.BeforeFirst(':');
+        wxString val = token.AfterFirst(':');
+
+        if (option == "bold")
+            StyleSetBold(styleNum, true);
+
+        else if (option == "italic")
+            StyleSetItalic(styleNum, true);
+
+        else if (option == "eol")
+            StyleSetEOLFilled(styleNum, true);
+
+        else if (option == "size") {
+            long points;
+            if (val.ToLong(&points))
+                StyleSetSize(styleNum, points);
+        }
+
+        else if (option == "face")
+            StyleSetFaceName(styleNum, val);
+
+        else if (option == "fore")
+            StyleSetForeground(styleNum, wxColourFromSpec(val));
+
+        else if (option == "back")
+            StyleSetBackground(styleNum, wxColourFromSpec(val));
+    }
+}
+
+
+void wxStyledTextCtrl::StyleSetForeground(int styleNum, const wxColour& colour) {
+    SendMsg(SCI_STYLESETFORE, styleNum, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::StyleSetBackground(int styleNum, const wxColour& colour) {
+    SendMsg(SCI_STYLESETBACK, styleNum, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) {
+    int      size     = font.GetPointSize();
+    wxString faceName = font.GetFaceName();
+    bool     bold     = font.GetWeight() == wxBOLD;
+    bool     italic   = font.GetStyle() != wxNORMAL;
+
+    StyleSetFontAttr(styleNum, size, faceName, bold, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size,
+                                        const wxString& faceName,
+                                        bool bold, bool italic) {
+    StyleSetSize(styleNum, size);
+    StyleSetFaceName(styleNum, faceName);
+    StyleSetBold(styleNum, bold);
+    StyleSetItalic(styleNum, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetBold(int styleNum, bool bold) {
+    SendMsg(SCI_STYLESETBOLD, styleNum, bold);
+}
+
+
+void wxStyledTextCtrl::StyleSetItalic(int styleNum, bool italic) {
+    SendMsg(SCI_STYLESETITALIC, styleNum, italic);
+}
+
+
+void wxStyledTextCtrl::StyleSetFaceName(int styleNum, const wxString& faceName) {
+    SendMsg(SCI_STYLESETFONT, styleNum, (long)faceName.c_str());
+}
+
+
+void wxStyledTextCtrl::StyleSetSize(int styleNum, int pointSize) {
+    SendMsg(SCI_STYLESETSIZE, styleNum, pointSize);
+}
+
+
+void wxStyledTextCtrl::StyleSetEOLFilled(int styleNum, bool fillEOL) {
+    SendMsg(SCI_STYLESETEOLFILLED, styleNum, fillEOL);
+}
+
+
+//----------------------------------------------------------------------
+// Margins in the edit area
+
+int wxStyledTextCtrl::GetLeftMargin() {
+    return LOWORD(SendMsg(EM_GETMARGINS));
+}
+
+
+int wxStyledTextCtrl::GetRightMargin() {
+    return HIWORD(SendMsg(EM_GETMARGINS));
+}
+
+
+void wxStyledTextCtrl::SetMargins(int left, int right) {
+    int flag = 0;
+    int val = 0;
+
+    if (right != -1) {
+        flag |= EC_RIGHTMARGIN;
+        val = right << 16;
+    }
+    if (left != -1) {
+        flag |= EC_LEFTMARGIN;
+        val |= (left & 0xffff);
+    }
+
+    SendMsg(EM_SETMARGINS, flag, val);
+}
+
+
+//----------------------------------------------------------------------
+// Margins for selection, markers, etc.
+
+void wxStyledTextCtrl::SetMarginType(int margin, int type) {
+    SendMsg(SCI_SETMARGINTYPEN, margin, type);
+}
+
+
+int  wxStyledTextCtrl::GetMarginType(int margin) {
+    return SendMsg(SCI_GETMARGINTYPEN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginWidth(int margin, int pixelWidth) {
+    SendMsg(SCI_SETMARGINWIDTHN, margin, pixelWidth);
+}
+
+
+int  wxStyledTextCtrl::GetMarginWidth(int margin) {
+    return SendMsg(SCI_GETMARGINWIDTHN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginMask(int margin, int mask) {
+    SendMsg(SCI_SETMARGINMASKN, margin, mask);
+}
+
+
+int  wxStyledTextCtrl::GetMarginMask(int margin) {
+    return SendMsg(SCI_GETMARGINMASKN, margin);
+}
+
+
+void wxStyledTextCtrl::SetMarginSensitive(int margin, bool sensitive) {
+    SendMsg(SCI_SETMARGINSENSITIVEN, margin, sensitive);
+}
+
+
+bool wxStyledTextCtrl::GetMarginSensitive(int margin) {
+    return SendMsg(SCI_GETMARGINSENSITIVEN, margin);
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Selection and Caret styles
+
+
+void wxStyledTextCtrl::SetSelectionForeground(const wxColour& colour) {
+    SendMsg(SCI_SETSELFORE, 0, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::SetSelectionBackground(const wxColour& colour) {
+    SendMsg(SCI_SETSELBACK, 0, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::SetCaretForeground(const wxColour& colour) {
+    SendMsg(SCI_SETCARETFORE, 0, wxColourAsLong(colour));
+}
+
+
+int wxStyledTextCtrl::GetCaretPeriod() {
+    return SendMsg(SCI_GETCARETPERIOD);
+}
+
+
+void wxStyledTextCtrl::SetCaretPeriod(int milliseconds) {
+    SendMsg(SCI_SETCARETPERIOD, milliseconds);
+}
+
+
+
+//----------------------------------------------------------------------
+// Other settings
+
+
+void wxStyledTextCtrl::SetBufferedDraw(bool isBuffered) {
+    SendMsg(SCI_SETBUFFEREDDRAW, isBuffered);
+}
+
+
+void wxStyledTextCtrl::SetTabWidth(int numChars) {
+    SendMsg(SCI_SETTABWIDTH, numChars);
+}
+
+
+void wxStyledTextCtrl::SetWordChars(const wxString& wordChars) {
+    SendMsg(SCI_SETTABWIDTH, 0, (long)wordChars.c_str());
+}
+
+
+//----------------------------------------------------------------------
+// Brace highlighting
+
+
+void wxStyledTextCtrl::BraceHighlight(int pos1, int pos2) {
+    SendMsg(SCI_BRACEHIGHLIGHT, pos1, pos2);
+}
+
+
+void wxStyledTextCtrl::BraceBadlight(int pos) {
+    SendMsg(SCI_BRACEBADLIGHT, pos);
+}
+
+
+int wxStyledTextCtrl::BraceMatch(int pos, int maxReStyle) {
+    return SendMsg(SCI_BRACEMATCH, pos, maxReStyle);
+}
+
+
+
+//----------------------------------------------------------------------
+// Markers
+
+void wxStyledTextCtrl::MarkerDefine(int markerNumber, int markerSymbol,
+                                          const wxColour& foreground,
+                                          const wxColour& background) {
+    MarkerSetType(markerNumber, markerSymbol);
+    MarkerSetForeground(markerNumber, foreground);
+    MarkerSetBackground(markerNumber, background);
+}
+
+
+void wxStyledTextCtrl::MarkerSetType(int markerNumber, int markerSymbol) {
+    SendMsg(SCI_MARKERDEFINE, markerNumber, markerSymbol);
+}
+
+
+void wxStyledTextCtrl::MarkerSetForeground(int markerNumber, const wxColour& colour) {
+    SendMsg(SCI_MARKERSETFORE, markerNumber, wxColourAsLong(colour));
+}
+
+
+void wxStyledTextCtrl::MarkerSetBackground(int markerNumber, const wxColour& colour) {
+    SendMsg(SCI_MARKERSETBACK, markerNumber, wxColourAsLong(colour));
+}
+
+
+int wxStyledTextCtrl::MarkerAdd(int line, int markerNumber) {
+    return SendMsg(SCI_MARKERADD, line, markerNumber);
+}
+
+
+void wxStyledTextCtrl::MarkerDelete(int line, int markerNumber) {
+    SendMsg(SCI_MARKERDELETE, line, markerNumber);
+}
+
+
+void wxStyledTextCtrl::MarkerDeleteAll(int markerNumber) {
+    SendMsg(SCI_MARKERDELETEALL, markerNumber);
+}
+
+
+int wxStyledTextCtrl::MarkerGet(int line) {
+    return SendMsg(SCI_MARKERGET);
+}
+
+
+int wxStyledTextCtrl::MarkerGetNextLine(int lineStart, int markerMask) {
+    return SendMsg(SCI_MARKERNEXT, lineStart, markerMask);
+}
+
+
+int wxStyledTextCtrl::MarkerGetPrevLine(int lineStart, int markerMask) {
+//    return SendMsg(SCI_MARKERPREV, lineStart, markerMask);
+    return 0;
+}
+
+
+int wxStyledTextCtrl::MarkerLineFromHandle(int handle) {
+    return SendMsg(SCI_MARKERLINEFROMHANDLE, handle);
+}
+
+
+void wxStyledTextCtrl::MarkerDeleteHandle(int handle) {
+    SendMsg(SCI_MARKERDELETEHANDLE, handle);
+}
+
+
+
+//----------------------------------------------------------------------
+// Indicators
+
+
+void wxStyledTextCtrl::IndicatorSetStyle(int indicNum, int indicStyle) {
+    SendMsg(SCI_INDICSETSTYLE, indicNum, indicStyle);
+}
+
+
+int wxStyledTextCtrl::IndicatorGetStyle(int indicNum) {
+    return SendMsg(SCI_INDICGETSTYLE, indicNum);
+}
+
+
+void wxStyledTextCtrl::IndicatorSetColour(int indicNum, const wxColour& colour) {
+    SendMsg(SCI_INDICSETSTYLE, indicNum, wxColourAsLong(colour));
+}
+
+
+
+//----------------------------------------------------------------------
+// Auto completion
+
+
+void wxStyledTextCtrl::AutoCompShow(const wxString& listOfWords) {
+    SendMsg(SCI_AUTOCSHOW, 0, (long)listOfWords.c_str());
+}
+
+
+void wxStyledTextCtrl::AutoCompCancel() {
+    SendMsg(SCI_AUTOCCANCEL);
+}
+
+
+bool wxStyledTextCtrl::AutoCompActive() {
+    return SendMsg(SCI_AUTOCACTIVE) != 0;
+}
+
+
+int wxStyledTextCtrl::AutoCompPosAtStart() {
+    return SendMsg(SCI_AUTOCPOSSTART);
+}
+
+
+void wxStyledTextCtrl::AutoCompComplete() {
+    SendMsg(SCI_AUTOCCOMPLETE);
+}
+
+
+void wxStyledTextCtrl::AutoCompStopChars(const wxString& stopChars) {
+    SendMsg(SCI_AUTOCSHOW, 0, (long)stopChars.c_str());
+}
+
+
+//----------------------------------------------------------------------
+// Call tips
+
+void wxStyledTextCtrl::CallTipShow(int pos, const wxString& text) {
+    SendMsg(SCI_CALLTIPSHOW, pos, (long)text.c_str());
+}
+
+
+void wxStyledTextCtrl::CallTipCancel() {
+    SendMsg(SCI_CALLTIPCANCEL);
+}
+
+
+bool wxStyledTextCtrl::CallTipActive() {
+    return SendMsg(SCI_CALLTIPACTIVE) != 0;
+}
+
+
+int wxStyledTextCtrl::CallTipPosAtStart() {
+    return SendMsg(SCI_CALLTIPPOSSTART);
+}
+
+
+void wxStyledTextCtrl::CallTipSetHighlight(int start, int end) {
+    SendMsg(SCI_CALLTIPSETHLT, start, end);
+}
+
+
+void wxStyledTextCtrl::CallTipSetBackground(const wxColour& colour) {
+    SendMsg(SCI_CALLTIPSETBACK, wxColourAsLong(colour));
+}
+
+
+//----------------------------------------------------------------------
+// Key bindings
+
+void wxStyledTextCtrl::CmdKeyAssign(int key, int modifiers, int cmd) {
+    SendMsg(SCI_ASSIGNCMDKEY, MAKELONG(key, modifiers), cmd);
+}
+
+
+void wxStyledTextCtrl::CmdKeyClear(int key, int modifiers) {
+    SendMsg(SCI_CLEARCMDKEY, MAKELONG(key, modifiers));
+}
+
+
+void wxStyledTextCtrl::CmdKeyClearAll() {
+    SendMsg(SCI_CLEARALLCMDKEYS);
+}
+
+
+void wxStyledTextCtrl::CmdKeyExecute(int cmd) {
+    SendMsg(cmd);
+}
+
+
+
+//----------------------------------------------------------------------
+// Print formatting
+
+int
+wxStyledTextCtrl::FormatRange(bool   doDraw,
+                                    int    startPos,
+                                    int    endPos,
+                                    wxDC*  draw,
+                                    wxDC*  target,  // Why does it use two? Can they be the same?
+                                    wxRect renderRect,
+                                    wxRect pageRect) {
+    FORMATRANGE fr;
+
+    fr.hdc = draw;
+    fr.hdcTarget = target;
+    fr.rc.top = renderRect.GetTop();
+    fr.rc.left = renderRect.GetLeft();
+    fr.rc.right = renderRect.GetRight();
+    fr.rc.bottom = renderRect.GetBottom();
+    fr.rcPage.top = pageRect.GetTop();
+    fr.rcPage.left = pageRect.GetLeft();
+    fr.rcPage.right = pageRect.GetRight();
+    fr.rcPage.bottom = pageRect.GetBottom();
+    fr.chrg.cpMin = startPos;
+    fr.chrg.cpMax = endPos;
+
+    return SendMsg(EM_FORMATRANGE, doDraw, (long)&fr);
+}
+
+
+//----------------------------------------------------------------------
+// Document Sharing
+
+void* wxStyledTextCtrl::GetDocument() {
+    return (void*)SendMsg(SCI_GETDOCPOINTER);
+}
+
+
+void wxStyledTextCtrl::SetDocument(void* document) {
+    SendMsg(SCI_SETDOCPOINTER, 0, (long)document);
+}
+
+
+//----------------------------------------------------------------------
+// Long Lines
+
+int wxStyledTextCtrl::GetEdgeColumn() {
+    return SendMsg(SCI_GETEDGECOLUMN);
+}
+
+void wxStyledTextCtrl::SetEdgeColumn(int column) {
+    SendMsg(SCI_SETEDGECOLUMN, column);
+}
+
+wxSTC_EDGE wxStyledTextCtrl::GetEdgeMode() {
+    return (wxSTC_EDGE) SendMsg(SCI_GETEDGEMODE);
+}
+
+void wxStyledTextCtrl::SetEdgeMode(wxSTC_EDGE mode){
+    SendMsg(SCI_SETEDGEMODE, mode);
+}
+
+wxColour wxStyledTextCtrl::GetEdgeColour() {
+    long c = SendMsg(SCI_GETEDGECOLOUR);
+    return wxColourFromLong(c);
+}
+
+void wxStyledTextCtrl::SetEdgeColour(const wxColour& colour) {
+    SendMsg(SCI_SETEDGECOLOUR, wxColourAsLong(colour));
+}
+
+
+//----------------------------------------------------------------------
+// Lexer
+
+void     wxStyledTextCtrl::SetLexer(wxSTC_LEX lexer) {
+    SendMsg(SCI_SETLEXER, lexer);
+}
+
+
+wxSTC_LEX wxStyledTextCtrl::GetLexer() {
+    return (wxSTC_LEX)SendMsg(SCI_GETLEXER);
+}
+
+
+void     wxStyledTextCtrl::Colourise(int start, int end) {
+    SendMsg(SCI_COLOURISE, start, end);
+}
+
+
+void     wxStyledTextCtrl::SetProperty(const wxString& key, const wxString& value) {
+    SendMsg(SCI_SETPROPERTY, (long)key.c_str(), (long)value.c_str());
+}
+
+
+void     wxStyledTextCtrl::SetKeywords(int keywordSet, const wxString& keywordList) {
+    SendMsg(SCI_SETKEYWORDS, keywordSet, (long)keywordList.c_str());
+}
+
+
+
+//----------------------------------------------------------------------
+// Event handlers
+
+void wxStyledTextCtrl::OnPaint(wxPaintEvent& evt) {
+    wxPaintDC dc(this);
+    wxRegion  region = GetUpdateRegion();
+
+    m_swx->DoPaint(&dc, region.GetBox());
+}
+
+void wxStyledTextCtrl::OnScrollWin(wxScrollWinEvent& evt) {
+    if (evt.GetOrientation() == wxHORIZONTAL)
+        m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
+    else
+        m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
+}
+
+void wxStyledTextCtrl::OnSize(wxSizeEvent& evt) {
+    wxSize sz = GetClientSize();
+    m_swx->DoSize(sz.x, sz.y);
+}
+
+void wxStyledTextCtrl::OnMouseLeftDown(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonDown(Point(pt.x, pt.y), m_stopWatch.Time(),
+                      evt.ShiftDown(), evt.ControlDown(), evt.AltDown());
+}
+
+void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonMove(Point(pt.x, pt.y));
+}
+
+void wxStyledTextCtrl::OnMouseLeftUp(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoButtonUp(Point(pt.x, pt.y), m_stopWatch.Time(),
+                      evt.ControlDown());
+}
+
+
+void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) {
+    wxPoint pt = evt.GetPosition();
+    m_swx->DoContextMenu(Point(pt.x, pt.y));
+}
+
+void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) {
+    int  processed = 0;
+    long key = evt.KeyCode();
+    if ((key > WXK_ESCAPE) &&
+        (key != WXK_DELETE) && (key < 255) &&
+        !evt.ControlDown() && !evt.AltDown()) {
+
+        m_swx->DoAddChar(key);
+        processed = true;
+    }
+    else {
+        key = toupper(key);
+        processed = m_swx->DoKeyDown(key, evt.ShiftDown(),
+                                     evt.ControlDown(), evt.AltDown());
+    }
+    if (! processed)
+        evt.Skip();
+}
+
+void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) {
+    m_swx->DoLoseFocus();
+}
+
+void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) {
+    m_swx->DoGainFocus();
+}
+
+void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& evt) {
+    m_swx->DoSysColourChange();
+}
+
+void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& evt) {
+    // do nothing to help avoid flashing
+}
+
+
+
+void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
+    m_swx->DoCommand(evt.GetId());
+}
+
+
+//----------------------------------------------------------------------
+// Turn notifications from Scintilla into events
+
+void wxStyledTextCtrl::NotifyChange() {
+    wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
+    GetEventHandler()->ProcessEvent(evt);
+}
+
+void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
+    SCNotification& scn = *_scn;
+    int eventType = 0;
+    switch (scn.nmhdr.code) {
+    case SCN_STYLENEEDED:
+        eventType = wxEVT_STC_STYLENEEDED;
+        break;
+    case SCN_CHARADDED:
+        eventType = wxEVT_STC_CHARADDED;
+        break;
+    case SCN_UPDATEUI:
+        eventType = wxEVT_STC_UPDATEUI;
+        break;
+    case SCN_SAVEPOINTREACHED:
+        eventType = wxEVT_STC_SAVEPOINTREACHED;
+        break;
+    case SCN_SAVEPOINTLEFT:
+        eventType = wxEVT_STC_SAVEPOINTLEFT;
+        break;
+    case SCN_MODIFYATTEMPTRO:
+        eventType = wxEVT_STC_ROMODIFYATTEMPT;
+        break;
+    case SCN_DOUBLECLICK:
+        eventType = wxEVT_STC_DOUBLECLICK;
+        break;
+    case SCN_MODIFIED:
+        eventType = wxEVT_STC_MODIFIED;
+        break;
+    case SCN_KEY:
+        eventType = wxEVT_STC_KEY;
+        break;
+    case SCN_MACRORECORD:
+        eventType = wxEVT_STC_MACRORECORD;
+        break;
+    case SCN_MARGINCLICK:
+        eventType = wxEVT_STC_MARGINCLICK;
+        break;
+    case SCN_NEEDSHOWN:
+        eventType = wxEVT_STC_NEEDSHOWN;
+        break;
+    }
+    if (eventType) {
+        wxStyledTextEvent evt(eventType, GetId());
+        evt.SetPosition(scn.position);
+        evt.SetKey(scn.ch);
+        evt.SetModifiers(scn.modifiers);
+        if (eventType == wxEVT_STC_MODIFIED) {
+            evt.SetModificationType(scn.modificationType);
+            evt.SetText(scn.text);
+            evt.SetLength(scn.length);
+            evt.SetLinesAdded(scn.linesAdded);
+            evt.SetLine(scn.line);
+            evt.SetFoldLevelNow(scn.foldLevelNow);
+            evt.SetFoldLevelPrev(scn.foldLevelPrev);
+        }
+        if (eventType == wxEVT_STC_MARGINCLICK)
+            evt.SetMargin(scn.margin);
+        if (eventType == wxEVT_STC_MACRORECORD) {
+            evt.SetMessage(scn.message);
+            evt.SetWParam(scn.wParam);
+            evt.SetLParam(scn.lParam);
+        }
+
+        GetEventHandler()->ProcessEvent(evt);
+    }
+}
+
+
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+
+wxStyledTextEvent::wxStyledTextEvent(wxEventType commandType, int id)
+    : wxCommandEvent(commandType, id)
+{
+    m_position = 0;
+    m_key = 0;
+    m_modifiers = 0;
+    m_modificationType = 0;
+    m_length = 0;
+    m_linesAdded = 0;
+    m_line = 0;
+    m_foldLevelNow = 0;
+    m_foldLevelPrev = 0;
+    m_margin = 0;
+    m_message = 0;
+    m_wParam = 0;
+    m_lParam = 0;
+
+
+}
+
+bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; }
+bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; }
+bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; }
+
+void wxStyledTextEvent::CopyObject(wxObject& obj) const {
+    wxCommandEvent::CopyObject(obj);
+
+    wxStyledTextEvent* o = (wxStyledTextEvent*)&obj;
+    o->m_position =      m_position;
+    o->m_key =           m_key;
+    o->m_modifiers =     m_modifiers;
+    o->m_modificationType = m_modificationType;
+    o->m_text =          m_text;
+    o->m_length =        m_length;
+    o->m_linesAdded =    m_linesAdded;
+    o->m_line =          m_line;
+    o->m_foldLevelNow =  m_foldLevelNow;
+    o->m_foldLevelPrev = m_foldLevelPrev;
+
+    o->m_margin =        m_margin;
+
+    o->m_message =       m_message;
+    o->m_wParam =        m_wParam;
+    o->m_lParam =        m_lParam;
+
+
+
+}
+
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+