From 1a2fb4cd61069956c046e9721fda447ba1a743d7 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Mon, 18 Mar 2002 22:31:01 +0000 Subject: [PATCH] Updated wxSTC from Scintilla 1.40 to Scintilla 1.45 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14676 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- contrib/include/wx/stc/stc.h | 134 +- contrib/src/stc/Makefile.in | 5 +- contrib/src/stc/PlatWX.cpp | 431 +++- contrib/src/stc/PlatWX.h | 8 + contrib/src/stc/ScintillaWX.cpp | 41 +- contrib/src/stc/ScintillaWX.h | 5 + contrib/src/stc/StcVC.dsp | 26 +- contrib/src/stc/gen_iface.py | 4 +- contrib/src/stc/makefile.b32 | 5 +- contrib/src/stc/makefile.g95 | 5 +- contrib/src/stc/makefile.vc | 5 +- contrib/src/stc/scintilla/README.txt | 2 +- contrib/src/stc/scintilla/include/KeyWords.h | 16 +- contrib/src/stc/scintilla/include/Platform.h | 350 ++- contrib/src/stc/scintilla/include/PropSet.h | 7 +- contrib/src/stc/scintilla/include/SString.h | 293 ++- contrib/src/stc/scintilla/include/SciLexer.h | 41 +- contrib/src/stc/scintilla/include/Scintilla.h | 56 +- .../src/stc/scintilla/include/Scintilla.iface | 149 +- .../src/stc/scintilla/src/AutoComplete.cxx | 5 +- contrib/src/stc/scintilla/src/AutoComplete.h | 3 +- contrib/src/stc/scintilla/src/CallTip.cxx | 39 +- contrib/src/stc/scintilla/src/CallTip.h | 3 +- .../stc/scintilla/src/ContractionState.cxx | 104 +- .../src/stc/scintilla/src/ContractionState.h | 28 +- contrib/src/stc/scintilla/src/Document.cxx | 150 +- contrib/src/stc/scintilla/src/Document.h | 22 +- .../stc/scintilla/src/DocumentAccessor.cxx | 13 +- .../src/stc/scintilla/src/DocumentAccessor.h | 4 +- contrib/src/stc/scintilla/src/Editor.cxx | 1879 +++++++++++------ contrib/src/stc/scintilla/src/Editor.h | 191 +- contrib/src/stc/scintilla/src/Indicator.h | 2 +- contrib/src/stc/scintilla/src/KeyMap.cxx | 2 +- contrib/src/stc/scintilla/src/KeyMap.h | 2 +- contrib/src/stc/scintilla/src/KeyWords.cxx | 34 +- contrib/src/stc/scintilla/src/LexAVE.cxx | 2 +- contrib/src/stc/scintilla/src/LexAda.cxx | 2 +- contrib/src/stc/scintilla/src/LexBaan.cxx | 189 ++ contrib/src/stc/scintilla/src/LexBullant.cxx | 233 ++ contrib/src/stc/scintilla/src/LexCPP.cxx | 26 +- contrib/src/stc/scintilla/src/LexConf.cxx | 1 + contrib/src/stc/scintilla/src/LexCrontab.cxx | 1 + contrib/src/stc/scintilla/src/LexEiffel.cxx | 6 +- contrib/src/stc/scintilla/src/LexHTML.cxx | 368 +++- contrib/src/stc/scintilla/src/LexLisp.cxx | 4 +- contrib/src/stc/scintilla/src/LexLua.cxx | 336 ++- contrib/src/stc/scintilla/src/LexMatlab.cxx | 168 ++ contrib/src/stc/scintilla/src/LexOthers.cxx | 143 +- contrib/src/stc/scintilla/src/LexPascal.cxx | 3 +- contrib/src/stc/scintilla/src/LexPerl.cxx | 2 +- contrib/src/stc/scintilla/src/LexPython.cxx | 96 +- contrib/src/stc/scintilla/src/LexRuby.cxx | 6 +- contrib/src/stc/scintilla/src/LexSQL.cxx | 4 +- contrib/src/stc/scintilla/src/LexVB.cxx | 238 ++- contrib/src/stc/scintilla/src/LineMarker.cxx | 10 +- contrib/src/stc/scintilla/src/LineMarker.h | 4 +- contrib/src/stc/scintilla/src/PropSet.cxx | 86 +- contrib/src/stc/scintilla/src/RESearch.cxx | 4 +- .../src/stc/scintilla/src/ScintillaBase.cxx | 67 +- contrib/src/stc/scintilla/src/ScintillaBase.h | 19 +- contrib/src/stc/scintilla/src/Style.cxx | 23 +- contrib/src/stc/scintilla/src/Style.h | 7 +- contrib/src/stc/scintilla/src/StyleContext.h | 52 +- .../src/stc/scintilla/src/UniConversion.cxx | 4 - contrib/src/stc/scintilla/src/ViewStyle.cxx | 25 +- .../src/stc/scintilla/src/WindowAccessor.cxx | 10 +- contrib/src/stc/stc.cpp | 140 +- contrib/src/stc/stc.cpp.in | 56 +- contrib/src/stc/stc.h.in | 14 - include/wx/stc/stc.h | 134 +- src/stc/Makefile.in | 5 +- src/stc/PlatWX.cpp | 431 +++- src/stc/PlatWX.h | 8 + src/stc/ScintillaWX.cpp | 41 +- src/stc/ScintillaWX.h | 5 + src/stc/StcVC.dsp | 26 +- src/stc/gen_iface.py | 4 +- src/stc/makefile.b32 | 5 +- src/stc/makefile.g95 | 5 +- src/stc/makefile.vc | 5 +- src/stc/scintilla/README.txt | 2 +- src/stc/scintilla/include/KeyWords.h | 16 +- src/stc/scintilla/include/Platform.h | 350 ++- src/stc/scintilla/include/PropSet.h | 7 +- src/stc/scintilla/include/SString.h | 293 ++- src/stc/scintilla/include/SciLexer.h | 41 +- src/stc/scintilla/include/Scintilla.h | 56 +- src/stc/scintilla/include/Scintilla.iface | 149 +- src/stc/scintilla/src/AutoComplete.cxx | 5 +- src/stc/scintilla/src/AutoComplete.h | 3 +- src/stc/scintilla/src/CallTip.cxx | 39 +- src/stc/scintilla/src/CallTip.h | 3 +- src/stc/scintilla/src/ContractionState.cxx | 104 +- src/stc/scintilla/src/ContractionState.h | 28 +- src/stc/scintilla/src/Document.cxx | 150 +- src/stc/scintilla/src/Document.h | 22 +- src/stc/scintilla/src/DocumentAccessor.cxx | 13 +- src/stc/scintilla/src/DocumentAccessor.h | 4 +- src/stc/scintilla/src/Editor.cxx | 1879 +++++++++++------ src/stc/scintilla/src/Editor.h | 191 +- src/stc/scintilla/src/Indicator.h | 2 +- src/stc/scintilla/src/KeyMap.cxx | 2 +- src/stc/scintilla/src/KeyMap.h | 2 +- src/stc/scintilla/src/KeyWords.cxx | 34 +- src/stc/scintilla/src/LexAVE.cxx | 2 +- src/stc/scintilla/src/LexAda.cxx | 2 +- src/stc/scintilla/src/LexBaan.cxx | 189 ++ src/stc/scintilla/src/LexBullant.cxx | 233 ++ src/stc/scintilla/src/LexCPP.cxx | 26 +- src/stc/scintilla/src/LexConf.cxx | 1 + src/stc/scintilla/src/LexCrontab.cxx | 1 + src/stc/scintilla/src/LexEiffel.cxx | 6 +- src/stc/scintilla/src/LexHTML.cxx | 368 +++- src/stc/scintilla/src/LexLisp.cxx | 4 +- src/stc/scintilla/src/LexLua.cxx | 336 ++- src/stc/scintilla/src/LexMatlab.cxx | 168 ++ src/stc/scintilla/src/LexOthers.cxx | 143 +- src/stc/scintilla/src/LexPascal.cxx | 3 +- src/stc/scintilla/src/LexPerl.cxx | 2 +- src/stc/scintilla/src/LexPython.cxx | 96 +- src/stc/scintilla/src/LexRuby.cxx | 6 +- src/stc/scintilla/src/LexSQL.cxx | 4 +- src/stc/scintilla/src/LexVB.cxx | 238 ++- src/stc/scintilla/src/LineMarker.cxx | 10 +- src/stc/scintilla/src/LineMarker.h | 4 +- src/stc/scintilla/src/PropSet.cxx | 86 +- src/stc/scintilla/src/RESearch.cxx | 4 +- src/stc/scintilla/src/ScintillaBase.cxx | 67 +- src/stc/scintilla/src/ScintillaBase.h | 19 +- src/stc/scintilla/src/Style.cxx | 23 +- src/stc/scintilla/src/Style.h | 7 +- src/stc/scintilla/src/StyleContext.h | 52 +- src/stc/scintilla/src/UniConversion.cxx | 4 - src/stc/scintilla/src/ViewStyle.cxx | 25 +- src/stc/scintilla/src/WindowAccessor.cxx | 10 +- src/stc/stc.cpp | 140 +- src/stc/stc.cpp.in | 56 +- src/stc/stc.h.in | 14 - wxPython/CHANGES.txt | 2 + wxPython/contrib/stc/msw/stc_.cpp | 488 ++++- wxPython/contrib/stc/msw/stc_.py | 91 +- wxPython/demo/data/stc.h.html | 145 +- wxPython/demo/wxStyledTextCtrl_2.py | 22 +- wxPython/setup.py | 4 + 144 files changed, 9487 insertions(+), 4091 deletions(-) create mode 100644 contrib/src/stc/PlatWX.h create mode 100644 contrib/src/stc/scintilla/src/LexBaan.cxx create mode 100644 contrib/src/stc/scintilla/src/LexBullant.cxx create mode 100644 contrib/src/stc/scintilla/src/LexMatlab.cxx create mode 100644 src/stc/PlatWX.h create mode 100644 src/stc/scintilla/src/LexBaan.cxx create mode 100644 src/stc/scintilla/src/LexBullant.cxx create mode 100644 src/stc/scintilla/src/LexMatlab.cxx diff --git a/contrib/include/wx/stc/stc.h b/contrib/include/wx/stc/stc.h index 157f970301..0a5cafc81e 100644 --- a/contrib/include/wx/stc/stc.h +++ b/contrib/include/wx/stc/stc.h @@ -73,6 +73,9 @@ #define wxSTC_MARK_CIRCLEPLUSCONNECTED 19 #define wxSTC_MARK_CIRCLEMINUS 20 #define wxSTC_MARK_CIRCLEMINUSCONNECTED 21 + +// Invisible mark that only sets the line background color +#define wxSTC_MARK_BACKGROUND 22 #define wxSTC_MARK_CHARACTER 10000 // Markers used for outlining column @@ -83,6 +86,7 @@ #define wxSTC_MARKNUM_FOLDERSUB 29 #define wxSTC_MARKNUM_FOLDER 30 #define wxSTC_MARKNUM_FOLDEROPEN 31 +#define wxSTC_MASK_FOLDERS 0xFE000000 #define wxSTC_MARGIN_SYMBOL 0 #define wxSTC_MARGIN_NUMBER 1 @@ -127,10 +131,10 @@ #define wxSTC_INDIC_TT 2 #define wxSTC_INDIC_DIAGONAL 3 #define wxSTC_INDIC_STRIKE 4 -#define wxSTC_INDIC0_MASK 32 -#define wxSTC_INDIC1_MASK 64 -#define wxSTC_INDIC2_MASK 128 -#define wxSTC_INDICS_MASK 224 +#define wxSTC_INDIC0_MASK 0x20 +#define wxSTC_INDIC1_MASK 0x40 +#define wxSTC_INDIC2_MASK 0x80 +#define wxSTC_INDICS_MASK 0xE0 // PrintColourMode - use same colours as screen. #define wxSTC_PRINT_NORMAL 0 @@ -159,6 +163,12 @@ #define wxSTC_FOLDLEVELHEADERFLAG 0x2000 #define wxSTC_FOLDLEVELNUMBERMASK 0x0FFF #define wxSTC_TIME_FOREVER 10000000 +#define wxSTC_WRAP_NONE 0 +#define wxSTC_WRAP_WORD 1 +#define wxSTC_CACHE_NONE 0 +#define wxSTC_CACHE_CARET 1 +#define wxSTC_CACHE_PAGE 2 +#define wxSTC_CACHE_DOCUMENT 3 #define wxSTC_CMD_LINEDOWN 2300 #define wxSTC_CMD_LINEDOWNEXTEND 2301 #define wxSTC_CMD_LINEUP 2302 @@ -203,6 +213,7 @@ #define wxSTC_CMD_UPPERCASE 2341 #define wxSTC_CMD_LINESCROLLDOWN 2342 #define wxSTC_CMD_LINESCROLLUP 2343 +#define wxSTC_CMD_DELETEBACKNOTLINE 2344 #define wxSTC_EDGE_NONE 0 #define wxSTC_EDGE_LINE 1 #define wxSTC_EDGE_BACKGROUND 2 @@ -302,6 +313,12 @@ #define wxSTC_LEX_EIFFELKW 24 #define wxSTC_LEX_TCL 25 #define wxSTC_LEX_NNCRONTAB 26 +#define wxSTC_LEX_BULLANT 27 +#define wxSTC_LEX_VBSCRIPT 28 +#define wxSTC_LEX_ASP 29 +#define wxSTC_LEX_PHP 30 +#define wxSTC_LEX_BAAN 31 +#define wxSTC_LEX_MATLAB 32 // When a lexer specifies its language as SCLEX_AUTOMATIC it receives a // value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -323,7 +340,7 @@ #define wxSTC_P_COMMENTBLOCK 12 #define wxSTC_P_STRINGEOL 13 -// Lexical states for SCLEX_CPP, SCLEX_VB +// Lexical states for SCLEX_CPP #define wxSTC_C_DEFAULT 0 #define wxSTC_C_COMMENT 1 #define wxSTC_C_COMMENTLINE 2 @@ -344,6 +361,17 @@ #define wxSTC_C_COMMENTDOCKEYWORD 17 #define wxSTC_C_COMMENTDOCKEYWORDERROR 18 +// Lexical states for SCLEX_VB, SCLEX_VBSCRIPT +#define wxSTC_B_DEFAULT 0 +#define wxSTC_B_COMMENT 1 +#define wxSTC_B_NUMBER 2 +#define wxSTC_B_KEYWORD 3 +#define wxSTC_B_STRING 4 +#define wxSTC_B_PREPROCESSOR 5 +#define wxSTC_B_OPERATOR 6 +#define wxSTC_B_IDENTIFIER 7 +#define wxSTC_B_DATE 8 + // Lexical states for SCLEX_HTML, SCLEX_XML #define wxSTC_H_DEFAULT 0 #define wxSTC_H_TAG 1 @@ -531,6 +559,11 @@ #define wxSTC_LUA_OPERATOR 10 #define wxSTC_LUA_IDENTIFIER 11 #define wxSTC_LUA_STRINGEOL 12 +#define wxSTC_LUA_WORD2 13 +#define wxSTC_LUA_WORD3 14 +#define wxSTC_LUA_WORD4 15 +#define wxSTC_LUA_WORD5 16 +#define wxSTC_LUA_WORD6 17 // Lexical states for SCLEX_ERRORLIST #define wxSTC_ERR_DEFAULT 0 @@ -602,6 +635,19 @@ #define wxSTC_ADA_IDENTIFIER 7 #define wxSTC_ADA_STRINGEOL 8 +// Lexical states for SCLEX_BAAN +#define wxSTC_BAAN_DEFAULT 0 +#define wxSTC_BAAN_COMMENT 1 +#define wxSTC_BAAN_COMMENTDOC 2 +#define wxSTC_BAAN_NUMBER 3 +#define wxSTC_BAAN_WORD 4 +#define wxSTC_BAAN_STRING 5 +#define wxSTC_BAAN_PREPROCESSOR 6 +#define wxSTC_BAAN_OPERATOR 7 +#define wxSTC_BAAN_IDENTIFIER 8 +#define wxSTC_BAAN_STRINGEOL 9 +#define wxSTC_BAAN_WORD2 10 + // Lexical states for SCLEX_LISP #define wxSTC_LISP_DEFAULT 0 #define wxSTC_LISP_COMMENT 1 @@ -636,21 +682,17 @@ #define wxSTC_NNCRONTAB_ENVIRONMENT 9 #define wxSTC_NNCRONTAB_IDENTIFIER 10 -// END of generated section -//---------------------------------------------------------------------- -// Others - -#define wxSTC_MASK_FOLDERS ((1 << wxSTC_MARKNUM_FOLDER) | \ - (1 << wxSTC_MARKNUM_FOLDEROPEN) | \ - (1 << wxSTC_MARKNUM_FOLDERSUB) | \ - (1 << wxSTC_MARKNUM_FOLDERTAIL) | \ - (1 << wxSTC_MARKNUM_FOLDERMIDTAIL) | \ - (1 << wxSTC_MARKNUM_FOLDEROPENMID) | \ - (1 << wxSTC_MARKNUM_FOLDEREND)) - - - +// Lexical states for SCLEX_MATLAB +#define wxSTC_MATLAB_DEFAULT 0 +#define wxSTC_MATLAB_COMMENT 1 +#define wxSTC_MATLAB_COMMAND 2 +#define wxSTC_MATLAB_NUMBER 3 +#define wxSTC_MATLAB_KEYWORD 4 +#define wxSTC_MATLAB_STRING 5 +#define wxSTC_MATLAB_OPERATOR 6 +#define wxSTC_MATLAB_IDENTIFIER 7 +// END of generated section //---------------------------------------------------------------------- class ScintillaWX; // forward declare @@ -821,7 +863,7 @@ public: void SetCodePage(int codePage); // Set the symbol used for a particular marker number, - // and optionally the for and background colours. + // and optionally the fore and background colours. void MarkerDefine(int markerNumber, int markerSymbol, const wxColour& foreground = wxNullColour, const wxColour& background = wxNullColour); @@ -832,8 +874,8 @@ public: // Set the background colour used for a particular marker number. void MarkerSetBackground(int markerNumber, const wxColour& back); - // Add a marker to a line. - void MarkerAdd(int line, int markerNumber); + // Add a marker to a line, returning an ID which can be used to find or delete the marker. + int MarkerAdd(int line, int markerNumber); // Delete a marker from a line void MarkerDelete(int line, int markerNumber); @@ -980,7 +1022,7 @@ public: // Is the background of the line containing the caret in a different colour? bool GetCaretLineVisible(); - // Display the background of the line containing the caret in a different colour. + // Dsplay the background of the line containing the caret in a different colour. void SetCaretLineVisible(bool show); // Get the colour of the background of the line containing the caret. @@ -989,6 +1031,10 @@ public: // Set the colour of the background of the line containing the caret. void SetCaretLineBack(const wxColour& back); + // Set a style to be changeable or not (read only). + // Experimental feature, currently buggy. + void StyleSetChangeable(int style, bool changeable); + // Display a auto-completion list. // The lenEntered parameter indicates how many characters before // the caret should be used to provide context. @@ -1027,7 +1073,8 @@ public: // Retrieve whether auto-completion cancelled by backspacing before start. bool AutoCompGetCancelAtStart(); - // Define a set of character that when typed fills up the selected word. + // Define a set of characters that when typed will cause the autocompletion to + // choose the selected item. void AutoCompSetFillUps(const wxString& characterSet); // Should a single item auto-completion list automatically choose the item. @@ -1051,6 +1098,12 @@ public: // Retrieve whether or not autocompletion is hidden automatically when nothing matches bool AutoCompGetAutoHide(); + // Set whether or not autocompletion deletes any word characters after the inserted text upon completion + void AutoCompSetDropRestOfWord(bool dropRestOfWord); + + // Retrieve whether or not autocompletion deletes any word characters after the inserted text upon completion + bool AutoCompGetDropRestOfWord(); + // Set the number of spaces used for one level of indentation. void SetIndent(int indentSize); @@ -1369,6 +1422,28 @@ public: // Retrieve the time the mouse must sit still to generate a mouse dwell event int GetMouseDwellTime(); + // Get position of start of word + int WordStartPosition(int pos, bool onlyWordCharacters); + + // Get position of end of word + int WordEndPosition(int pos, bool onlyWordCharacters); + + // Sets whether text is word wrapped + void SetWrapMode(int mode); + + // Retrieve whether text is word wrapped + int GetWrapMode(); + + // Sets the degree of caching of layout information + void SetLayoutCache(int mode); + + // Retrieve the degree of caching of layout information + int GetLayoutCache(); + + // Delete the selection or if no selection, the character before the caret. + // Will not delete the chraacter before at the start of a line. + void DeleteBackNotLine(); + // Move the caret inside current view if it's not there already void MoveCaretInsideView(); @@ -1487,6 +1562,13 @@ public: // Get cursor type int GetCursor(); + // Change the way control characters are displayed: + // If symbol is < 32, keep the drawn way, else, use the given character + void SetControlCharSymbol(int symbol); + + // Get the way control characters are displayed + int GetControlCharSymbol(); + // Move to the previous change in capitalistion void WordPartLeft(); @@ -1508,6 +1590,10 @@ public: // Delete forwards from the current position to the end of the line void DelLineRight(); + // Get and Set the xOffset (ie, horizonal scroll position) + void SetXOffset(int newOffset); + int GetXOffset(); + // Start notifying the container of all key presses and commands. void StartRecord(); diff --git a/contrib/src/stc/Makefile.in b/contrib/src/stc/Makefile.in index d6fdd6bc60..01b2877cb8 100644 --- a/contrib/src/stc/Makefile.in +++ b/contrib/src/stc/Makefile.in @@ -34,6 +34,9 @@ OBJECTS=PlatWX.o ScintillaWX.o stc.o \ KeyMap.o \ KeyWords.o \ LexAVE.o \ + LexBaan.o \ + LexBullant.o \ + LexMatlab.o \ LexAda.o \ LexCPP.o \ LexConf.o \ @@ -61,7 +64,7 @@ OBJECTS=PlatWX.o ScintillaWX.o stc.o \ DEPFILES=$(OBJECTS:.o=.d) -APPEXTRADEFS=-D__WX__ -DSCI_LEXER -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/contrib/include +APPEXTRADEFS=-D__WX__ -DSCI_LEXER -DLINK_LEXERS -I$(scintilla_dir)/src -I$(scintilla_dir)/include -I$(top_srcdir)/contrib/include include $(top_builddir)/src/makelib.env diff --git a/contrib/src/stc/PlatWX.cpp b/contrib/src/stc/PlatWX.cpp index 52a351218a..ae08569e59 100644 --- a/contrib/src/stc/PlatWX.cpp +++ b/contrib/src/stc/PlatWX.cpp @@ -6,7 +6,10 @@ #include +#include + #include "Platform.h" +#include "PlatWX.h" #include "wx/stc/stc.h" @@ -14,6 +17,7 @@ #include #endif + Point Point::FromLong(long lpoint) { return Point(lpoint & 0xFFFF, lpoint >> 16); } @@ -29,35 +33,12 @@ PRectangle PRectangleFromwxRect(wxRect rc) { rc.GetRight()+1, rc.GetBottom()+1); } -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(); +wxColour wxColourFromCA(const ColourAllocated& ca) { + ColourDesired cd(ca.AsLong()); + return wxColour(cd.GetRed(), cd.GetGreen(), cd.GetBlue()); } -unsigned int Colour::GetBlue() { - return co.Blue(); -} +//---------------------------------------------------------------------- Palette::Palette() { used = 0; @@ -84,7 +65,7 @@ void Palette::WantFind(ColourPair &cp, bool want) { if (used < numEntries) { entries[used].desired = cp.desired; - entries[used].allocated = cp.desired; + entries[used].allocated.Set(cp.desired.AsLong()); used++; } } else { @@ -94,7 +75,7 @@ void Palette::WantFind(ColourPair &cp, bool want) { return; } } - cp.allocated = cp.desired; + cp.allocated.Set(cp.desired.AsLong()); } } @@ -104,6 +85,8 @@ void Palette::Allocate(Window &) { } +//---------------------------------------------------------------------- + Font::Font() { id = 0; ascent = 0; @@ -113,36 +96,172 @@ Font::~Font() { } void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) { - // TODO: what to do about the characterSet? + wxFontEncoding encoding; Release(); + + switch (characterSet) { + default: + case wxSTC_CHARSET_ANSI: + case wxSTC_CHARSET_DEFAULT: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_BALTIC: + encoding = wxFONTENCODING_ISO8859_13; + break; + + case wxSTC_CHARSET_CHINESEBIG5: + encoding = wxFONTENCODING_CP950; + break; + + case wxSTC_CHARSET_EASTEUROPE: + encoding = wxFONTENCODING_ISO8859_2; + break; + + case wxSTC_CHARSET_GB2312: + encoding = wxFONTENCODING_CP936; + break; + + case wxSTC_CHARSET_GREEK: + encoding = wxFONTENCODING_ISO8859_7; + break; + + case wxSTC_CHARSET_HANGUL: + encoding = wxFONTENCODING_CP949; + break; + + case wxSTC_CHARSET_MAC: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_OEM: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_RUSSIAN: + encoding = wxFONTENCODING_KOI8; + break; + + case wxSTC_CHARSET_SHIFTJIS: + encoding = wxFONTENCODING_CP932; + break; + + case wxSTC_CHARSET_SYMBOL: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_TURKISH: + encoding = wxFONTENCODING_ISO8859_9; + break; + + case wxSTC_CHARSET_JOHAB: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_HEBREW: + encoding = wxFONTENCODING_ISO8859_8; + break; + + case wxSTC_CHARSET_ARABIC: + encoding = wxFONTENCODING_ISO8859_6; + break; + + case wxSTC_CHARSET_VIETNAMESE: + encoding = wxFONTENCODING_DEFAULT; + break; + + case wxSTC_CHARSET_THAI: + encoding = wxFONTENCODING_ISO8859_11; + break; + } + + // TODO: Use wxFontMapper and wxEncodingConverter if encoding not available. + id = new wxFont(size, wxDEFAULT, italic ? wxITALIC : wxNORMAL, bold ? wxBOLD : wxNORMAL, false, faceName, - wxFONTENCODING_DEFAULT); + encoding); } void Font::Release() { if (id) - delete id; + delete (wxFont*)id; id = 0; } +//---------------------------------------------------------------------- + +class SurfaceImpl : public Surface { +private: + wxDC* hdc; + bool hdcOwned; + wxBitmap* bitmap; + int x; + int y; + bool unicodeMode; -Surface::Surface() : +public: + SurfaceImpl(); + ~SurfaceImpl(); + + void Init(); + void Init(SurfaceID sid); + void InitPixMap(int width, int height, Surface *surface_); + + void Release(); + bool Initialised(); + void PenColour(ColourAllocated fore); + int LogPixelsY(); + int DeviceHeightFont(int points); + void MoveTo(int x_, int y_); + void LineTo(int x_, int y_); + void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back); + void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back); + void FillRectangle(PRectangle rc, ColourAllocated back); + void FillRectangle(PRectangle rc, Surface &surfacePattern); + void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back); + void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); + void Copy(PRectangle rc, Point from, Surface &surfaceSource); + + void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); + void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); + void MeasureWidths(Font &font_, const char *s, int len, int *positions); + int WidthText(Font &font_, const char *s, int len); + int WidthChar(Font &font_, char ch); + int Ascent(Font &font_); + int Descent(Font &font_); + int InternalLeading(Font &font_); + int ExternalLeading(Font &font_); + int Height(Font &font_); + int AverageCharWidth(Font &font_); + + int SetPalette(Palette *pal, bool inBackGround); + void SetClip(PRectangle rc); + void FlushCachedState(); + + void SetUnicodeMode(bool unicodeMode_); + + void BrushColour(ColourAllocated back); + void SetFont(Font &font_); +}; + + + +SurfaceImpl::SurfaceImpl() : hdc(0), hdcOwned(0), bitmap(0), - x(0), y(0) { -} + x(0), y(0), unicodeMode(0) +{} -Surface::~Surface() { +SurfaceImpl::~SurfaceImpl() { Release(); } -void Surface::Release() { +void SurfaceImpl::Release() { if (bitmap) { ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap); delete bitmap; @@ -156,24 +275,24 @@ void Surface::Release() { } -bool Surface::Initialised() { +bool SurfaceImpl::Initialised() { return hdc != 0; } -void Surface::Init() { +void SurfaceImpl::Init() { Release(); hdc = new wxMemoryDC(); hdcOwned = true; } -void Surface::Init(SurfaceID hdc_) { +void SurfaceImpl::Init(SurfaceID hdc_) { Release(); - hdc = hdc_; + hdc = (wxDC*)hdc_; } -void Surface::InitPixMap(int width, int height, Surface *surface_) { +void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_) { Release(); - hdc = new wxMemoryDC(surface_->hdc); + hdc = new wxMemoryDC(); hdcOwned = true; if (width < 1) width = 1; if (height < 1) height = 1; @@ -181,64 +300,63 @@ void Surface::InitPixMap(int width, int height, Surface *surface_) { ((wxMemoryDC*)hdc)->SelectObject(*bitmap); } -void Surface::PenColour(Colour fore) { - hdc->SetPen(wxPen(fore.co, 1, wxSOLID)); +void SurfaceImpl::PenColour(ColourAllocated fore) { + hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID)); } -void Surface::BrushColor(Colour back) { - hdc->SetBrush(wxBrush(back.co, wxSOLID)); +void SurfaceImpl::BrushColour(ColourAllocated back) { + hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID)); } -void Surface::SetFont(Font &font_) { +void SurfaceImpl::SetFont(Font &font_) { if (font_.GetID()) { - hdc->SetFont(*font_.GetID()); + hdc->SetFont(*((wxFont*)font_.GetID())); } } -int Surface::LogPixelsY() { +int SurfaceImpl::LogPixelsY() { return hdc->GetPPI().y; } - -int Surface::DeviceHeightFont(int points) { +int SurfaceImpl::DeviceHeightFont(int points) { return points; +// int logPix = LogPixelsY(); +// return (points * logPix + logPix / 2) / 72; } - -void Surface::MoveTo(int x_, int y_) { +void SurfaceImpl::MoveTo(int x_, int y_) { x = x_; y = y_; } -void Surface::LineTo(int x_, int y_) { +void SurfaceImpl::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) { +void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) { PenColour(fore); - BrushColor(back); + BrushColour(back); hdc->DrawPolygon(npts, (wxPoint*)pts); } -void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) { +void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); - BrushColor(back); + BrushColour(back); hdc->DrawRectangle(wxRectFromPRectangle(rc)); } -void Surface::FillRectangle(PRectangle rc, Colour back) { - BrushColor(back); +void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) { + BrushColour(back); hdc->SetPen(*wxTRANSPARENT_PEN); hdc->DrawRectangle(wxRectFromPRectangle(rc)); } -void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) { +void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { wxBrush br; - if (surfacePattern.bitmap) - br = wxBrush(*surfacePattern.bitmap); + if (((SurfaceImpl&)surfacePattern).bitmap) + br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap); else // Something is wrong so display in red br = wxBrush(*wxRED, wxSOLID); hdc->SetPen(*wxTRANSPARENT_PEN); @@ -246,79 +364,112 @@ void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) { hdc->DrawRectangle(wxRectFromPRectangle(rc)); } -void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) { +void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); - BrushColor(back); + BrushColour(back); hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4); } -void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) { +void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) { PenColour(fore); - BrushColor(back); + BrushColour(back); hdc->DrawEllipse(wxRectFromPRectangle(rc)); } -void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) { +void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { wxRect r = wxRectFromPRectangle(rc); hdc->Blit(r.x, r.y, r.width, r.height, - surfaceSource.hdc, from.x, from.y, wxCOPY); + ((SurfaceImpl&)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) { +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase, + const char *s, int len, + ColourAllocated fore, ColourAllocated back) { SetFont(font); - hdc->SetTextForeground(fore.co); - hdc->SetTextBackground(back.co); + hdc->SetTextForeground(wxColourFromCA(fore)); + hdc->SetTextBackground(wxColourFromCA(back)); FillRectangle(rc, back); +#if wxUSE_UNICODE +#error fix this... Convert s from UTF-8. +#else + wxString str = wxString(s, len); +#endif + // 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); + hdc->DrawText(str, rc.left, ybase - font.ascent); } -void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) { +void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase, + const char *s, int len, + ColourAllocated fore, ColourAllocated back) { SetFont(font); - hdc->SetTextForeground(fore.co); - hdc->SetTextBackground(back.co); + hdc->SetTextForeground(wxColourFromCA(fore)); + hdc->SetTextBackground(wxColourFromCA(back)); FillRectangle(rc, back); hdc->SetClippingRegion(wxRectFromPRectangle(rc)); +#if wxUSE_UNICODE +#error fix this... Convert s from UTF-8. +#else + wxString str = wxString(s, len); +#endif + // see comments above - hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent); + hdc->DrawText(str, rc.left, ybase - font.ascent); hdc->DestroyClippingRegion(); } -int Surface::WidthText(Font &font, const char *s, int len) { +int SurfaceImpl::WidthText(Font &font, const char *s, int len) { SetFont(font); int w; int h; - hdc->GetTextExtent(wxString(s, len), &w, &h); + +#if wxUSE_UNICODE +#error fix this... Convert s from UTF-8. +#else + wxString str = wxString(s, len); +#endif + + hdc->GetTextExtent(str, &w, &h); return w; } -void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) { +void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) { +#if wxUSE_UNICODE +#error fix this... Convert s from UTF-8. +#else + wxString str = wxString(s, len); +#endif + SetFont(font); int totalWidth = 0; - for (int i=0; iGetTextExtent(s[i], &w, &h); + hdc->GetTextExtent(str[i], &w, &h); totalWidth += w; positions[i] = totalWidth; } } -int Surface::WidthChar(Font &font, char ch) { +int SurfaceImpl::WidthChar(Font &font, char ch) { SetFont(font); int w; int h; +#if wxUSE_UNICODE +#error fix this... Convert s from UTF-8. +#else hdc->GetTextExtent(ch, &w, &h); +#endif return w; } -#define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") -int Surface::Ascent(Font &font) { +int SurfaceImpl::Ascent(Font &font) { SetFont(font); int w, h, d, e; hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e); @@ -326,66 +477,81 @@ int Surface::Ascent(Font &font) { return font.ascent; } -int Surface::Descent(Font &font) { +int SurfaceImpl::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) { +int SurfaceImpl::InternalLeading(Font &font) { return 0; } -int Surface::ExternalLeading(Font &font) { +int SurfaceImpl::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) { +int SurfaceImpl::Height(Font &font) { SetFont(font); return hdc->GetCharHeight(); } -int Surface::AverageCharWidth(Font &font) { +int SurfaceImpl::AverageCharWidth(Font &font) { SetFont(font); return hdc->GetCharWidth(); } -int Surface::SetPalette(Palette *pal, bool inBackGround) { +int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) { return 0; } -void Surface::SetClip(PRectangle rc) { +void SurfaceImpl::SetClip(PRectangle rc) { hdc->SetClippingRegion(wxRectFromPRectangle(rc)); } -void Surface::FlushCachedState() { +void SurfaceImpl::FlushCachedState() { } +void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { + // TODO: Make this jive with wxUSE_UNICODE + unicodeMode=unicodeMode_; +} + +Surface *Surface::Allocate() { + return new SurfaceImpl; +} + + +//---------------------------------------------------------------------- + + +inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; } + Window::~Window() { } void Window::Destroy() { if (id) - id->Destroy(); + GETWIN(id)->Destroy(); id = 0; } bool Window::HasFocus() { - return wxWindow::FindFocus() == id; + return wxWindow::FindFocus() == GETWIN(id); } PRectangle Window::GetPosition() { - wxRect rc(id->GetPosition(), id->GetSize()); + wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize()); return PRectangleFromwxRect(rc); } void Window::SetPosition(PRectangle rc) { wxRect r = wxRectFromPRectangle(rc); - id->SetSize(r); + GETWIN(id)->SetSize(r); } void Window::SetPositionRelative(PRectangle rc, Window) { @@ -393,25 +559,25 @@ void Window::SetPositionRelative(PRectangle rc, Window) { } PRectangle Window::GetClientPosition() { - wxSize sz = id->GetClientSize(); + wxSize sz = GETWIN(id)->GetClientSize(); return PRectangle(0, 0, sz.x, sz.y); } void Window::Show(bool show) { - id->Show(show); + GETWIN(id)->Show(show); } void Window::InvalidateAll() { - id->Refresh(false); + GETWIN(id)->Refresh(false); } void Window::InvalidateRectangle(PRectangle rc) { wxRect r = wxRectFromPRectangle(rc); - id->Refresh(false, &r); + GETWIN(id)->Refresh(false, &r); } void Window::SetFont(Font &font) { - id->SetFont(*font.GetID()); + GETWIN(id)->SetFont(*((wxFont*)font.GetID())); } void Window::SetCursor(Cursor curs) { @@ -444,19 +610,23 @@ void Window::SetCursor(Cursor curs) { break; } - id->SetCursor(wxCursor(cursorId)); + GETWIN(id)->SetCursor(wxCursor(cursorId)); } void Window::SetTitle(const char *s) { - id->SetTitle(s); +#if wxUSE_UNICODE +#error Fix this... +#else + GETWIN(id)->SetTitle(s); +#endif } //---------------------------------------------------------------------- // Helper classes for ListBox -// A wxListBox that gives focus to its parent if it gets it. +// A wxListBox that gives focus back to its parent if it gets it. class wxSTCListBox : public wxListBox { public: wxSTCListBox(wxWindow* parent, wxWindowID id) @@ -532,7 +702,9 @@ BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxSTCListBoxWinBase) END_EVENT_TABLE() -#define GETLB(win) (((wxSTCListBoxWin*)win)->GetLB()) +inline wxListBox* GETLB(WindowID win) { + return (((wxSTCListBoxWin*)win)->GetLB()); +} //---------------------------------------------------------------------- @@ -543,7 +715,7 @@ ListBox::~ListBox() { } void ListBox::Create(Window &parent, int ctrlID) { - id = new wxSTCListBoxWin(parent.id, ctrlID); + id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID); } void ListBox::SetVisibleRows(int rows) { @@ -569,7 +741,7 @@ void ListBox::SetAverageCharWidth(int width) { } void ListBox::SetFont(Font &font) { - GETLB(id)->SetFont(*font.GetID()); + GETLB(id)->SetFont(*((wxFont*)font.GetID())); } void ListBox::Clear() { @@ -605,14 +777,18 @@ int ListBox::Find(const char *prefix) { } void ListBox::GetValue(int n, char *value, int len) { +#if wxUSE_UNICODE +#error fix this... wxString text = GETLB(id)->GetString(n); strncpy(value, text.c_str(), len); value[len-1] = '\0'; +#endif } void ListBox::Sort() { } +//---------------------------------------------------------------------- Menu::Menu() : id(0) { } @@ -624,26 +800,27 @@ void Menu::CreatePopUp() { void Menu::Destroy() { if (id) - delete id; + delete (wxMenu*)id; id = 0; } void Menu::Show(Point pt, Window &w) { - w.GetID()->PopupMenu(id, pt.x - 4, pt.y); + GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y); Destroy(); } +//---------------------------------------------------------------------- -Colour Platform::Chrome() { +ColourDesired Platform::Chrome() { wxColour c; c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); - return Colour(c.Red(), c.Green(), c.Blue()); + return ColourDesired(c.Red(), c.Green(), c.Blue()); } -Colour Platform::ChromeHighlight() { +ColourDesired Platform::ChromeHighlight() { wxColour c; c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT); - return Colour(c.Red(), c.Green(), c.Blue()); + return ColourDesired(c.Red(), c.Green(), c.Blue()); } const char *Platform::DefaultFont() { @@ -744,6 +921,26 @@ int Platform::Clamp(int val, int minVal, int maxVal) { } +bool Platform::IsDBCSLeadByte(int codePage, char ch) { + return false; +} + + + +//---------------------------------------------------------------------- + +ElapsedTime::ElapsedTime() { + wxStartTimer(); +} + +double ElapsedTime::Duration(bool reset) { + double result = wxGetElapsedTime(reset); + result /= 1000.0; + return result; +} + + +//---------------------------------------------------------------------- diff --git a/contrib/src/stc/PlatWX.h b/contrib/src/stc/PlatWX.h new file mode 100644 index 0000000000..e658a67f65 --- /dev/null +++ b/contrib/src/stc/PlatWX.h @@ -0,0 +1,8 @@ + + + + +wxRect wxRectFromPRectangle(PRectangle prc); +PRectangle PRectangleFromwxRect(wxRect rc); +wxColour wxColourFromCA(const ColourAllocated& ca); + diff --git a/contrib/src/stc/ScintillaWX.cpp b/contrib/src/stc/ScintillaWX.cpp index da83a4212c..1b65391a59 100644 --- a/contrib/src/stc/ScintillaWX.cpp +++ b/contrib/src/stc/ScintillaWX.cpp @@ -14,10 +14,10 @@ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// -#include #include "ScintillaWX.h" #include "wx/stc/stc.h" +#include "PlatWX.h" //---------------------------------------------------------------------- @@ -82,10 +82,10 @@ public: void OnPaint(wxPaintEvent& evt) { wxPaintDC dc(this); - Surface surfaceWindow; - surfaceWindow.Init(&dc); - m_ct->PaintCT(&surfaceWindow); - surfaceWindow.Release(); + Surface* surfaceWindow = Surface::Allocate(); + surfaceWindow->Init(&dc); + m_ct->PaintCT(surfaceWindow); + delete surfaceWindow; } #if wxUSE_POPUPWIN @@ -184,7 +184,7 @@ void ScintillaWX::SetTicking(bool on) { if (timer.ticking) { steTimer = new wxSTCTimer(this); steTimer->Start(timer.tickSize); - timer.tickerID = (int)steTimer; + timer.tickerID = steTimer; } else { steTimer = (wxSTCTimer*)timer.tickerID; steTimer->Stop(); @@ -343,12 +343,12 @@ void ScintillaWX::CreateCallTipWindow(PRectangle) { void ScintillaWX::AddToPopUp(const char *label, int cmd, bool enabled) { if (!label[0]) - popup.GetID()->AppendSeparator(); + ((wxMenu*)popup.GetID())->AppendSeparator(); else - popup.GetID()->Append(cmd, label); + ((wxMenu*)popup.GetID())->Append(cmd, label); if (!enabled) - popup.GetID()->Enable(cmd, enabled); + ((wxMenu*)popup.GetID())->Enable(cmd, enabled); } @@ -379,13 +379,13 @@ long ScintillaWX::WndProc(unsigned int iMessage, unsigned long wParam, long lPar void ScintillaWX::DoPaint(wxDC* dc, wxRect rect) { paintState = painting; - Surface surfaceWindow; - surfaceWindow.Init(dc); + Surface* surfaceWindow = Surface::Allocate(); + surfaceWindow->Init(dc); PRectangle rcPaint = PRectangleFromwxRect(rect); dc->BeginDrawing(); - Paint(&surfaceWindow, rcPaint); + Paint(surfaceWindow, rcPaint); dc->EndDrawing(); - surfaceWindow.Release(); + delete surfaceWindow; if (paintState == paintAbandoned) { // Painting area was insufficient to cover new styling or brace highlight positions FullPaint(); @@ -466,9 +466,10 @@ void ScintillaWX::DoMouseWheel(int rotation, int delta, int linesPerAction, int void ScintillaWX::DoSize(int width, int height) { - PRectangle rcClient(0,0,width,height); - SetScrollBarsTo(rcClient); - DropGraphics(); +// PRectangle rcClient(0,0,width,height); +// SetScrollBarsTo(rcClient); +// DropGraphics(); + ChangeSize(); } void ScintillaWX::DoLoseFocus(){ @@ -622,10 +623,10 @@ void ScintillaWX::FullPaint() { rcPaint = GetTextRectangle(); paintingAllText = true; wxClientDC dc(stc); - Surface surfaceWindow; - surfaceWindow.Init(&dc); - Paint(&surfaceWindow, rcPaint); - surfaceWindow.Release(); + Surface* surfaceWindow = Surface::Allocate(); + surfaceWindow->Init(&dc); + Paint(surfaceWindow, rcPaint); + delete surfaceWindow; // stc->Refresh(FALSE); diff --git a/contrib/src/stc/ScintillaWX.h b/contrib/src/stc/ScintillaWX.h index ffc229f538..6d583435ec 100644 --- a/contrib/src/stc/ScintillaWX.h +++ b/contrib/src/stc/ScintillaWX.h @@ -19,6 +19,11 @@ //---------------------------------------------------------------------- +#include +#include +#include +#include + #include "Platform.h" #include "Scintilla.h" diff --git a/contrib/src/stc/StcVC.dsp b/contrib/src/stc/StcVC.dsp index 9473d5230c..fd875fe06b 100644 --- a/contrib/src/stc/StcVC.dsp +++ b/contrib/src/stc/StcVC.dsp @@ -7,19 +7,19 @@ CFG=StcVC - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "StcVC.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "StcVC.mak" CFG="StcVC - Win32 Debug" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "StcVC - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "StcVC - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -76,7 +76,7 @@ LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"..\..\lib\stcd.lib" -!ENDIF +!ENDIF # Begin Target @@ -187,6 +187,18 @@ SOURCE=.\scintilla\src\LexAVE.cxx # End Source File # Begin Source File +SOURCE=.\scintilla\src\LexBaan.cxx +# End Source File +# Begin Source File + +SOURCE=.\scintilla\src\LexBullant.cxx +# End Source File +# Begin Source File + +SOURCE=.\scintilla\src\LexMatlab.cxx +# End Source File +# Begin Source File + SOURCE=.\scintilla\src\LexConf.cxx # End Source File # Begin Source File diff --git a/contrib/src/stc/gen_iface.py b/contrib/src/stc/gen_iface.py index 4c7d15bcca..b8d0972434 100644 --- a/contrib/src/stc/gen_iface.py +++ b/contrib/src/stc/gen_iface.py @@ -154,7 +154,7 @@ methodOverrideMap = { MarkerSetBackground(markerNumber, background);''', ('Set the symbol used for a particular marker number,', - 'and optionally the for and background colours.')), + 'and optionally the fore and background colours.')), 'SetMarginTypeN' : ('SetMarginType', 0, 0, 0), 'GetMarginTypeN' : ('GetMarginType', 0, 0, 0), @@ -226,6 +226,8 @@ methodOverrideMap = { 'AutoCGetIgnoreCase' : ('AutoCompGetIgnoreCase', 0, 0, 0), 'AutoCSetAutoHide' : ('AutoCompSetAutoHide', 0, 0, 0), 'AutoCGetAutoHide' : ('AutoCompGetAutoHide', 0, 0, 0), + 'AutoCSetDropRestOfWord' : ('AutoCompSetDropRestOfWord', 0,0,0), + 'AutoCGetDropRestOfWord' : ('AutoCompGetDropRestOfWord', 0,0,0), 'SetHScrollBar' : ('SetUseHorizontalScrollBar', 0, 0, 0), diff --git a/contrib/src/stc/makefile.b32 b/contrib/src/stc/makefile.b32 index 40e5497e24..72a60182ab 100644 --- a/contrib/src/stc/makefile.b32 +++ b/contrib/src/stc/makefile.b32 @@ -17,7 +17,7 @@ SCINTILLA=.\scintilla S=$(SCINTILLA)\src -STCEXTRACPPFLAGS=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S) +STCEXTRACPPFLAGS=-D__WX__ -DSCI_LEXER -DLINK_LEXERS -I$(SCINTILLA)/include -I$(S) LIBTARGET=$(WXDIR)\contrib\lib\stc.lib @@ -34,6 +34,9 @@ OBJECTS = \ KeyWords.obj \ LexAVE.obj \ LexAda.obj \ + LexBaan.obj \ + LexBullant.obj \ + LexMatlab.obj \ LexCPP.obj \ LexConf.obj \ LexCrontab.obj \ diff --git a/contrib/src/stc/makefile.g95 b/contrib/src/stc/makefile.g95 index cf708ed801..4ae99521f5 100644 --- a/contrib/src/stc/makefile.g95 +++ b/contrib/src/stc/makefile.g95 @@ -7,7 +7,7 @@ WXDIR = ../../.. SCINTILLA=$(WXDIR)/contrib/src/stc/scintilla S=$(SCINTILLA)/src -EXTRAINC=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)/contrib/include +EXTRAINC=-D__WX__ -DSCI_LEXER -DLINK_LEXERS -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)/contrib/include OBJECTS = \ $(S)/AutoComplete.$(OBJSUFF) \ @@ -22,6 +22,9 @@ OBJECTS = \ $(S)/KeyWords.$(OBJSUFF) \ $(S)/LexAVE.$(OBJSUFF) \ $(S)/LexAda.$(OBJSUFF) \ + $(S)/LexBaan.$(OBJSUFF) \ + $(S)/LexBullant.$(OBJSUFF) \ + $(S)/LexMatlab.$(OBJSUFF) \ $(S)/LexCPP.$(OBJSUFF) \ $(S)/LexConf.$(OBJSUFF) \ $(S)/LexCrontab.$(OBJSUFF) \ diff --git a/contrib/src/stc/makefile.vc b/contrib/src/stc/makefile.vc index 9c6d478b87..9a3fdc08e7 100644 --- a/contrib/src/stc/makefile.vc +++ b/contrib/src/stc/makefile.vc @@ -9,7 +9,7 @@ WXDIR = $(WXWIN) SCINTILLA=.\scintilla S=$(SCINTILLA)\src -EXTRAINC=-D__WX__ -DSCI_LEXER -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)\contrib\include +EXTRAINC=-D__WX__ -DSCI_LEXER -DLINK_LEXERS -I$(SCINTILLA)/include -I$(S) -I. -I$(WXDIR)\contrib\include NOPCH=1 !include $(WXDIR)\src\makevc.env @@ -27,6 +27,9 @@ OBJECTS = \ $(D)\KeyWords.obj \ $(D)\LexAVE.obj \ $(D)\LexAda.obj \ + $(D)\LexBaan.obj \ + $(D)\LexBullant.obj \ + $(D)\LexMatlab.obj \ $(D)\LexCPP.obj \ $(D)\LexConf.obj \ $(D)\LexCrontab.obj \ diff --git a/contrib/src/stc/scintilla/README.txt b/contrib/src/stc/scintilla/README.txt index 98c4018245..32a294845c 100644 --- a/contrib/src/stc/scintilla/README.txt +++ b/contrib/src/stc/scintilla/README.txt @@ -3,5 +3,5 @@ scintilla/include directories from the Scintilla/SCiTE source distribution. All other code needed to implement Scintilla on top of wxWindows is located in the directory above this one. -The current version of the Scintilla code is 1.40 +The current version of the Scintilla code is 1.45 diff --git a/contrib/src/stc/scintilla/include/KeyWords.h b/contrib/src/stc/scintilla/include/KeyWords.h index 869b59d267..fa427ff2eb 100644 --- a/contrib/src/stc/scintilla/include/KeyWords.h +++ b/contrib/src/stc/scintilla/include/KeyWords.h @@ -15,25 +15,25 @@ typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyl */ class LexerModule { protected: - LexerModule *next; + const LexerModule *next; int language; - const char *languageName; LexerFunction fnLexer; LexerFunction fnFolder; - static LexerModule *base; + static const LexerModule *base; static int nextLanguage; public: + const char *languageName; LexerModule(int language_, LexerFunction fnLexer_, const char *languageName_=0, LexerFunction fnFolder_=0); - int GetLanguage() { return language; } + int GetLanguage() const { return language; } virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler); + WordList *keywordlists[], Accessor &styler) const; virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler); - static LexerModule *Find(int language); - static LexerModule *Find(const char *languageName); + WordList *keywordlists[], Accessor &styler) const; + static const LexerModule *Find(int language); + static const LexerModule *Find(const char *languageName); }; /** diff --git a/contrib/src/stc/scintilla/include/Platform.h b/contrib/src/stc/scintilla/include/Platform.h index 48f337a16a..dc8c9dc935 100644 --- a/contrib/src/stc/scintilla/include/Platform.h +++ b/contrib/src/stc/scintilla/include/Platform.h @@ -3,7 +3,7 @@ ** 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-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef PLATFORM_H @@ -18,8 +18,13 @@ #define PLAT_GTK_WIN32 0 #define PLAT_WIN 0 #define PLAT_WX 0 +#define PLAT_FOX 0 -#if defined(__WX__) +#if defined(FOX) +#undef PLAT_FOX +#define PLAT_FOX 1 + +#elif defined(__WX__) #undef PLAT_WX #define PLAT_WX 1 @@ -39,79 +44,14 @@ #endif -// Include the main header for each platform - -#if PLAT_GTK -#ifdef _MSC_VER -#pragma warning(disable: 4505 4514 4710 4800) -#endif -#include -#include -#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: 4244 4309 4710 4800) -#endif -#include -#include -#include -#endif - -#if PLAT_WX -#include -#endif - -#define ColourID scColourID -#define FontID scFontID -#define SurfaceID scSurfaceID -#define WindowID scWindowID -#define MenuID scMenuID -#define Point scPoint -#define PRectangle scPRectangle -#define Colour scColour -#define ColourPair scColourPair -#define Window scWindow -#define Palette scPalette -#define Font scFont -#define Surface scSurface -#define Window scWindow -#define ListBox scListBox -#define Menu scMenu -#define Platform scPlatform -#define TextRange scTextRange -#define KeyMap scKeyMap -#define Style scStyle - - // 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 +typedef void *FontID; +typedef void *SurfaceID; +typedef void *WindowID; +typedef void *MenuID; +typedef void *TickerID; /** * A geometric point class. @@ -168,42 +108,88 @@ public: int Height() { return bottom - top; } }; -#if PLAT_WX -wxRect wxRectFromPRectangle(PRectangle prc); -PRectangle PRectangleFromwxRect(wxRect rc); -#endif +/** + * In some circumstances, including Win32 in paletted mode and GTK+, each colour + * must be allocated before use. The desired colours are held in the ColourDesired class, + * and after allocation the allocation entry is stored in the ColourAllocated class. In other + * circumstances, such as Win32 in true colour mode, the allocation process just copies + * the RGB values from the desired to the allocated class. + * As each desired colour requires allocation before it can be used, the ColourPair class + * holds both a ColourDesired and a ColourAllocated + * The Palette class is responsible for managing the palette of colours which contains a + * list of ColourPair objects and performs the allocation. + */ /** - * A colour class. + * Holds a desired RGB colour. */ -class Colour { - ColourID co; +class ColourDesired { + long 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(); + ColourDesired(long lcol=0) { + co = lcol; + } - friend class Surface; - friend class Palette; + ColourDesired(unsigned int red, unsigned int green, unsigned int blue) { + co = red | (green << 8) | (blue << 16); + } + + bool operator==(const ColourDesired &other) const { + return co == other.co; + } + + void Set(long lcol) { + co = lcol; + } + + long AsLong() const { + return co; + } + + unsigned int GetRed() { + return co & 0xff; + } + + unsigned int GetGreen() { + return (co >> 8) & 0xff; + } + + unsigned int GetBlue() { + return (co >> 16) & 0xff; + } }; /** - * 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. + * Holds an allocated RGB colour which may be an approximation to the desired colour. + */ +class ColourAllocated { + long coAllocated; + +public: + + ColourAllocated(long lcol=0) { + coAllocated = lcol; + } + + void Set(long lcol) { + coAllocated = lcol; + } + + long AsLong() const { + return coAllocated; + } +}; + +/** + * Colour pairs hold a desired colour and an allocated colour. */ struct ColourPair { - Colour desired; - Colour allocated; + ColourDesired desired; + ColourAllocated allocated; - ColourPair(Colour desired_=Colour(0,0,0)) { + ColourPair(ColourDesired desired_=ColourDesired(0,0,0)) { desired = desired_; - allocated = desired; + allocated.Set(desired.AsLong()); } }; @@ -217,14 +203,13 @@ class Palette { enum {numEntries = 100}; ColourPair entries[numEntries]; #if PLAT_GTK - GdkColor *allocatedPalette; + void *allocatedPalette; // GdkColor * int allocatedLen; -#elif PLAT_WIN - HPALETTE hpal; -#elif PLAT_WX - // wxPalette* pal; // **** Is this needed? #endif public: +#if PLAT_WIN + void *hpal; +#endif bool allowRealization; Palette(); @@ -240,8 +225,6 @@ public: void WantFind(ColourPair &cp, bool want); void Allocate(Window &w); - - friend class Surface; }; /** @@ -267,6 +250,7 @@ public: // Alias another font - caller guarantees not to Release void SetID(FontID id_) { id = id_; } friend class Surface; + friend class SurfaceImpl; }; /** @@ -274,97 +258,67 @@ public: */ class Surface { private: - bool unicodeMode; -#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(); - int DeviceHeightFont(int points); - 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); - void FlushCachedState(); - - void SetUnicodeMode(bool unicodeMode_) { - unicodeMode=unicodeMode_; - } + Surface() {}; + virtual ~Surface() {}; + static Surface *Allocate(); + + virtual void Init()=0; + virtual void Init(SurfaceID sid)=0; + virtual void InitPixMap(int width, int height, Surface *surface_)=0; + + virtual void Release()=0; + virtual bool Initialised()=0; + virtual void PenColour(ColourAllocated fore)=0; + virtual int LogPixelsY()=0; + virtual int DeviceHeightFont(int points)=0; + virtual void MoveTo(int x_, int y_)=0; + virtual void LineTo(int x_, int y_)=0; + virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back)=0; + virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; + virtual void FillRectangle(PRectangle rc, ColourAllocated back)=0; + virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; + virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; + virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; + virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; + + virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; + virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; + virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0; + virtual int WidthText(Font &font_, const char *s, int len)=0; + virtual int WidthChar(Font &font_, char ch)=0; + virtual int Ascent(Font &font_)=0; + virtual int Descent(Font &font_)=0; + virtual int InternalLeading(Font &font_)=0; + virtual int ExternalLeading(Font &font_)=0; + virtual int Height(Font &font_)=0; + virtual int AverageCharWidth(Font &font_)=0; + + virtual int SetPalette(Palette *pal, bool inBackGround)=0; + virtual void SetClip(PRectangle rc)=0; + virtual void FlushCachedState()=0; + + virtual void SetUnicodeMode(bool unicodeMode_)=0; }; +/** + * A simple callback action passing one piece of untyped user data. + */ +typedef void (*CallBackAction)(void*); + /** * Class to hide the details of window manipulation. * Does not own the window which will normally have a longer life than this object. */ class Window { - friend class ListBox; protected: WindowID id; public: - Window() : id(0) {} - Window(const Window &source) : id(source.id) {} + Window() : id(0), cursorLast(cursorInvalid) {} + Window(const Window &source) : id(source.id), cursorLast(cursorInvalid) {} virtual ~Window(); Window &operator=(WindowID id_) { id = id_; @@ -382,20 +336,19 @@ public: void InvalidateAll(); void InvalidateRectangle(PRectangle rc); virtual void SetFont(Font &font); - enum Cursor { cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow }; + enum Cursor { cursorInvalid, 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 +private: + Cursor cursorLast; }; /** * Listbox management. */ + class ListBox : public Window { +private: #if PLAT_GTK WindowID list; WindowID scroller; @@ -404,6 +357,9 @@ class ListBox : public Window { int desiredVisibleRows; unsigned int maxItemCharacters; unsigned int aveCharWidth; +public: + CallBackAction doubleClickAction; + void *doubleClickActionData; public: ListBox(); virtual ~ListBox(); @@ -420,6 +376,10 @@ public: int Find(const char *prefix); void GetValue(int n, char *value, int len); void Sort(); + void SetDoubleClickAction(CallBackAction action, void *data) { + doubleClickAction = action; + doubleClickActionData = data; + } }; /** @@ -435,6 +395,14 @@ public: void Show(Point pt, Window &w); }; +class ElapsedTime { + long bigBit; + long littleBit; +public: + ElapsedTime(); + double Duration(bool reset=false); +}; + /** * 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. @@ -448,8 +416,8 @@ public: // but gcc warns about this Platform() {} ~Platform() {} - static Colour Chrome(); - static Colour ChromeHighlight(); + static ColourDesired Chrome(); + static ColourDesired ChromeHighlight(); static const char *DefaultFont(); static int DefaultFontSize(); static unsigned int DoubleClickTime(); @@ -457,6 +425,7 @@ public: static bool IsKeyDown(int key); static long SendScintilla( WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0); + static bool IsDBCSLeadByte(int codePage, char ch); // These are utility functions not really tied to a platform static int Minimum(int a, int b); @@ -483,4 +452,9 @@ public: #define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__)) #endif +// Shut up annoying Visual C++ warnings: +#ifdef _MSC_VER +#pragma warning(disable: 4244 4309 4514 4710) +#endif + #endif diff --git a/contrib/src/stc/scintilla/include/PropSet.h b/contrib/src/stc/scintilla/include/PropSet.h index 6f6bf410f1..2596349818 100644 --- a/contrib/src/stc/scintilla/include/PropSet.h +++ b/contrib/src/stc/scintilla/include/PropSet.h @@ -2,7 +2,7 @@ /** @file PropSet.h ** A Java style properties file module. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef PROPSET_H @@ -41,7 +41,7 @@ public: SString Expand(const char *withVars); int GetInt(const char *key, int defaultValue=0); SString GetWild(const char *keybase, const char *filename); - SString GetNewExpand(const char *keybase, const char *filename); + SString GetNewExpand(const char *keybase, const char *filename=""); void Clear(); char *ToString(); // Caller must delete[] the return value bool GetFirst(char **key, char **val); @@ -70,7 +70,8 @@ public: char *Allocate(int size); void SetFromAllocated(); bool InList(const char *s); - const char *GetNearestWord(const char *wordStart, int searchLen = -1, bool ignoreCase = false); + const char *GetNearestWord(const char *wordStart, int searchLen = -1, + bool ignoreCase = false, SString wordCharacters=""); char *GetNearestWords(const char *wordStart, int searchLen=-1, bool ignoreCase=false, char otherSeparator='\0'); }; diff --git a/contrib/src/stc/scintilla/include/SString.h b/contrib/src/stc/scintilla/include/SString.h index aeb5940502..df7fd43b5b 100644 --- a/contrib/src/stc/scintilla/include/SString.h +++ b/contrib/src/stc/scintilla/include/SString.h @@ -8,7 +8,7 @@ #ifndef SSTRING_H #define SSTRING_H -// These functions are implemented because each platform calls them something different +// These functions are implemented because each platform calls them something different. int CompareCaseInsensitive(const char *a, const char *b); int CompareNCaseInsensitive(const char *a, const char *b, int len); bool EqualCaseInsensitive(const char *a, const char *b); @@ -17,63 +17,94 @@ bool EqualCaseInsensitive(const char *a, const char *b); // While it would be 'better' to use std::string, that doubles the executable size. // An SString may contain embedded nul characters. -/** - * Duplicate a C string. - * Allocate memory of the given size, or big enough to fit the string if length isn't given; - * then copy the given string in the allocated memory. - * @return the pointer to the new string - */ -inline char *StringDup( - const char *s, ///< The string to duplicate - int len=-1) ///< The length of memory to allocate. Optional. -{ - if (!s) - return 0; - if (len == -1) - len = strlen(s); - char *sNew = new char[len + 1]; - if (sNew) { - strncpy(sNew, s, len); - sNew[len] = '\0'; - } - return sNew; -} - /** * @brief A simple string class. + * * Hold the length of the string for quick operations, * can have a buffer bigger than the string to avoid too many memory allocations and copies. * May have embedded zeroes as a result of @a substitute, but rely too heavily on C string * functions to allow reliable manipulations of these strings. **/ class SString { - char *s; ///< The C string - int sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string - int sLen; ///< The size of the string in s - int sizeGrowth; ///< Minimum growth size when appending strings +public: + /** Type of string lengths (sizes) and positions (indexes). */ + typedef unsigned int lenpos_t; + /** Out of bounds value indicating that the string argument should be measured. */ + enum { measure_length=0xffffffffU}; + +private: + char *s; ///< The C string + lenpos_t sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string + lenpos_t sLen; ///< The size of the string in s + lenpos_t sizeGrowth; ///< Minimum growth size when appending strings enum { sizeGrowthDefault = 64 }; + bool grow(lenpos_t lenNew) { + while (sizeGrowth * 6 < lenNew) { + sizeGrowth *= 2; + } + char *sNew = new char[lenNew + sizeGrowth + 1]; + if (sNew) { + if (s) { + memcpy(sNew, s, sLen); + delete []s; + } + s = sNew; + s[sLen] = '\0'; + sSize = lenNew + sizeGrowth; + } + return sNew != 0; + } -public: - typedef int size_type; + SString &assign(const char *sOther, lenpos_t sSize_=measure_length) { + if (!sOther) { + sSize_ = 0; + } else if (sSize_ == measure_length) { + sSize_ = strlen(sOther); + } + if (sSize > 0 && sSize_ <= sSize) { // Does not allocate new buffer if the current is big enough + if (s && sSize_) { + strncpy(s, sOther, sSize_); + } + s[sSize_] = '\0'; + sLen = sSize_; + } else { + delete []s; + s = StringAllocate(sOther, sSize_); + if (s) { + sSize = sSize_; // Allow buffer bigger than real string, thus providing space to grow + sLen = strlen(s); + } else { + sSize = sLen = 0; + } + } + return *this; + } +public: SString() : s(0), sSize(0), sLen(0), sizeGrowth(sizeGrowthDefault) { } SString(const SString &source) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(source.s); + s = StringAllocate(source.s); sSize = sLen = (s) ? strlen(s) : 0; } SString(const char *s_) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(s_); + s = StringAllocate(s_); sSize = sLen = (s) ? strlen(s) : 0; } - SString(const char *s_, int first, int last) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(s_ + first, last - first); + SString(const char *s_, lenpos_t first, lenpos_t last) : sizeGrowth(sizeGrowthDefault) { + s = StringAllocate(s_ + first, last - first); sSize = sLen = (s) ? strlen(s) : 0; } SString(int i) : sizeGrowth(sizeGrowthDefault) { char number[32]; sprintf(number, "%0d", i); - s = StringDup(number); + s = StringAllocate(number); + sSize = sLen = (s) ? strlen(s) : 0; + } + SString(double d, int precision) : sizeGrowth(sizeGrowthDefault) { + char number[32]; + sprintf(number, "%.*f", precision, d); + s = StringAllocate(number); sSize = sLen = (s) ? strlen(s) : 0; } ~SString() { @@ -82,51 +113,23 @@ public: sSize = 0; sLen = 0; } - void clear(void) { + void clear() { if (s) { *s = '\0'; } sLen = 0; } /** Size of buffer. */ - size_type size(void) const { ///< + lenpos_t size() const { if (s) return sSize; else return 0; } /** Size of string in buffer. */ - int length() const { + lenpos_t length() const { return sLen; } - SString &assign(const char* sOther, int sSize_ = -1) { - if (!sOther) { - sSize_ = 0; - } - if (sSize_ < 0) { - sSize_ = strlen(sOther); - } - if (sSize > 0 && sSize_ <= sSize) { // Does not allocate new buffer if the current is big enough - if (s && sSize_) { - strncpy(s, sOther, sSize_); - } - s[sSize_] = '\0'; - sLen = sSize_; - } else { - delete []s; - s = StringDup(sOther, sSize_); - if (s) { - sSize = sSize_; // Allow buffer bigger than real string, thus providing space to grow - sLen = strlen(s); - } else { - sSize = sLen = 0; - } - } - return *this; - } - SString &assign(const SString& sOther, int sSize_ = -1) { - return assign(sOther.s, sSize_); - } SString &operator=(const char *source) { return assign(source); } @@ -162,7 +165,7 @@ public: else return false; } - void setsizegrowth(int sizeGrowth_) { + void setsizegrowth(lenpos_t sizeGrowth_) { sizeGrowth = sizeGrowth_; } const char *c_str() const { @@ -179,77 +182,167 @@ public: sLen = 0; return sRet; } - char operator[](int i) const { + char operator[](lenpos_t i) const { if (s && i < sSize) // Or < sLen? Depends on the use, both are OK return s[i]; else return '\0'; } - SString &append(const char* sOther, int sLenOther=-1, char sep=0) { - if (sLenOther < 0) + SString &append(const char *sOther, lenpos_t sLenOther=measure_length, char sep = '\0') { + if (!sOther) { + return *this; + } + if (sLenOther == measure_length) { sLenOther = strlen(sOther); + } int lenSep = 0; - if (sLen && sep) // Only add a separator if not empty + if (sLen && sep) { // Only add a separator if not empty lenSep = 1; - int lenNew = sLen + sLenOther + lenSep; - if (lenNew + 1 < sSize) { - // Conservative about growing the buffer: don't do it, unless really needed + } + lenpos_t lenNew = sLen + sLenOther + lenSep; + // Conservative about growing the buffer: don't do it, unless really needed + if ((lenNew + 1 < sSize) || (grow(lenNew))) { if (lenSep) { s[sLen] = sep; sLen++; } strncpy(&s[sLen], sOther, sLenOther); - s[sLen + sLenOther] = '\0'; sLen += sLenOther; - } else { - // Grow the buffer bigger than really needed, to have room for other appends - char *sNew = new char[lenNew + sizeGrowth + 1]; - if (sNew) { - if (s) { - memcpy(sNew, s, sLen); - delete []s; - } - s = sNew; - sSize = lenNew + sizeGrowth; - if (lenSep) { - s[sLen] = sep; - sLen++; - } - strncpy(&s[sLen], sOther, sLenOther); - sNew[sLen + sLenOther] = '\0'; - sLen += sLenOther; - } + s[sLen] = '\0'; } return *this; } - SString &operator +=(const char *sOther) { - return append(sOther, -1); + SString &operator+=(const char *sOther) { + return append(sOther, static_cast(measure_length)); } - SString &operator +=(const SString &sOther) { + SString &operator+=(const SString &sOther) { return append(sOther.s, sOther.sSize); } - SString &operator +=(char ch) { + SString &operator+=(char ch) { return append(&ch, 1); } - SString &appendwithseparator(const char* sOther, char sep) { + SString &appendwithseparator(const char *sOther, char sep) { return append(sOther, strlen(sOther), sep); } + SString &insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther=measure_length) { + if (!sOther) { + return *this; + } + if (sLenOther == measure_length) { + sLenOther = strlen(sOther); + } + lenpos_t lenNew = sLen + sLenOther; + // Conservative about growing the buffer: don't do it, unless really needed + if ((lenNew + 1 < sSize) || grow(lenNew)) { + lenpos_t moveChars = sLen - pos + 1; + for (lenpos_t i = moveChars; i > 0; i--) { + s[pos + sLenOther + i - 1] = s[pos + i - 1]; + } + memcpy(s + pos, sOther, sLenOther); + sLen = lenNew; + } + return *this; + } + /** Remove @a len characters from the @a pos position, included. + * Characters at pos + len and beyond replace characters at pos. + * If @a len is 0, or greater than the length of the string + * starting at @a pos, the string is just truncated at @a pos. + */ + void remove(lenpos_t pos, lenpos_t len) { + if (len < 1 || pos + len >= sLen) { + s[pos] = '\0'; + sLen = pos; + } else { + for (lenpos_t i = pos; i < sLen - len + 1; i++) { + s[i] = s[i+len]; + } + sLen -= len; + } + } + /** Read an integral numeric value from the string. */ int value() const { if (s) return atoi(s); else return 0; } - void substitute(char find, char replace) { + int search(const char *sFind, lenpos_t start=0) { + if (start < sLen) { + const char *sFound = strstr(s + start, sFind); + if (sFound) { + return sFound - s; + } + } + return -1; + } + bool contains(const char *sFind) { + return search(sFind) >= 0; + } + int substitute(char chFind, char chReplace) { + int c = 0; char *t = s; while (t) { - t = strchr(t, find); + t = strchr(t, chFind); if (t) { - *t = replace; + *t = chReplace; t++; + c++; } } + return c; + } + int substitute(const char *sFind, const char *sReplace) { + int c = 0; + lenpos_t lenFind = strlen(sFind); + lenpos_t lenReplace = strlen(sReplace); + int posFound = search(sFind); + while (posFound >= 0) { + remove(posFound, lenFind); + insert(posFound, sReplace, lenReplace); + posFound = search(sFind, posFound + lenReplace); + c++; + } + return c; + } + int remove(const char *sFind) { + return substitute(sFind, ""); + } + /** + * Duplicate a C string. + * Allocate memory of the given size, or big enough to fit the string if length isn't given; + * then copy the given string in the allocated memory. + * @return the pointer to the new string + */ + static char *StringAllocate( + const char *s, ///< The string to duplicate + lenpos_t len=measure_length) ///< The length of memory to allocate. Optional. + { + if (s == 0) { + return 0; + } + if (len == measure_length) { + len = strlen(s); + } + char *sNew = new char[len + 1]; + if (sNew) { + strncpy(sNew, s, len); + sNew[len] = '\0'; + } + return sNew; } }; +/** + * Duplicate a C string. + * Allocate memory of the given size, or big enough to fit the string if length isn't given; + * then copy the given string in the allocated memory. + * @return the pointer to the new string + */ +inline char *StringDup( + const char *s, ///< The string to duplicate + SString::lenpos_t len=SString::measure_length) ///< The length of memory to allocate. Optional. +{ + return SString::StringAllocate(s, len); +} + #endif diff --git a/contrib/src/stc/scintilla/include/SciLexer.h b/contrib/src/stc/scintilla/include/SciLexer.h index 680cb15138..fb77a702e0 100644 --- a/contrib/src/stc/scintilla/include/SciLexer.h +++ b/contrib/src/stc/scintilla/include/SciLexer.h @@ -2,7 +2,7 @@ /** @file SciLexer.h ** Interface to the added lexer functions in the SciLexer version of the edit control. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. // Most of this file is automatically generated from the Scintilla.iface interface definition @@ -41,6 +41,12 @@ #define SCLEX_EIFFELKW 24 #define SCLEX_TCL 25 #define SCLEX_NNCRONTAB 26 +#define SCLEX_BULLANT 27 +#define SCLEX_VBSCRIPT 28 +#define SCLEX_ASP 29 +#define SCLEX_PHP 30 +#define SCLEX_BAAN 31 +#define SCLEX_MATLAB 32 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -75,6 +81,15 @@ #define SCE_C_WORD2 16 #define SCE_C_COMMENTDOCKEYWORD 17 #define SCE_C_COMMENTDOCKEYWORDERROR 18 +#define SCE_B_DEFAULT 0 +#define SCE_B_COMMENT 1 +#define SCE_B_NUMBER 2 +#define SCE_B_KEYWORD 3 +#define SCE_B_STRING 4 +#define SCE_B_PREPROCESSOR 5 +#define SCE_B_OPERATOR 6 +#define SCE_B_IDENTIFIER 7 +#define SCE_B_DATE 8 #define SCE_H_DEFAULT 0 #define SCE_H_TAG 1 #define SCE_H_TAGUNKNOWN 2 @@ -233,6 +248,11 @@ #define SCE_LUA_OPERATOR 10 #define SCE_LUA_IDENTIFIER 11 #define SCE_LUA_STRINGEOL 12 +#define SCE_LUA_WORD2 13 +#define SCE_LUA_WORD3 14 +#define SCE_LUA_WORD4 15 +#define SCE_LUA_WORD5 16 +#define SCE_LUA_WORD6 17 #define SCE_ERR_DEFAULT 0 #define SCE_ERR_PYTHON 1 #define SCE_ERR_GCC 2 @@ -291,6 +311,17 @@ #define SCE_ADA_OPERATOR 6 #define SCE_ADA_IDENTIFIER 7 #define SCE_ADA_STRINGEOL 8 +#define SCE_BAAN_DEFAULT 0 +#define SCE_BAAN_COMMENT 1 +#define SCE_BAAN_COMMENTDOC 2 +#define SCE_BAAN_NUMBER 3 +#define SCE_BAAN_WORD 4 +#define SCE_BAAN_STRING 5 +#define SCE_BAAN_PREPROCESSOR 6 +#define SCE_BAAN_OPERATOR 7 +#define SCE_BAAN_IDENTIFIER 8 +#define SCE_BAAN_STRINGEOL 9 +#define SCE_BAAN_WORD2 10 #define SCE_LISP_DEFAULT 0 #define SCE_LISP_COMMENT 1 #define SCE_LISP_NUMBER 2 @@ -319,6 +350,14 @@ #define SCE_NNCRONTAB_STRING 8 #define SCE_NNCRONTAB_ENVIRONMENT 9 #define SCE_NNCRONTAB_IDENTIFIER 10 +#define SCE_MATLAB_DEFAULT 0 +#define SCE_MATLAB_COMMENT 1 +#define SCE_MATLAB_COMMAND 2 +#define SCE_MATLAB_NUMBER 3 +#define SCE_MATLAB_KEYWORD 4 +#define SCE_MATLAB_STRING 5 +#define SCE_MATLAB_OPERATOR 6 +#define SCE_MATLAB_IDENTIFIER 7 //--Autogenerated -- end of section automatically generated from Scintilla.iface #endif diff --git a/contrib/src/stc/scintilla/include/Scintilla.h b/contrib/src/stc/scintilla/include/Scintilla.h index abe1581a49..99b3ee0b1a 100644 --- a/contrib/src/stc/scintilla/include/Scintilla.h +++ b/contrib/src/stc/scintilla/include/Scintilla.h @@ -2,7 +2,7 @@ /** @file Scintilla.h ** Interface to the edit control. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. // Most of this file is automatically generated from the Scintilla.iface interface definition @@ -12,10 +12,11 @@ #define SCINTILLA_H #if PLAT_WIN -#ifdef STATIC_BUILD -void Scintilla_RegisterClasses(HINSTANCE hInstance); -#endif +// Return false on failure: +bool Scintilla_RegisterClasses(void *hInstance); +bool Scintilla_ReleaseResources(); #endif +int Scintilla_LinkLexers(); // Here should be placed typedefs for uptr_t, an unsigned integer type large enough to // hold a pointer and sptr_t, a signed integer large enough to hold a pointer. @@ -99,6 +100,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_MARK_CIRCLEPLUSCONNECTED 19 #define SC_MARK_CIRCLEMINUS 20 #define SC_MARK_CIRCLEMINUSCONNECTED 21 +#define SC_MARK_BACKGROUND 22 #define SC_MARK_CHARACTER 10000 #define SC_MARKNUM_FOLDEREND 25 #define SC_MARKNUM_FOLDEROPENMID 26 @@ -107,6 +109,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_MARKNUM_FOLDERSUB 29 #define SC_MARKNUM_FOLDER 30 #define SC_MARKNUM_FOLDEROPEN 31 +#define SC_MASK_FOLDERS 0xFE000000 #define SCI_MARKERDEFINE 2040 #define SCI_MARKERSETFORE 2041 #define SCI_MARKERSETBACK 2042 @@ -187,10 +190,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define INDIC_TT 2 #define INDIC_DIAGONAL 3 #define INDIC_STRIKE 4 -#define INDIC0_MASK 32 -#define INDIC1_MASK 64 -#define INDIC2_MASK 128 -#define INDICS_MASK INDIC0_MASK | INDIC1_MASK | INDIC2_MASK +#define INDIC0_MASK 0x20 +#define INDIC1_MASK 0x40 +#define INDIC2_MASK 0x80 +#define INDICS_MASK 0xE0 #define SCI_INDICSETSTYLE 2080 #define SCI_INDICGETSTYLE 2081 #define SCI_INDICSETFORE 2082 @@ -204,6 +207,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETCARETLINEVISIBLE 2096 #define SCI_GETCARETLINEBACK 2097 #define SCI_SETCARETLINEBACK 2098 +#define SCI_STYLESETCHANGEABLE 2099 #define SCI_AUTOCSHOW 2100 #define SCI_AUTOCCANCEL 2101 #define SCI_AUTOCACTIVE 2102 @@ -223,6 +227,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_USERLISTSHOW 2117 #define SCI_AUTOCSETAUTOHIDE 2118 #define SCI_AUTOCGETAUTOHIDE 2119 +#define SCI_AUTOCSETDROPRESTOFWORD 2270 +#define SCI_AUTOCGETDROPRESTOFWORD 2271 #define SCI_SETINDENT 2122 #define SCI_GETINDENT 2123 #define SCI_SETUSETABS 2124 @@ -341,6 +347,18 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_TIME_FOREVER 10000000 #define SCI_SETMOUSEDWELLTIME 2264 #define SCI_GETMOUSEDWELLTIME 2265 +#define SCI_WORDSTARTPOSITION 2266 +#define SCI_WORDENDPOSITION 2267 +#define SC_WRAP_NONE 0 +#define SC_WRAP_WORD 1 +#define SCI_SETWRAPMODE 2268 +#define SCI_GETWRAPMODE 2269 +#define SC_CACHE_NONE 0 +#define SC_CACHE_CARET 1 +#define SC_CACHE_PAGE 2 +#define SC_CACHE_DOCUMENT 3 +#define SCI_SETLAYOUTCACHE 2272 +#define SCI_GETLAYOUTCACHE 2273 #define SCI_LINEDOWN 2300 #define SCI_LINEDOWNEXTEND 2301 #define SCI_LINEUP 2302 @@ -385,6 +403,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_UPPERCASE 2341 #define SCI_LINESCROLLDOWN 2342 #define SCI_LINESCROLLUP 2343 +#define SCI_DELETEBACKNOTLINE 2344 #define SCI_MOVECARETINSIDEVIEW 2401 #define SCI_LINELENGTH 2350 #define SCI_BRACEHIGHLIGHT 2351 @@ -432,6 +451,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_CURSORWAIT 3 #define SCI_SETCURSOR 2386 #define SCI_GETCURSOR 2387 +#define SCI_SETCONTROLCHARSYMBOL 2388 +#define SCI_GETCONTROLCHARSYMBOL 2389 #define SCI_WORDPARTLEFT 2390 #define SCI_WORDPARTLEFTEXTEND 2391 #define SCI_WORDPARTRIGHT 2392 @@ -441,6 +462,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETVISIBLEPOLICY 2394 #define SCI_DELLINELEFT 2395 #define SCI_DELLINERIGHT 2396 +#define SCI_SETXOFFSET 2397 +#define SCI_GETXOFFSET 2398 #define SCI_GRABFOCUS 2400 #define SCI_STARTRECORD 3001 #define SCI_STOPRECORD 3002 @@ -493,12 +516,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCN_KEY 2005 #define SCN_DOUBLECLICK 2006 #define SCN_UPDATEUI 2007 -#define SCN_CHECKBRACE 2007 #define SCN_MODIFIED 2008 #define SCN_MACRORECORD 2009 #define SCN_MARGINCLICK 2010 #define SCN_NEEDSHOWN 2011 -#define SCN_POSCHANGED 2012 #define SCN_PAINTED 2013 #define SCN_USERLISTSELECTION 2014 #define SCN_URIDROPPED 2015 @@ -528,7 +549,7 @@ struct TextToFind { #ifdef PLATFORM_H -// This structure is used in printing and requires some of the graphics types +// This structure is used in printing and requires some of the graphics types // from Platform.h. Not needed by most client code. struct RangeToFormat { @@ -545,7 +566,7 @@ struct NotifyHeader { // hwndFrom is really an environment specifc window handle or pointer // but most clients of Scintilla.h do not have this type visible. //WindowID hwndFrom; - void *hwndFrom; + void *hwndFrom; unsigned int idFrom; unsigned int code; }; @@ -571,20 +592,15 @@ struct SCNotification { int y; // SCN_DWELLSTART, SCN_DWELLEND }; -#define SC_MASK_FOLDERS ((1< +## The License.txt file describes the conditions under which this software may be distributed. + ## A line starting with ## is a pure comment and should be stripped by readers. ## A line starting with #! is for future shbang use ## A line starting with # followed by a space is a documentation comment and refers @@ -25,6 +28,9 @@ ## The syntax for evt is [=[,]*]) ## Feature names that contain an underscore are defined by Windows, so in these ## cases, using the Windows definition is preferred where available. +## The feature numbers are stable so features will not be renumbered. +## Features may be removed but they will go through a period of deprecation +## before removal which is signalled by moving them into the Deprecated category. ## Types: ## void @@ -35,20 +41,27 @@ ## string -> pointer to const character ## stringresult -> pointer to character ## cells -> pointer to array of cells, each cell containing a style byte and character byte -## charrange -> range of a min and a max position -## charrangeresult -> like charrange, but output param -## textrange -> charrange + output string +## textrange -> range of a min and a max position with an output string ## findtext -> searchrange, text -> foundposition -## findtextex -> searchrange ## keymod -> integer containing key in low half and modifiers in high half -## countedstring ## formatrange +## Types no longer used: +## findtextex -> searchrange +## charrange -> range of a min and a max position +## charrangeresult -> like charrange, but output param +## countedstring ## point -> x,y ## pointresult -> like point, but output param ## rectangle -> left,top,right,bottom ## Client code should ignore definitions containing types it does not understand, except ## for possibly #defining the constants +## String arguments may contain NUL ('\0') characters where the calls provide a length +## argument and retrieve NUL characters. All retrieved strings except for those retrieved +## by GetLine also have a NUL appended but client code should calculate the size that +## will be returned rather than relying upon the NUL whenever possible. Allow for the +## extra NUL character when allocating buffers. + cat Basics ################################################ @@ -229,6 +242,9 @@ val SC_MARK_CIRCLEPLUSCONNECTED=19 val SC_MARK_CIRCLEMINUS=20 val SC_MARK_CIRCLEMINUSCONNECTED=21 +# Invisible mark that only sets the line background color +val SC_MARK_BACKGROUND=22 + val SC_MARK_CHARACTER=10000 # Markers used for outlining column @@ -240,6 +256,8 @@ val SC_MARKNUM_FOLDERSUB=29 val SC_MARKNUM_FOLDER=30 val SC_MARKNUM_FOLDEROPEN=31 +val SC_MASK_FOLDERS=0xFE000000 + # Set the symbol used for a particular marker number. fun void MarkerDefine=2040(int markerNumber, int markerSymbol) @@ -249,8 +267,8 @@ fun void MarkerSetFore=2041(int markerNumber, colour fore) # Set the background colour used for a particular marker number. fun void MarkerSetBack=2042(int markerNumber, colour back) -# Add a marker to a line. -fun void MarkerAdd=2043(int line, int markerNumber) +# Add a marker to a line, returning an ID which can be used to find or delete the marker. +fun int MarkerAdd=2043(int line, int markerNumber) # Delete a marker from a line fun void MarkerDelete=2044(int line, int markerNumber) @@ -413,11 +431,10 @@ val INDIC_SQUIGGLE=1 val INDIC_TT=2 val INDIC_DIAGONAL=3 val INDIC_STRIKE=4 -val INDIC0_MASK=32 -val INDIC1_MASK=64 -val INDIC2_MASK=128 -val INDICS_MASK=224 -##INDIC0_MASK | INDIC1_MASK | INDIC2_MASK +val INDIC0_MASK=0x20 +val INDIC1_MASK=0x40 +val INDIC2_MASK=0x80 +val INDICS_MASK=0xE0 # Set an indicator to plain, squiggle or TT. set void IndicSetStyle=2080(int indic, int style) @@ -451,7 +468,7 @@ get int GetMaxLineState=2094(,) # Is the background of the line containing the caret in a different colour? get bool GetCaretLineVisible=2095(,) -# Display the background of the line containing the caret in a different colour. +# Dsplay the background of the line containing the caret in a different colour. set void SetCaretLineVisible=2096(bool show,) # Get the colour of the background of the line containing the caret. @@ -460,6 +477,10 @@ get colour GetCaretLineBack=2097(,) # Set the colour of the background of the line containing the caret. set void SetCaretLineBack=2098(colour back,) +# Set a style to be changeable or not (read only). +# Experimental feature, currently buggy. +set void StyleSetChangeable=2099(int style, bool changeable) + # Display a auto-completion list. # The lenEntered parameter indicates how many characters before # the caret should be used to provide context. @@ -498,7 +519,8 @@ set void AutoCSetCancelAtStart=2110(bool cancel,) # Retrieve whether auto-completion cancelled by backspacing before start. get bool AutoCGetCancelAtStart=2111(,) -# Define a set of character that when typed fills up the selected word. +# Define a set of characters that when typed will cause the autocompletion to +# choose the selected item. set void AutoCSetFillUps=2112(, string characterSet) # Should a single item auto-completion list automatically choose the item. @@ -522,6 +544,12 @@ set void AutoCSetAutoHide=2118(bool autoHide,) # Retrieve whether or not autocompletion is hidden automatically when nothing matches get bool AutoCGetAutoHide=2119(,) +# Set whether or not autocompletion deletes any word characters after the inserted text upon completion +set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,) + +# Retrieve whether or not autocompletion deletes any word characters after the inserted text upon completion +get bool AutoCGetDropRestOfWord=2271(,) + # Set the number of spaces used for one level of indentation. set void SetIndent=2122(int indentSize,) @@ -878,6 +906,32 @@ set void SetMouseDwellTime=2264(int periodMilliseconds,) # Retrieve the time the mouse must sit still to generate a mouse dwell event get int GetMouseDwellTime=2265(,) +# Get position of start of word +fun int WordStartPosition=2266(position pos, bool onlyWordCharacters) + +# Get position of end of word +fun int WordEndPosition=2267(position pos, bool onlyWordCharacters) + +val SC_WRAP_NONE=0 +val SC_WRAP_WORD=1 + +# Sets whether text is word wrapped +set void SetWrapMode=2268(int mode,) + +# Retrieve whether text is word wrapped +get int GetWrapMode=2269(,) + +val SC_CACHE_NONE=0 +val SC_CACHE_CARET=1 +val SC_CACHE_PAGE=2 +val SC_CACHE_DOCUMENT=3 + +# Sets the degree of caching of layout information +set void SetLayoutCache=2272(int mode,) + +# Retrieve the degree of caching of layout information +get int GetLayoutCache=2273(,) + ## Start of key messages # Move caret down one line. fun void LineDown=2300(,) @@ -1014,6 +1068,10 @@ fun void LineScrollDown=2342(,) # Scroll the document up, keeping the caret visible. fun void LineScrollUp=2343(,) +# Delete the selection or if no selection, the character before the caret. +# Will not delete the chraacter before at the start of a line. +fun void DeleteBackNotLine=2344(,) + # Move the caret inside current view if it's not there already fun void MoveCaretInsideView=2401(,) @@ -1146,6 +1204,12 @@ set void SetCursor=2386(int cursorType,) # Get cursor type get int GetCursor=2387(,) +# Change the way control characters are displayed: +# If symbol is < 32, keep the drawn way, else, use the given character +set void SetControlCharSymbol=2388(int symbol,) +# Get the way control characters are displayed +get int GetControlCharSymbol=2389(,) + # Move to the previous change in capitalistion fun void WordPartLeft=2390(,) # Move to the previous change in capitalistion extending selection to new caret position. @@ -1167,6 +1231,10 @@ fun void DelLineLeft=2395(,) # Delete forwards from the current position to the end of the line fun void DelLineRight=2396(,) +# Get and Set the xOffset (ie, horizonal scroll position) +set void SetXOffset=2397(int newOffset,) +get int GetXOffset=2398(,) + # Set the focus to this Scintilla widget. # GTK+ Specific fun void GrabFocus=2400(,) @@ -1273,6 +1341,13 @@ val SCLEX_EIFFEL=23 val SCLEX_EIFFELKW=24 val SCLEX_TCL=25 val SCLEX_NNCRONTAB=26 +val SCLEX_BULLANT=27 +val SCLEX_VBSCRIPT=28 +val SCLEX_ASP=29 +val SCLEX_PHP=30 +val SCLEX_BAAN=31 +val SCLEX_MATLAB=32 + # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. val SCLEX_AUTOMATIC=1000 @@ -1291,7 +1366,7 @@ val SCE_P_OPERATOR=10 val SCE_P_IDENTIFIER=11 val SCE_P_COMMENTBLOCK=12 val SCE_P_STRINGEOL=13 -# Lexical states for SCLEX_CPP, SCLEX_VB +# Lexical states for SCLEX_CPP val SCE_C_DEFAULT=0 val SCE_C_COMMENT=1 val SCE_C_COMMENTLINE=2 @@ -1311,6 +1386,16 @@ val SCE_C_COMMENTLINEDOC=15 val SCE_C_WORD2=16 val SCE_C_COMMENTDOCKEYWORD=17 val SCE_C_COMMENTDOCKEYWORDERROR=18 +# Lexical states for SCLEX_VB, SCLEX_VBSCRIPT +val SCE_B_DEFAULT=0 +val SCE_B_COMMENT=1 +val SCE_B_NUMBER=2 +val SCE_B_KEYWORD=3 +val SCE_B_STRING=4 +val SCE_B_PREPROCESSOR=5 +val SCE_B_OPERATOR=6 +val SCE_B_IDENTIFIER=7 +val SCE_B_DATE=8 # Lexical states for SCLEX_HTML, SCLEX_XML val SCE_H_DEFAULT=0 val SCE_H_TAG=1 @@ -1484,6 +1569,11 @@ val SCE_LUA_PREPROCESSOR=9 val SCE_LUA_OPERATOR=10 val SCE_LUA_IDENTIFIER=11 val SCE_LUA_STRINGEOL=12 +val SCE_LUA_WORD2=13 +val SCE_LUA_WORD3=14 +val SCE_LUA_WORD4=15 +val SCE_LUA_WORD5=16 +val SCE_LUA_WORD6=17 # Lexical states for SCLEX_ERRORLIST val SCE_ERR_DEFAULT=0 val SCE_ERR_PYTHON=1 @@ -1548,6 +1638,18 @@ val SCE_ADA_CHARACTER=5 val SCE_ADA_OPERATOR=6 val SCE_ADA_IDENTIFIER=7 val SCE_ADA_STRINGEOL=8 +# Lexical states for SCLEX_BAAN +val SCE_BAAN_DEFAULT=0 +val SCE_BAAN_COMMENT=1 +val SCE_BAAN_COMMENTDOC=2 +val SCE_BAAN_NUMBER=3 +val SCE_BAAN_WORD=4 +val SCE_BAAN_STRING=5 +val SCE_BAAN_PREPROCESSOR=6 +val SCE_BAAN_OPERATOR=7 +val SCE_BAAN_IDENTIFIER=8 +val SCE_BAAN_STRINGEOL=9 +val SCE_BAAN_WORD2=10 # Lexical states for SCLEX_LISP val SCE_LISP_DEFAULT=0 val SCE_LISP_COMMENT=1 @@ -1579,6 +1681,15 @@ val SCE_NNCRONTAB_NUMBER=7 val SCE_NNCRONTAB_STRING=8 val SCE_NNCRONTAB_ENVIRONMENT=9 val SCE_NNCRONTAB_IDENTIFIER=10 +# Lexical states for SCLEX_MATLAB +val SCE_MATLAB_DEFAULT=0 +val SCE_MATLAB_COMMENT=1 +val SCE_MATLAB_COMMAND=2 +val SCE_MATLAB_NUMBER=3 +val SCE_MATLAB_KEYWORD=4 +val SCE_MATLAB_STRING=5 +val SCE_MATLAB_OPERATOR=6 +val SCE_MATLAB_IDENTIFIER=7 # Events @@ -1591,14 +1702,10 @@ evt void ModifyAttemptRO=2004(void) evt void Key=2005(int ch, int modifiers) evt void DoubleClick=2006(void) evt void UpdateUI=2007(void) -# The old name for SCN_UPDATEUI -val SCN_CHECKBRACE=2007 evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev) -# Optional module for macro recording evt void MacroRecord=2009(int message, int wParam, int lParam) evt void MarginClick=2010(int modifiers, int position, int margin) evt void NeedShown=2011(int position, int length) -evt void PosChanged=2012(int position) evt void Painted=2013(void) evt void UserListSelection=2014(int listType, string text) evt void URIDropped=2015(string text) @@ -1606,3 +1713,7 @@ evt void DwellStart=2016(int position) evt void DwellEnd=2017(int position) cat Deprecated + +# The old name for SCN_UPDATEUI +val SCN_CHECKBRACE=2007 +evt void PosChanged=2012(int position) diff --git a/contrib/src/stc/scintilla/src/AutoComplete.cxx b/contrib/src/stc/scintilla/src/AutoComplete.cxx index 7f7412e43f..48aaee38ae 100644 --- a/contrib/src/stc/scintilla/src/AutoComplete.cxx +++ b/contrib/src/stc/scintilla/src/AutoComplete.cxx @@ -2,7 +2,7 @@ /** @file AutoComplete.cxx ** Defines the auto completion list box. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -22,7 +22,8 @@ AutoComplete::AutoComplete() : posStart(0), startLen(0), cancelAtStartPos(true), - autoHide(true) { + autoHide(true), + dropRestOfWord(false) { stopChars[0] = '\0'; fillUpChars[0] = '\0'; } diff --git a/contrib/src/stc/scintilla/src/AutoComplete.h b/contrib/src/stc/scintilla/src/AutoComplete.h index 79d4675291..622a5666ec 100644 --- a/contrib/src/stc/scintilla/src/AutoComplete.h +++ b/contrib/src/stc/scintilla/src/AutoComplete.h @@ -2,7 +2,7 @@ /** @file AutoComplete.h ** Defines the auto completion list box. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef AUTOCOMPLETE_H @@ -25,6 +25,7 @@ public: /// Should autocompletion be canceled if editor's currentPos <= startPos? bool cancelAtStartPos; bool autoHide; + bool dropRestOfWord; AutoComplete(); ~AutoComplete(); diff --git a/contrib/src/stc/scintilla/src/CallTip.cxx b/contrib/src/stc/scintilla/src/CallTip.cxx index 3422de6969..4b4ae0c7ce 100644 --- a/contrib/src/stc/scintilla/src/CallTip.cxx +++ b/contrib/src/stc/scintilla/src/CallTip.cxx @@ -21,11 +21,11 @@ CallTip::CallTip() { 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); + colourBG.desired = ColourDesired(0xff, 0xff, 0xff); + colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80); + colourSel.desired = ColourDesired(0, 0, 0x80); + colourShade.desired = ColourDesired(0, 0, 0); + colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0); } CallTip::~CallTip() { @@ -81,7 +81,7 @@ void CallTip::PaintCT(Surface *surfaceWindow) { rcClient.left = x; rcClient.top = ytext - ascent - 1; rcClient.right = xEnd; - surfaceWindow->DrawText(rcClient, font, ytext, + surfaceWindow->DrawTextNoClip(rcClient, font, ytext, chunkVal, thisStartHighlight, colourUnSel.allocated, colourBG.allocated); x = xEnd; @@ -91,7 +91,7 @@ void CallTip::PaintCT(Surface *surfaceWindow) { rcClient.top = ytext; rcClient.left = x; rcClient.right = xEnd; - surfaceWindow->DrawText(rcClient, font, ytext, + surfaceWindow->DrawTextNoClip(rcClient, font, ytext, chunkVal + thisStartHighlight, thisEndHighlight - thisStartHighlight, colourSel.allocated, colourBG.allocated); x = xEnd; @@ -100,7 +100,7 @@ void CallTip::PaintCT(Surface *surfaceWindow) { chunkLength - thisEndHighlight); rcClient.left = x; rcClient.right = xEnd; - surfaceWindow->DrawText(rcClient, font, ytext, + surfaceWindow->DrawTextNoClip(rcClient, font, ytext, chunkVal + thisEndHighlight, chunkLength - thisEndHighlight, colourUnSel.allocated, colourBG.allocated); chunkVal = chunkEnd + 1; @@ -117,21 +117,25 @@ void CallTip::PaintCT(Surface *surfaceWindow) { } PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, - const char *faceName, int size) { - Surface surfaceMeasure; - surfaceMeasure.Init(); - int deviceHeight = surfaceMeasure.DeviceHeightFont(size); - font.Create(faceName, SC_CHARSET_DEFAULT, deviceHeight, false, false); + const char *faceName, int size, bool unicodeMode_) { if (val) delete []val; val = new char[strlen(defn) + 1]; if (!val) return PRectangle(); strcpy(val, defn); + unicodeMode = unicodeMode_; + Surface *surfaceMeasure = Surface::Allocate(); + if (!surfaceMeasure) + return PRectangle(); + surfaceMeasure->Init(); + surfaceMeasure->SetUnicodeMode(unicodeMode); startHighlight = 0; endHighlight = 0; inCallTipMode = true; posStartCallTip = pos; + int deviceHeight = surfaceMeasure->DeviceHeightFont(size); + font.Create(faceName, SC_CHARSET_DEFAULT, deviceHeight, false, false); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! int width = 0; @@ -139,16 +143,17 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, const char *newline; const char *look = val; while ((newline = strchr(look, '\n')) != NULL) { - int thisWidth = surfaceMeasure.WidthText(font, look, newline - look); + 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)); + int lastWidth = surfaceMeasure->WidthText(font, look, strlen(look)); width = Platform::Maximum(width, lastWidth) + 10; - int lineHeight = surfaceMeasure.Height(font); + 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; + int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2; + delete surfaceMeasure; return PRectangle(pt.x -5, pt.y + 1, pt.x + width - 5, pt.y + 1 + height); } diff --git a/contrib/src/stc/scintilla/src/CallTip.h b/contrib/src/stc/scintilla/src/CallTip.h index b38a4840ab..9f5025f63b 100644 --- a/contrib/src/stc/scintilla/src/CallTip.h +++ b/contrib/src/stc/scintilla/src/CallTip.h @@ -29,6 +29,7 @@ public: ColourPair colourSel; ColourPair colourShade; ColourPair colourLight; + bool unicodeMode; CallTip(); ~CallTip(); @@ -40,7 +41,7 @@ public: /// 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); + const char *faceName, int size, bool unicodeMode_); void CallTipCancel(); diff --git a/contrib/src/stc/scintilla/src/ContractionState.cxx b/contrib/src/stc/scintilla/src/ContractionState.cxx index 1f14696650..5b36b2cadf 100644 --- a/contrib/src/stc/scintilla/src/ContractionState.cxx +++ b/contrib/src/stc/scintilla/src/ContractionState.cxx @@ -11,8 +11,9 @@ OneLine::OneLine() { displayLine = 0; - docLine = 0; + //docLine = 0; visible = true; + height = 1; expanded = true; } @@ -22,6 +23,8 @@ ContractionState::ContractionState() { linesInDoc = 1; linesInDisplay = 1; valid = false; + docLines = 0; + sizeDocLines = 0; } ContractionState::~ContractionState() { @@ -30,14 +33,34 @@ ContractionState::~ContractionState() { void ContractionState::MakeValid() const { if (!valid) { - // Could be cleverer by keeping the index of the last still valid entry + // Could be cleverer by keeping the index of the last still valid entry // rather than invalidating all. - int lineDisplay = 0; + linesInDisplay = 0; + for (int lineInDoc=0; lineInDoc= linesInDisplay) - return linesInDoc-1; + return linesInDoc; if (size == 0) return lineDisplay; MakeValid(); - return lines[lineDisplay].docLine; + if (docLines) { // Valid allocation + return docLines[lineDisplay]; + } else { + return 0; + } } void ContractionState::Grow(int sizeNew) { @@ -113,13 +146,15 @@ void ContractionState::InsertLines(int lineDoc, int lineCount) { Grow(linesInDoc + lineCount + growSize); } linesInDoc += lineCount; - linesInDisplay += lineCount; for (int i = linesInDoc; i >= lineDoc + lineCount; i--) { lines[i].visible = lines[i - lineCount].visible; + lines[i].height = lines[i - lineCount].height; + linesInDisplay += lines[i].height; lines[i].expanded = lines[i - lineCount].expanded; } for (int d=0;d lineDocEnd) - return false; + if (lineDocStart == 0) + lineDocStart++; + if (lineDocStart > lineDocEnd) + return false; if (size == 0) { Grow(linesInDoc + growSize); } @@ -170,7 +205,7 @@ bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) { for (int line=lineDocStart; line <= lineDocEnd; line++) { if (lines[line].visible != visible) { - delta += visible ? 1 : -1; + delta += visible ? lines[line].height : -lines[line].height; lines[line].visible = visible; } } @@ -181,7 +216,7 @@ bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible } bool ContractionState::GetExpanded(int lineDoc) const { - if (size == 0) + if (size == 0) return true; if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { return lines[lineDoc].expanded; @@ -192,6 +227,11 @@ bool ContractionState::GetExpanded(int lineDoc) const { bool ContractionState::SetExpanded(int lineDoc, bool expanded) { if (size == 0) { + if (expanded) { + // If in completely expanded state then setting + // one line to expanded has no effect. + return false; + } Grow(linesInDoc + growSize); } if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { @@ -203,6 +243,38 @@ bool ContractionState::SetExpanded(int lineDoc, bool expanded) { return false; } +int ContractionState::GetHeight(int lineDoc) const { + if (size == 0) + return 1; + if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { + return lines[lineDoc].height; + } else { + return 1; + } +} + +// Set the number of display lines needed for this line. +// Return true if this is a change. +bool ContractionState::SetHeight(int lineDoc, int height) { + if (lineDoc > linesInDoc) + return false; + if (size == 0) { + if (height == 1) { + // If in completely expanded state then all lines + // assumed to have height of one so no effect here. + return false; + } + Grow(linesInDoc + growSize); + } + if (lines[lineDoc].height != height) { + lines[lineDoc].height = height; + valid = false; + return true; + } else { + return false; + } +} + void ContractionState::ShowAll() { delete []lines; lines = 0; diff --git a/contrib/src/stc/scintilla/src/ContractionState.h b/contrib/src/stc/scintilla/src/ContractionState.h index 0d7881c7b2..e15ee3bbe6 100644 --- a/contrib/src/stc/scintilla/src/ContractionState.h +++ b/contrib/src/stc/scintilla/src/ContractionState.h @@ -13,10 +13,11 @@ class OneLine { public: int displayLine; ///< Position within set of visible lines - int docLine; ///< Inverse of @a displayLine + //int docLine; ///< Inverse of @a displayLine + int height; ///< Number of display lines needed to show all of the line bool visible; bool expanded; - + OneLine(); virtual ~OneLine() {} }; @@ -27,33 +28,38 @@ class ContractionState { void Grow(int sizeNew); enum { growSize = 4000 }; int linesInDoc; - int linesInDisplay; + mutable int linesInDisplay; mutable OneLine *lines; int size; + mutable int *docLines; + mutable int sizeDocLines; mutable bool valid; void MakeValid() const; public: ContractionState(); virtual ~ContractionState(); - + void Clear(); - - int LinesInDoc() const; - int LinesDisplayed() const; + + 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); - void ShowAll(); + int GetHeight(int lineDoc) const; + bool SetHeight(int lineDoc, int height); + + void ShowAll(); }; #endif diff --git a/contrib/src/stc/scintilla/src/Document.cxx b/contrib/src/stc/scintilla/src/Document.cxx index abbb87d5dc..3d3e5a51dd 100644 --- a/contrib/src/stc/scintilla/src/Document.cxx +++ b/contrib/src/stc/scintilla/src/Document.cxx @@ -2,7 +2,7 @@ /** @file Document.cxx ** Text document that handles notifications, DBCS, styling, words and end of line. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -19,7 +19,7 @@ #include "RESearch.h" // This is ASCII specific but is safe with chars >= 0x80 -inline bool isspacechar(unsigned char ch) { +static inline bool isspacechar(unsigned char ch) { return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); } @@ -34,10 +34,9 @@ Document::Document() { stylingBits = 5; stylingBitsMask = 0x1F; stylingMask = 0; - for (int ch = 0; ch < 256; ch++) { - wordchars[ch] = isalnum(ch) || ch == '_'; - } + SetWordChars(0); endStyled = 0; + styleClock = 0; enteredCount = 0; enteredReadOnlyCount = 0; tabInChars = 8; @@ -219,7 +218,6 @@ bool Document::IsCrLf(int pos) { return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n'); } -#if PLAT_WIN bool Document::IsDBCS(int pos) { if (dbcsCodePage) { if (SC_CP_UTF8 == dbcsCodePage) { @@ -232,7 +230,7 @@ bool Document::IsDBCS(int pos) { while (startLine > 0 && cb.CharAt(startLine) != '\r' && cb.CharAt(startLine) != '\n') startLine--; while (startLine <= pos) { - if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) { + if (Platform::IsDBCSLeadByte(dbcsCodePage, cb.CharAt(startLine))) { startLine++; if (startLine >= pos) return true; @@ -243,13 +241,6 @@ bool Document::IsDBCS(int pos) { } return false; } -#else -// PLAT_GTK or PLAT_WX -// TODO: support DBCS under GTK+ and WX -bool Document::IsDBCS(int) { - return false; -} -#endif int Document::LenChar(int pos) { if (IsCrLf(pos)) { @@ -302,7 +293,6 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { // Not between CR and LF -#if PLAT_WIN if (dbcsCodePage) { if (SC_CP_UTF8 == dbcsCodePage) { unsigned char ch = static_cast(cb.CharAt(pos)); @@ -324,12 +314,11 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { while (startLine < pos) { if (atLeadByte) atLeadByte = false; - else if (IsDBCSLeadByteEx(dbcsCodePage, cb.CharAt(startLine))) + else if (Platform::IsDBCSLeadByte(dbcsCodePage, cb.CharAt(startLine))) atLeadByte = true; else atLeadByte = false; startLine++; - //Platform::DebugPrintf("DBCS %s\n", atlead ? "D" : "-"); } @@ -342,7 +331,6 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { } } } -#endif return pos; } @@ -634,21 +622,46 @@ int Document::GetColumn(int pos) { int column = 0; int line = LineFromPosition(pos); if ((line >= 0) && (line < LinesTotal())) { - for (int i = LineStart(line);i < pos;i++) { + for (int i = LineStart(line);i < pos;) { char ch = cb.CharAt(i); - if (ch == '\t') + if (ch == '\t') { column = NextTab(column, tabInChars); - else if (ch == '\r') + i++; + } else if (ch == '\r') { return column; - else if (ch == '\n') + } else if (ch == '\n') { return column; - else + } else { column++; + i = MovePositionOutsideChar(i + 1, 1); + } } } return column; } +int Document::FindColumn(int line, int column) { + int position = LineStart(line); + int columnCurrent = 0; + if ((line >= 0) && (line < LinesTotal())) { + while (columnCurrent < column) { + char ch = cb.CharAt(position); + if (ch == '\t') { + columnCurrent = NextTab(columnCurrent, tabInChars); + position++; + } else if (ch == '\r') { + return position; + } else if (ch == '\n') { + return position; + } else { + columnCurrent++; + position = MovePositionOutsideChar(position + 1, 1); + } + } + } + return position; +} + void Document::Indent(bool forwards, int lineBottom, int lineTop) { // Dedent - suck white space off the front of the line to dedent by equivalent of a tab for (int line = lineBottom; line >= lineTop; line--) { @@ -700,72 +713,88 @@ void Document::ConvertLineEnds(int eolModeSet) { EndUndoAction(); } -bool Document::IsWordChar(unsigned char ch) { - if ((SC_CP_UTF8 == dbcsCodePage) && (ch > 0x80)) - return true; - return wordchars[ch]; +Document::charClassification Document::WordCharClass(unsigned char ch) { + if ((SC_CP_UTF8 == dbcsCodePage) && (ch >= 0x80)) + return ccWord; + return charClass[ch]; } -int Document::ExtendWordSelect(int pos, int delta) { +/** + * Used by commmands that want to select whole words. + * Finds the start of word at pos when delta < 0 or the end of the word when delta >= 0. + */ +int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) { + charClassification ccStart = ccWord; if (delta < 0) { - while (pos > 0 && IsWordChar(cb.CharAt(pos - 1))) + if (!onlyWordCharacters) + ccStart = WordCharClass(cb.CharAt(pos-1)); + while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) pos--; } else { - while (pos < (Length()) && IsWordChar(cb.CharAt(pos))) + if (!onlyWordCharacters) + ccStart = WordCharClass(cb.CharAt(pos)); + while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart)) pos++; } return pos; } +/** + * Find the start of the next word in either a forward (delta >= 0) or backwards direction + * (delta < 0). + * This is looking for a transition between character classes although there is also some + * additional movement to transit white space. + * Used by cursor movement by word commands. + */ int Document::NextWordStart(int pos, int delta) { if (delta < 0) { - while (pos > 0 && (cb.CharAt(pos - 1) == ' ' || cb.CharAt(pos - 1) == '\t')) + while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccSpace)) pos--; - if (isspacechar(cb.CharAt(pos - 1))) { // Back up to previous line - while (pos > 0 && isspacechar(cb.CharAt(pos - 1))) - pos--; - } else { - bool startAtWordChar = IsWordChar(cb.CharAt(pos - 1)); - while (pos > 0 && !isspacechar(cb.CharAt(pos - 1)) && (startAtWordChar == IsWordChar(cb.CharAt(pos - 1)))) + if (pos > 0) { + charClassification ccStart = WordCharClass(cb.CharAt(pos-1)); + while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) { pos--; + } } } else { - bool startAtWordChar = IsWordChar(cb.CharAt(pos)); - while (pos < (Length()) && isspacechar(cb.CharAt(pos))) - pos++; - while (pos < (Length()) && !isspacechar(cb.CharAt(pos)) && (startAtWordChar == IsWordChar(cb.CharAt(pos)))) + charClassification ccStart = WordCharClass(cb.CharAt(pos)); + while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart)) pos++; - while (pos < (Length()) && (cb.CharAt(pos) == ' ' || cb.CharAt(pos) == '\t')) + while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccSpace)) pos++; } return pos; } /** - * Check that the character before the given position - * is not a word character. + * Check that the character at the given position is a word or punctuation character and that + * the previous character is of a different character class. */ bool Document::IsWordStartAt(int pos) { if (pos > 0) { - return !IsWordChar(CharAt(pos - 1)); + charClassification ccPos = WordCharClass(CharAt(pos)); + return (ccPos == ccWord || ccPos == ccPunctuation) && + (ccPos != WordCharClass(CharAt(pos - 1))); } return true; } /** - * Check that the character after the given position - * is not a word character. + * Check that the character at the given position is a word or punctuation character and that + * the next character is of a different character class. */ bool Document::IsWordEndAt(int pos) { if (pos < Length() - 1) { - return !IsWordChar(CharAt(pos)); + charClassification ccPrev = WordCharClass(CharAt(pos-1)); + return (ccPrev == ccWord || ccPrev == ccPunctuation) && + (ccPrev != WordCharClass(CharAt(pos))); } return true; } /** - * Check that the given range is delimited by - * non word characters. + * Check that the given range is has transitions between character classes at both + * ends and where the characters on the inside are word or punctuation characters. */ bool Document::IsWordAt(int start, int end) { return IsWordStartAt(start) && IsWordEndAt(end); @@ -1018,16 +1047,22 @@ void Document::ChangeCase(Range r, bool makeUpperCase) { void Document::SetWordChars(unsigned char *chars) { int ch; for (ch = 0; ch < 256; ch++) { - wordchars[ch] = false; + if (ch == '\r' || ch == '\n') + charClass[ch] = ccNewLine; + else if (ch < 0x20 || ch == ' ') + charClass[ch] = ccSpace; + else + charClass[ch] = ccPunctuation; } if (chars) { while (*chars) { - wordchars[*chars] = true; + charClass[*chars] = ccWord; chars++; } } else { for (ch = 0; ch < 256; ch++) { - wordchars[ch] = isalnum(ch) || ch == '_'; + if (ch >= 0x80 || isalnum(ch) || ch == '_') + charClass[ch] = ccWord; } } } @@ -1066,6 +1101,7 @@ void Document::SetStyles(int length, char *styles) { int prevEndStyled = endStyled; bool didChange = false; for (int iPos = 0; iPos < length; iPos++, endStyled++) { + PLATFORM_ASSERT(endStyled < Length()); if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) { didChange = true; } @@ -1080,6 +1116,12 @@ void Document::SetStyles(int length, char *styles) { } bool Document::EnsureStyledTo(int pos) { + if (pos > GetEndStyled()) { + styleClock++; + if (styleClock > 0x100000) { + styleClock = 0; + } + } // Ask the watchers to style, and stop as soon as one responds. for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); @@ -1149,7 +1191,7 @@ void Document::NotifyModified(DocModification mh) { } bool Document::IsWordPartSeparator(char ch) { - return ispunct(ch) && IsWordChar(ch); + return ispunct(ch) && (WordCharClass(ch) == ccWord); } int Document::WordPartLeft(int pos) { diff --git a/contrib/src/stc/scintilla/src/Document.h b/contrib/src/stc/scintilla/src/Document.h index 394c8f94b0..941ad79ccf 100644 --- a/contrib/src/stc/scintilla/src/Document.h +++ b/contrib/src/stc/scintilla/src/Document.h @@ -2,7 +2,7 @@ /** @file Document.h ** Text document that handles notifications, DBCS, styling, words and end of line. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef DOCUMENT_H @@ -37,6 +37,7 @@ public: return (start != invalidPosition) && (end != invalidPosition); } + // Is the position within the range? bool Contains(Position pos) const { if (start < end) { return (pos >= start && pos <= end); @@ -45,6 +46,15 @@ public: } } + // Is the character after pos within the range? + bool ContainsCharacter(Position pos) const { + if (start < end) { + return (pos >= start && pos < end); + } else { + return (pos < start && pos >= end); + } + } + bool Contains(Range other) const { return Contains(other.start) && Contains(other.end); } @@ -81,9 +91,11 @@ public: private: int refCount; CellBuffer cb; - bool wordchars[256]; + enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation }; + charClassification charClass[256]; char stylingMask; int endStyled; + int styleClock; int enteredCount; int enteredReadOnlyCount; @@ -140,6 +152,7 @@ public: void SetLineIndentation(int line, int indent); int GetLineIndentPosition(int line); int GetColumn(int position); + int FindColumn(int line, int column); void Indent(bool forwards, int lineBottom, int lineTop); void ConvertLineEnds(int eolModeSet); void SetReadOnly(bool set) { cb.SetReadOnly(set); } @@ -175,7 +188,7 @@ public: int GetFoldParent(int line); void Indent(bool forwards); - int ExtendWordSelect(int pos, int delta); + int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false); int NextWordStart(int pos, int delta); int Length() { return cb.Length(); } long FindText(int minPos, int maxPos, const char *s, @@ -193,6 +206,7 @@ public: void SetStyles(int length, char *styles); int GetEndStyled() { return endStyled; } bool EnsureStyledTo(int pos); + int GetStyleClock() { return styleClock; } int SetLineState(int line, int state) { return cb.SetLineState(line, state); } int GetLineState(int line) { return cb.GetLineState(line); } @@ -209,7 +223,7 @@ public: private: bool IsDBCS(int pos); - bool IsWordChar(unsigned char ch); + charClassification WordCharClass(unsigned char ch); bool IsWordStartAt(int pos); bool IsWordEndAt(int pos); bool IsWordAt(int start, int end); diff --git a/contrib/src/stc/scintilla/src/DocumentAccessor.cxx b/contrib/src/stc/scintilla/src/DocumentAccessor.cxx index c187f2a442..f115f19304 100644 --- a/contrib/src/stc/scintilla/src/DocumentAccessor.cxx +++ b/contrib/src/stc/scintilla/src/DocumentAccessor.cxx @@ -23,22 +23,14 @@ DocumentAccessor::~DocumentAccessor() { } -#if PLAT_WIN bool DocumentAccessor::InternalIsLeadByte(char ch) { if (SC_CP_UTF8 == codePage) // For lexing, all characters >= 0x80 are treated the // same so none is considered a lead byte. return false; else - return IsDBCSLeadByteEx(codePage, ch); + return Platform::IsDBCSLeadByte(codePage, ch); } -#else -// PLAT_GTK or PLAT_WX -// TODO: support DBCS under GTK+ and WX -bool DocumentAccessor::InternalIsLeadByte(char) { - return false; -} -#endif void DocumentAccessor::Fill(int position) { if (lenDoc == -1) @@ -88,6 +80,7 @@ int DocumentAccessor::SetLineState(int line, int state) { void DocumentAccessor::StartAt(unsigned int start, char chMask) { pdoc->StartStyling(start, chMask); + startPosStyling = start; } void DocumentAccessor::StartSegment(unsigned int pos) { @@ -111,6 +104,7 @@ void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) { chFlags = 0; chAttr |= chFlags; for (unsigned int i = startSeg; i <= pos; i++) { + PLATFORM_ASSERT((startPosStyling + validLen) < Length()); styleBuf[validLen++] = static_cast(chAttr); } } @@ -128,6 +122,7 @@ void DocumentAccessor::Flush() { if (validLen > 0) { pdoc->SetStyles(validLen, styleBuf); validLen = 0; + startPosStyling += validLen; } } diff --git a/contrib/src/stc/scintilla/src/DocumentAccessor.h b/contrib/src/stc/scintilla/src/DocumentAccessor.h index 48742a9b40..5b68dd15c5 100644 --- a/contrib/src/stc/scintilla/src/DocumentAccessor.h +++ b/contrib/src/stc/scintilla/src/DocumentAccessor.h @@ -26,6 +26,7 @@ protected: char chFlags; char chWhile; unsigned int startSeg; + int startPosStyling; bool InternalIsLeadByte(char ch); void Fill(int position); @@ -33,7 +34,8 @@ protected: public: DocumentAccessor(Document *pdoc_, PropSet &props_, WindowID id_=0) : Accessor(), pdoc(pdoc_), props(props_), id(id_), - lenDoc(-1), validLen(0), chFlags(0), chWhile(0) { + lenDoc(-1), validLen(0), chFlags(0), chWhile(0), + startSeg(0), startPosStyling(0) { } ~DocumentAccessor(); char StyleAt(int position); diff --git a/contrib/src/stc/scintilla/src/Editor.cxx b/contrib/src/stc/scintilla/src/Editor.cxx index 2171924f0f..fd8a2d719c 100644 --- a/contrib/src/stc/scintilla/src/Editor.cxx +++ b/contrib/src/stc/scintilla/src/Editor.cxx @@ -2,7 +2,7 @@ /** @file Editor.cxx ** Main code for the edit control. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -12,6 +12,7 @@ #include "Platform.h" +#define INCLUDE_DEPRECATED_FEATURES #include "Scintilla.h" #include "ContractionState.h" @@ -31,6 +32,250 @@ active(false), on(false), period(500) {} Timer::Timer() : ticking(false), ticksToWait(0), tickerID(0) {} +LineLayout::LineLayout(int maxLineLength_) : + lineStarts(0), + lenLineStarts(0), + lineNumber(-1), + inCache(false), + maxLineLength(-1), + numCharsInLine(0), + validity(llInvalid), + xHighlightGuide(0), + highlightColumn(0), + selStart(0), + selEnd(0), + containsCaret(false), + edgeColumn(0), + chars(0), + styles(0), + indicators(0), + positions(0), + widthLine(wrapWidthInfinite), + lines(1) { + Resize(maxLineLength_); +} + +LineLayout::~LineLayout() { + Free(); +} + +void LineLayout::Resize(int maxLineLength_) { + if (maxLineLength_ > maxLineLength) { + Free(); + chars = new char[maxLineLength_ + 1]; + styles = new char[maxLineLength_ + 1]; + indicators = new char[maxLineLength_ + 1]; + positions = new int[maxLineLength_ + 1]; + maxLineLength = maxLineLength_; + } +} + +void LineLayout::Free() { + delete []chars; + chars = 0; + delete []styles; + styles = 0; + delete []indicators; + indicators = 0; + delete []positions; + positions = 0; + delete []lineStarts; + lineStarts = 0; +} + +void LineLayout::Invalidate(validLevel validity_) { + validity = validity_; +} + +void LineLayout::SetLineStart(int line, int start) { + if ((line >= lenLineStarts) && (line != 0)) { + int newMaxLines = line + 20; + int *newLineStarts = new int[newMaxLines]; + if (!newLineStarts) + return; + for (int i=0; i= rangeLine.start && braces[1] <= rangeLine.end) || + (braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) { + xHighlightGuide = xHighlight; + } +} + +void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) { + if (rangeLine.ContainsCharacter(braces[0])) { + int braceOffset = braces[0] - rangeLine.start; + if (braceOffset < numCharsInLine) { + styles[braceOffset] = bracePreviousStyles[0]; + } + } + if (rangeLine.ContainsCharacter(braces[1])) { + int braceOffset = braces[1] - rangeLine.start; + if (braceOffset < numCharsInLine) { + styles[braceOffset] = bracePreviousStyles[1]; + } + } + xHighlightGuide = 0; +} + +LineLayoutCache::LineLayoutCache() : + level(0), length(0), size(0), cache(0), + allInvalidated(false), styleClock(-1) { + Allocate(0); +} + +LineLayoutCache::~LineLayoutCache() { + Deallocate(); +} + +void LineLayoutCache::Allocate(int length_) { + allInvalidated = false; + length = length_; + size = length; + if (size > 1) { + size = (size / 16 + 1) * 16; + } + if (size > 0) { + cache = new LineLayout *[size]; + } + for (int i=0; i size) { + Deallocate(); + } else { + if (lengthForLevel < length) { + for (int i=lengthForLevel; iInvalidate(validity_); + } + } + if (validity_ == LineLayout::llInvalid) { + allInvalidated = true; + } + } +} + +void LineLayoutCache::SetLevel(int level_) { + allInvalidated = false; + if ((level_ != -1) && (level != level_)) { + level = level_; + Deallocate(); + } +} + +LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, + int linesOnScreen, int linesInDoc) { + AllocateForLevel(linesOnScreen, linesInDoc); + if (styleClock != styleClock_) { + Invalidate(LineLayout::llInvalid); + styleClock = styleClock_; + } + allInvalidated = false; + int pos = -1; + LineLayout *ret = 0; + if (((level == llcCaret) || (level == llcPage)) && (lineNumber == lineCaret)) { + pos = 0; + } else if (level == llcPage) { + pos = lineNumber % length; + } else if (level == llcDocument) { + pos = lineNumber; + } + if (pos >= 0) { + if (cache && (pos < length)) { + if (cache[pos]) { + if ((cache[pos]->lineNumber != lineNumber) || + (cache[pos]->maxLineLength < maxChars)) { + delete cache[pos]; + cache[pos] = 0; + } + } + if (!cache[pos]) { + cache[pos] = new LineLayout(maxChars); + } + if (cache[pos]) { + cache[pos]->lineNumber = lineNumber; + cache[pos]->inCache = true; + ret = cache[pos]; + } + } + } + + if (!ret) { + ret = new LineLayout(maxChars); + ret->lineNumber = lineNumber; + } + + return ret; +} + +void LineLayoutCache::Dispose(LineLayout *ll) { + allInvalidated = false; + if (ll) { + if (!ll->inCache) { + delete ll; + } + } +} + Editor::Editor() { ctrlID = 0; @@ -39,6 +284,7 @@ Editor::Editor() { printMagnification = 0; printColourMode = SC_PRINT_NORMAL; cursorMode = SC_CURSORNORMAL; + controlCharSymbol = 0; /* Draw the control characters */ hasFocus = false; hideSelection = false; @@ -81,6 +327,12 @@ Editor::Editor() { xCaretMargin = 50; horizontalScrollBarVisible = true; + pixmapLine = Surface::Allocate(); + pixmapSelMargin = Surface::Allocate(); + pixmapSelPattern = Surface::Allocate(); + pixmapIndentGuide = Surface::Allocate(); + pixmapIndentGuideHighlight = Surface::Allocate(); + currentPos = 0; anchor = 0; @@ -109,6 +361,12 @@ Editor::Editor() { recordingMacro = false; foldFlags = 0; + + wrapState = eWrapNone; + wrapWidth = LineLayout::wrapWidthInfinite; + docLineLastWrapped = -1; + + llc.SetLevel(LineLayoutCache::llcDocument); } Editor::~Editor() { @@ -116,6 +374,11 @@ Editor::~Editor() { pdoc->Release(); pdoc = 0; DropGraphics(); + delete pixmapLine; + delete pixmapSelMargin; + delete pixmapSelPattern; + delete pixmapIndentGuide; + delete pixmapIndentGuideHighlight; } void Editor::Finalise() { @@ -123,16 +386,17 @@ void Editor::Finalise() { } void Editor::DropGraphics() { - pixmapLine.Release(); - pixmapSelMargin.Release(); - pixmapSelPattern.Release(); - pixmapIndentGuide.Release(); + pixmapLine->Release(); + pixmapSelMargin->Release(); + pixmapSelPattern->Release(); + pixmapIndentGuide->Release(); } void Editor::InvalidateStyleData() { stylesValid = false; palette.Release(); DropGraphics(); + llc.Invalidate(LineLayout::llInvalid); } void Editor::InvalidateStyleRedraw() { @@ -147,12 +411,13 @@ void Editor::RefreshColourPalette(Palette &pal, bool want) { void Editor::RefreshStyleData() { if (!stylesValid) { stylesValid = true; - Surface surface; - surface.Init(); - vs.Refresh(surface); - RefreshColourPalette(palette, true); - palette.Allocate(wMain); - RefreshColourPalette(palette, false); + AutoSurface surface(IsUnicodeMode()); + if (surface) { + vs.Refresh(*surface); + RefreshColourPalette(palette, true); + palette.Allocate(wMain); + RefreshColourPalette(palette, false); + } SetScrollBars(); } } @@ -220,19 +485,30 @@ Point Editor::LocationFromPosition(int pos) { int line = pdoc->LineFromPosition(pos); int lineVisible = cs.DisplayFromDoc(line); //Platform::DebugPrintf("line=%d\n", line); - Surface surface; - surface.Init(); - surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); - pt.y = (lineVisible - topLine) * vs.lineHeight; // + half a lineheight? - unsigned int posLineStart = pdoc->LineStart(line); - LineLayout ll; - LayoutLine(line, &surface, vs, ll); - if ((pos - posLineStart) > LineLayout::maxLineLength) { - // very long line so put x at arbitrary large position - pt.x = ll.positions[LineLayout::maxLineLength] + vs.fixedColumnWidth - xOffset; - } else { - pt.x = ll.positions[pos - posLineStart] + vs.fixedColumnWidth - xOffset; + AutoSurface surface(IsUnicodeMode()); + LineLayout *ll = RetrieveLineLayout(line); + if (surface && ll) { + // -1 because of adding in for visible lines in following loop. + pt.y = (lineVisible - topLine - 1) * vs.lineHeight; + pt.x = 0; + unsigned int posLineStart = pdoc->LineStart(line); + LayoutLine(line, surface, vs, ll, wrapWidth); + int posInLine = pos - posLineStart; + // In case of very long line put x at arbitrary large position + if (posInLine > ll->maxLineLength) { + pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)]; + } + for (int subLine=0; subLinelines; subLine++) { + if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine+1))) { + pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)]; + } + if (posInLine >= ll->LineStart(subLine)) { + pt.y += vs.lineHeight; + } + } + pt.x += vs.fixedColumnWidth - xOffset; } + llc.Dispose(ll); return pt; } @@ -253,29 +529,41 @@ void Editor::SetTopLine(int topLineNew) { int Editor::PositionFromLocation(Point pt) { RefreshStyleData(); pt.x = pt.x - vs.fixedColumnWidth + xOffset; - int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine); + int visibleLine = pt.y / vs.lineHeight + topLine; if (pt.y < 0) { // Division rounds towards 0 - line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine); + visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine; } - if (line < 0) - return 0; - if (line >= pdoc->LinesTotal()) + if (visibleLine < 0) + visibleLine = 0; + int lineDoc = cs.DocFromDisplay(visibleLine); + if (lineDoc >= pdoc->LinesTotal()) return pdoc->Length(); - Surface surface; - surface.Init(); - surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); - 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; + AutoSurface surface(IsUnicodeMode()); + int retVal = 0; + LineLayout *ll = RetrieveLineLayout(lineDoc); + if (surface && ll) { + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + unsigned int posLineStart = pdoc->LineStart(lineDoc); + int lineStartSet = cs.DisplayFromDoc(lineDoc); + int subLine = visibleLine - lineStartSet; + if (subLine < ll->lines) { + int lineStart = ll->LineStart(subLine); + int lineEnd = ll->LineStart(subLine+1); + int subLineStart = ll->positions[lineStart]; + for (int i = lineStart; i < lineEnd; i++) { + if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) || + ll->chars[i] == '\r' || ll->chars[i] == '\n') { + llc.Dispose(ll); + return pdoc->MovePositionOutsideChar(i + posLineStart, 1); + } + } + llc.Dispose(ll); + return lineEnd + posLineStart; } + retVal = ll->numCharsInLine + posLineStart; } - - return ll.numCharsInLine + posLineStart; + llc.Dispose(ll); + return retVal; } // Like PositionFromLocation but INVALID_POSITION returned when not near any text. @@ -289,51 +577,68 @@ int Editor::PositionFromLocationClose(Point pt) { if (pt.y < 0) return INVALID_POSITION; pt.x = pt.x - vs.fixedColumnWidth + xOffset; - int line = cs.DocFromDisplay(pt.y / vs.lineHeight + topLine); + int visibleLine = pt.y / vs.lineHeight + topLine; if (pt.y < 0) { // Division rounds towards 0 - line = cs.DocFromDisplay((pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine); + visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine; } - if (line < 0) + int lineDoc = cs.DocFromDisplay(visibleLine); + if (lineDoc < 0) return INVALID_POSITION; - if (line >= pdoc->LinesTotal()) + if (lineDoc >= pdoc->LinesTotal()) return INVALID_POSITION; - Surface surface; - surface.Init(); - surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); - 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; + AutoSurface surface(IsUnicodeMode()); + LineLayout *ll = RetrieveLineLayout(lineDoc); + if (surface && ll) { + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + unsigned int posLineStart = pdoc->LineStart(lineDoc); + int lineStartSet = cs.DisplayFromDoc(lineDoc); + int subLine = visibleLine - lineStartSet; + if (subLine < ll->lines) { + int lineStart = ll->LineStart(subLine); + int lineEnd = ll->LineStart(subLine+1); + int subLineStart = ll->positions[lineStart]; + for (int i = lineStart; i < lineEnd; i++) { + if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) || + ll->chars[i] == '\r' || ll->chars[i] == '\n') { + llc.Dispose(ll); + return pdoc->MovePositionOutsideChar(i + posLineStart, 1); + } + } } } + llc.Dispose(ll); return INVALID_POSITION; } -int Editor::PositionFromLineX(int line, int x) { +// Find the document position corresponding to an x coordinate on a particular document line. +// Ensure is between whole characters when document is in multi-byte or UTF-8 mode. +int Editor::PositionFromLineX(int lineDoc, int x) { RefreshStyleData(); - if (line >= pdoc->LinesTotal()) + if (lineDoc >= 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(); - surface.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); - 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; + AutoSurface surface(IsUnicodeMode()); + LineLayout *ll = RetrieveLineLayout(lineDoc); + int retVal = 0; + if (surface && ll) { + unsigned int posLineStart = pdoc->LineStart(lineDoc); + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + retVal = ll->numCharsInLine + posLineStart; + int subLine = 0; + int lineStart = ll->LineStart(subLine); + int lineEnd = ll->LineStart(subLine+1); + int subLineStart = ll->positions[lineStart]; + for (int i = lineStart; i < lineEnd; i++) { + if (x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) || + ll->chars[i] == '\r' || ll->chars[i] == '\n') { + retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1); + break; + } } } - - return ll.numCharsInLine + posLineStart; + llc.Dispose(ll); + return retVal; } void Editor::RedrawRect(PRectangle rc) { @@ -378,7 +683,8 @@ PRectangle Editor::RectangleFromRange(int start, int end) { if (maxPos < end) maxPos = end; int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos)); - int maxLine = cs.DisplayFromDoc(pdoc->LineFromPosition(maxPos)); + int lineDocMax = pdoc->LineFromPosition(maxPos); + int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1; PRectangle rcClient = GetTextRectangle(); PRectangle rc; rc.left = vs.fixedColumnWidth; @@ -498,11 +804,11 @@ int Editor::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { int mask = pdoc->stylingBitsMask; if (moveDir > 0) { while ((pos < pdoc->Length()) && - (!vs.styles[pdoc->StyleAt(pos - 1) & mask].visible)) + (vs.styles[pdoc->StyleAt(pos - 1) & mask].IsProtected())) pos++; } else { while ((pos > 0) && - (!vs.styles[pdoc->StyleAt(pos - 1) & mask].visible)) + (vs.styles[pdoc->StyleAt(pos - 1) & mask].IsProtected())) pos--; } return pos; @@ -532,12 +838,12 @@ int Editor::MovePositionSoVisible(int pos, int moveDir) { } else { int lineDisplay = cs.DisplayFromDoc(lineDoc); if (moveDir > 0) { - lineDisplay = Platform::Clamp(lineDisplay + 1, 0, cs.LinesDisplayed()); + // lineDisplay is already line before fold as lines in fold use display line of line after fold + lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed()); return 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))); + lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed()); + return pdoc->LineEnd(cs.DocFromDisplay(lineDisplay)); } } } @@ -572,11 +878,13 @@ void Editor::ScrollText(int /* linesToMove */) { void Editor::HorizontalScrollTo(int xPos) { //Platform::DebugPrintf("HorizontalScroll %d\n", xPos); - xOffset = xPos; - if (xOffset < 0) - xOffset = 0; - SetHorizontalScrollPos(); - RedrawRect(GetClientRectangle()); + if (xPos < 0) + xPos = 0; + if ((wrapState == eWrapNone) && (xOffset != xPos)) { + xOffset = xPos; + SetHorizontalScrollPos(); + RedrawRect(GetClientRectangle()); + } } void Editor::MoveCaretInsideView() { @@ -592,6 +900,26 @@ void Editor::MoveCaretInsideView() { } } +int Editor::DisplayFromPosition(int pos) { + int lineDoc = pdoc->LineFromPosition(pos); + int lineDisplay = cs.DisplayFromDoc(lineDoc); + AutoSurface surface(IsUnicodeMode()); + LineLayout *ll = RetrieveLineLayout(lineDoc); + if (surface && ll) { + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + unsigned int posLineStart = pdoc->LineStart(lineDoc); + int posInLine = pos - posLineStart; + lineDisplay--; // To make up for first increment ahead. + for (int subLine=0; subLinelines; subLine++) { + if (posInLine >= ll->LineStart(subLine)) { + lineDisplay++; + } + } + } + llc.Dispose(ll); + return lineDisplay; +} + void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { //Platform::DebugPrintf("EnsureCaretVisible %d %s\n", xOffset, useMargin ? " margin" : " "); PRectangle rcClient = GetTextRectangle(); @@ -602,7 +930,7 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { Point pt = LocationFromPosition(posCaret); Point ptEOL = LocationFromPosition(pdoc->LineEndPosition(posCaret)); Point ptBottomCaret = pt; - int lineCaret = cs.DisplayFromDoc(pdoc->LineFromPosition(posCaret)); + int lineCaret = DisplayFromPosition(posCaret); ptBottomCaret.y += vs.lineHeight - 1; // Ensure the caret is reasonably visible in context: @@ -615,7 +943,7 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { // If we scroll the display, we use a minimum amount of xMargin. int offsetLeft = rcClient.left + xMargin; int offsetRight = rcClient.right - xMargin; - // If we are in XJUMPS mode, then when the margin is reached, the + // If we are in XJUMPS mode, then when the margin is reached, the // offset jumps so that it won't need to move agin for a while. if (!(caretPolicy & CARET_XJUMPS)) { rcClient.left = offsetLeft; @@ -648,7 +976,7 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { } // Horizontal positioning - if (horiz) { + if (horiz && (wrapState == eWrapNone)) { int xOffsetNew = xOffset; if (pt.x < rcClient.left) { xOffsetNew = xOffset - (offsetLeft - pt.x); @@ -671,14 +999,15 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { } void Editor::ShowCaretAtCurrentPosition() { - if (!hasFocus) { + if (hasFocus) { + caret.active = true; + caret.on = true; + SetTicking(true); + } else { caret.active = false; caret.on = false; - return; } - caret.active = true; - caret.on = true; - SetTicking(true); + InvalidateCaret(); } void Editor::DropCaret() { @@ -693,6 +1022,72 @@ void Editor::InvalidateCaret() { InvalidateRange(currentPos, currentPos + 1); } +void Editor::NeedWrapping(int docLineStartWrapping) { + docLineLastWrapped = docLineStartWrapping - 1; + if (docLineLastWrapped < -1) + docLineLastWrapped = -1; + llc.Invalidate(LineLayout::llPositions); +} + +// Check if wrapping needed and perform any needed wrapping. +// Return true if wrapping occurred. +bool Editor::WrapLines() { + int goodTopLine = topLine; + bool wrapOccurred = false; + if (docLineLastWrapped < pdoc->LinesTotal()) { + if (wrapState == eWrapNone) { + if (wrapWidth != LineLayout::wrapWidthInfinite) { + wrapWidth = LineLayout::wrapWidthInfinite; + for (int lineDoc=0; lineDocLinesTotal(); lineDoc++) { + cs.SetHeight(lineDoc, 1); + } + wrapOccurred = true; + } + docLineLastWrapped = 0x7ffffff; + } else { + ElapsedTime et; + int lineDocTop = cs.DocFromDisplay(topLine); + int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop); + PRectangle rcTextArea = GetClientRectangle(); + rcTextArea.left = vs.fixedColumnWidth; + rcTextArea.right -= vs.rightMarginWidth; + wrapWidth = rcTextArea.Width(); + // Ensure all of the document is styled. + pdoc->EnsureStyledTo(pdoc->Length()); + AutoSurface surface(IsUnicodeMode()); + if (surface) { + int lastLineToWrap = pdoc->LinesTotal(); + while (docLineLastWrapped <= lastLineToWrap) { + docLineLastWrapped++; + LineLayout *ll = RetrieveLineLayout(docLineLastWrapped); + int linesWrapped = 1; + if (ll) { + LayoutLine(docLineLastWrapped, surface, vs, ll, wrapWidth); + linesWrapped = ll->lines; + } + llc.Dispose(ll); + if (cs.SetHeight(docLineLastWrapped, linesWrapped)) { + wrapOccurred = true; + } + } + } + goodTopLine = cs.DisplayFromDoc(lineDocTop); + if (subLineTop < cs.GetHeight(lineDocTop)) + goodTopLine += subLineTop; + else + goodTopLine += cs.GetHeight(lineDocTop); + double durWrap = et.Duration(true); + Platform::DebugPrintf("Wrap:%9.6g \n", durWrap); + } + } + if (wrapOccurred) { + SetScrollBars(); + SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos())); + SetVerticalScrollPos(); + } + return wrapOccurred; +} + int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) { if (vs.markers[markerCheck].markType == SC_MARK_EMPTY) return markerDefault; @@ -711,7 +1106,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { Surface *surface; if (bufferedDraw) { - surface = &pixmapSelMargin; + surface = pixmapSelMargin; } else { surface = surfWindow; } @@ -735,7 +1130,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { */ if (vs.ms[margin].mask & SC_MASK_FOLDERS) // Required because of special way brush is created for selection margin - surface->FillRectangle(rcSelMargin, pixmapSelPattern); + surface->FillRectangle(rcSelMargin, *pixmapSelPattern); else surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated); } else { @@ -743,16 +1138,15 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { } int visibleLine = topLine; - int line = cs.DocFromDisplay(visibleLine); int yposScreen = 0; - // Work out whether the top line is whitespace located after a + // Work out whether the top line is whitespace located after a // lessening of fold level which implies a 'fold tail' but which should not // be displayed until the last of a sequence of whitespace. - bool needWhiteClosure = false; - int level = pdoc->GetLevel(line); + bool needWhiteClosure = false; + int level = pdoc->GetLevel(cs.DocFromDisplay(topLine)); if (level & SC_FOLDLEVELWHITEFLAG) { - int lineBack = line; + int lineBack = cs.DocFromDisplay(topLine); int levelPrev = level; while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { lineBack--; @@ -763,32 +1157,44 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { needWhiteClosure = true; } } - + // Old code does not know about new markers needed to distinguish all cases - int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, + int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, SC_MARKNUM_FOLDEROPEN); - int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, + int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND, SC_MARKNUM_FOLDER); - + while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) { + PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed()); + + int lineDoc = cs.DocFromDisplay(visibleLine); + PLATFORM_ASSERT(cs.GetVisible(lineDoc)); + bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc); + // Decide which fold indicator should be displayed - level = pdoc->GetLevel(line); - int levelNext = pdoc->GetLevel(line+1); - int marks = pdoc->GetMark(line); + level = pdoc->GetLevel(lineDoc); + int levelNext = pdoc->GetLevel(lineDoc+1); + int marks = pdoc->GetMark(lineDoc); + if (!firstSubLine) + marks = 0; int levelNum = level & SC_FOLDLEVELNUMBERMASK; int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; if (level & SC_FOLDLEVELHEADERFLAG) { - if (cs.GetExpanded(line)) { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDEROPEN; - else - marks |= 1 << folderOpenMid; + if (firstSubLine) { + if (cs.GetExpanded(lineDoc)) { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDEROPEN; + else + marks |= 1 << folderOpenMid; + } else { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDER; + else + marks |= 1 << folderEnd; + } } else { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDER; - else - marks |= 1 << folderEnd; + marks |= 1 << SC_MARKNUM_FOLDERSUB; } needWhiteClosure = false; } else if (level & SC_FOLDLEVELWHITEFLAG) { @@ -836,20 +1242,19 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (!vs.ms[margin].symbol) { char number[100]; number[0] = '\0'; - sprintf(number, "%d", line + 1); + if (firstSubLine) + sprintf(number, "%d", lineDoc + 1); if (foldFlags & 64) - sprintf(number, "%X", pdoc->GetLevel(line)); + sprintf(number, "%X", pdoc->GetLevel(lineDoc)); PRectangle rcNumber = rcMarker; // Right justify int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, strlen(number)); int 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); - } + surface->DrawTextNoClip(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) { @@ -862,7 +1267,6 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { } visibleLine++; - line = cs.DocFromDisplay(visibleLine); yposScreen += vs.lineHeight; } } @@ -873,13 +1277,17 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated); if (bufferedDraw) { - surfWindow->Copy(rcMargin, Point(), pixmapSelMargin); + surfWindow->Copy(rcMargin, Point(), *pixmapSelMargin); } } void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { int ydiff = (rcTab.bottom - rcTab.top) / 2; int xhead = rcTab.right - 1 - ydiff; + if (xhead <= rcTab.left) { + ydiff -= rcTab.left - xhead - 1; + xhead = rcTab.left - 1; + } if ((rcTab.left + 2) < (rcTab.right - 1)) surface->MoveTo(rcTab.left + 2, ymid); else @@ -890,98 +1298,182 @@ void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { surface->LineTo(xhead, ymid + ydiff); } +static bool IsSpaceOrTab(char ch) { + return ch == ' ' || ch == '\t'; +} + +LineLayout *Editor::RetrieveLineLayout(int lineNumber) { + int posLineStart = pdoc->LineStart(lineNumber); + int posLineEnd = pdoc->LineStart(lineNumber + 1); + int lineCaret = pdoc->LineFromPosition(currentPos); + return llc.Retrieve(lineNumber, lineCaret, + posLineEnd - posLineStart, pdoc->GetStyleClock(), + LinesOnScreen() + 1, pdoc->LinesTotal()); +} + /** * Fill in the LineLayout data for the given line. * Copy the given @a line and its styles from the document into local arrays. * Also determine the x position at which each character starts. */ -void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll) { - int numCharsInLine = 0; +void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) { + if (!ll) + return; 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; - ll.xHighlightGuide = 0; - // If the line is very long, limit the treatment to a length that should fit in the viewport - if (posLineEnd > (posLineStart + LineLayout::maxLineLength)) { - posLineEnd = posLineStart + LineLayout::maxLineLength; - } - // Fill base line layout - for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) { - char chDoc = pdoc->CharAt(charInDoc); - styleByte = pdoc->StyleAt(charInDoc); - if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) { - ll.chars[numCharsInLine] = chDoc; - ll.styles[numCharsInLine] = static_cast(styleByte & styleMask); - ll.indicators[numCharsInLine] = static_cast(styleByte & ~styleMask); - if (vstyle.styles[ll.styles[numCharsInLine]].caseForce == Style::caseUpper) - ll.chars[numCharsInLine] = static_cast(toupper(chDoc)); - else if (vstyle.styles[ll.styles[numCharsInLine]].caseForce == Style::caseLower) - ll.chars[numCharsInLine] = static_cast(tolower(chDoc)); - numCharsInLine++; - } - } - // Extra element at the end of the line to hold end x position and act as - ll.chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character - ll.styles[numCharsInLine] = styleByte; // For eolFilled - ll.indicators[numCharsInLine] = 0; - - // Layout the line, determining the position of each character, - // with an extra element at the end for the end of the line. - int startseg = 0; // Start of the current segment, in char. number - int startsegx = 0; // Start of the current segment, in pixels - ll.positions[0] = 0; - unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars; - bool lastSegItalics = false; - - 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 (vstyle.styles[ll.styles[charInLine]].visible) { - 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; + if (ll->validity == LineLayout::llInvalid) { + ll->widthLine = LineLayout::wrapWidthInfinite; + ll->lines = 1; + int numCharsInLine = 0; + if (vstyle.edgeState == EDGE_BACKGROUND) { + ll->edgeColumn = pdoc->FindColumn(line, theEdge); + if (ll->edgeColumn >= posLineStart) { + ll->edgeColumn -= posLineStart; + } + } else { + ll->edgeColumn = -1; + } + + int posLineEnd = pdoc->LineStart(line + 1); + Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font; + char styleByte = 0; + int styleMask = pdoc->stylingBitsMask; + ll->xHighlightGuide = 0; + // If the line is very long, limit the treatment to a length that should fit in the viewport + if (posLineEnd > (posLineStart + ll->maxLineLength)) { + posLineEnd = posLineStart + ll->maxLineLength; + } + // Fill base line layout + for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) { + char chDoc = pdoc->CharAt(charInDoc); + styleByte = pdoc->StyleAt(charInDoc); + if (vstyle.viewEOL || ((chDoc != '\r') && (chDoc != '\n'))) { + ll->chars[numCharsInLine] = chDoc; + ll->styles[numCharsInLine] = static_cast(styleByte & styleMask); + ll->indicators[numCharsInLine] = static_cast(styleByte & ~styleMask); + if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper) + ll->chars[numCharsInLine] = static_cast(toupper(chDoc)); + else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) + ll->chars[numCharsInLine] = static_cast(tolower(chDoc)); + numCharsInLine++; + } + } + // Extra element at the end of the line to hold end x position and act as + ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character + ll->styles[numCharsInLine] = styleByte; // For eolFilled + ll->indicators[numCharsInLine] = 0; + + // Layout the line, determining the position of each character, + // with an extra element at the end for the end of the line. + int startseg = 0; // Start of the current segment, in char. number + int startsegx = 0; // Start of the current segment, in pixels + ll->positions[0] = 0; + unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars; + bool lastSegItalics = false; + + 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 (vstyle.styles[ll->styles[charInLine]].visible) { + if (IsControlCharacter(ll->chars[charInLine])) { + if (ll->chars[charInLine] == '\t') { + ll->positions[charInLine + 1] = ((((startsegx + 2) / + tabWidth) + 1) * tabWidth) - startsegx; + } else if (controlCharSymbol < 32) { + const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]); + // +3 For a blank on front and rounded edge each side: + ll->positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, strlen(ctrlChar)) + 3; + } else { + char cc[2] = { static_cast(controlCharSymbol), '\0' }; + surface->MeasureWidths(ctrlCharsFont, cc, 1, + ll->positions + startseg + 1); + } + lastSegItalics = false; + } else { // Regular character + lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic; + int lenSeg = charInLine - startseg + 1; + if ((lenSeg == 1) && (' ' == ll->chars[startseg])) { + // Over half the segments are single characters and of these about half are space characters. + ll->positions[charInLine + 1] = vstyle.styles[ll->styles[charInLine]].spaceWidth; + } else { + surface->MeasureWidths(vstyle.styles[ll->styles[charInLine]].font, ll->chars + startseg, + lenSeg, ll->positions + startseg + 1); + } } - lastSegItalics = false; - } else { // Regular character - lastSegItalics = vstyle.styles[ll.styles[charInLine]].italic; - int lenSeg = charInLine - startseg + 1; - if ((lenSeg == 1) && (' ' == ll.chars[startseg])) { - // Over half the segments are single characters and of these about half are space characters. - ll.positions[charInLine + 1] = vstyle.styles[ll.styles[charInLine]].spaceWidth; - } else { - surface->MeasureWidths(vstyle.styles[ll.styles[charInLine]].font, ll.chars + startseg, - lenSeg, ll.positions + startseg + 1); + } else { // invisible + for (int posToZero = startseg; posToZero <= (charInLine + 1); posToZero++) { + ll->positions[posToZero] = 0; } } - } else { // invisible - for (int posToZero = startseg; posToZero <= (charInLine + 1); posToZero++) { - ll.positions[posToZero] = 0; + for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) { + ll->positions[posToIncrease] += startsegx; } + startsegx = ll->positions[charInLine + 1]; + startseg = charInLine + 1; } - for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) { - ll.positions[posToIncrease] += startsegx; - } - startsegx = ll.positions[charInLine + 1]; - startseg = charInLine + 1; } + // Small hack to make lines that end with italics not cut off the edge of the last character + if ((startseg > 0) && lastSegItalics) { + ll->positions[startseg] += 2; + } + ll->numCharsInLine = numCharsInLine; + ll->validity = LineLayout::llPositions; + } + // Hard to cope when too narrow, so just assume there is space + if (width < 20) { + width = 20; } - // Small hack to make lines that end with italics not cut off the edge of the last character - if ((startseg > 0) && lastSegItalics) { - ll.positions[startseg] += 2; + if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { + ll->widthLine = width; + if (width == LineLayout::wrapWidthInfinite) { + ll->lines = 1; + } else { + ll->lines = 0; + // Calculate line start positions based upon width. + // For now this is simplistic - wraps on byte rather than character and + // in the middle of words. Should search for spaces or style changes. + int lastGoodBreak = 0; + int lastLineStart = 0; + int startOffset = 0; + int p=0; + while (p < ll->numCharsInLine) { + if ((ll->positions[p+1] - startOffset) >= width) { + if (lastGoodBreak == lastLineStart) { + // Try moving to start of last character + if (p > 0) { + lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1) + - posLineStart; + } + if (lastGoodBreak == lastLineStart) { + // Ensure at least one character on line. + lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart +1, 1) + - posLineStart; + } + } + lastLineStart = lastGoodBreak; + ll->lines++; + ll->SetLineStart(ll->lines, lastGoodBreak); + startOffset = ll->positions[lastGoodBreak]; + p = lastGoodBreak + 1; + continue; + } + if (p > 0) { + if (ll->styles[p] != ll->styles[p-1]) { + lastGoodBreak = p; + } else if (IsSpaceOrTab(ll->chars[p-1]) && !IsSpaceOrTab(ll->chars[p])) { + lastGoodBreak = p; + } + } + p++; + } + ll->lines++; + } + ll->validity = LineLayout::llLines; } - ll.numCharsInLine = numCharsInLine; } void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, - PRectangle rcLine, LineLayout &ll) { + PRectangle rcLine, LineLayout *ll, int subLine) { PRectangle rcSegment = rcLine; @@ -990,26 +1482,43 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // is taken by an individual character - internal leading gives varying results. Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; + // See if something overrides the line background color: Either if caret is on the line + // and background color is set for that, or if a marker is defined that forces its background + // color onto the line, or if a marker is defined but has no selection margin in which to + // display itself. These are checked in order with the earlier taking precedence. When + // multiple markers cause background override, the color for the highest numbered one is used. bool overrideBackground = false; - Colour background = Colour(0, 0, 0); - if (caret.active && vsDraw.showCaretLineBackground && ll.containsCaret) { + ColourAllocated background; + if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) { overrideBackground = true; background = vsDraw.caretLineBackground.allocated; } - if (vsDraw.maskInLine) { - int marks = pdoc->GetMark(line) & vsDraw.maskInLine; - if (marks) { - overrideBackground = true; - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if (marks & 1) { - background = vsDraw.markers[markBit].back.allocated; + if (!overrideBackground) { + int marks = pdoc->GetMark(line); + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if ((marks & 1) && vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) { + background = vsDraw.markers[markBit].back.allocated; + overrideBackground = true; + } + marks >>= 1; + } + } + if (!overrideBackground) { + if (vsDraw.maskInLine) { + int marks = pdoc->GetMark(line) & vsDraw.maskInLine; + if (marks) { + overrideBackground = true; + for (int markBit = 0; (markBit < 32) && marks; markBit++) { + if (marks & 1) { + background = vsDraw.markers[markBit].back.allocated; + } + marks >>= 1; } - marks >>= 1; } } } - bool inIndentation = true; + bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. int indentWidth = pdoc->indentInChars * vsDraw.spaceWidth; if (indentWidth == 0) indentWidth = pdoc->tabInChars * vsDraw.spaceWidth; @@ -1018,115 +1527,126 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis int posLineEnd = pdoc->LineStart(line + 1); int styleMask = pdoc->stylingBitsMask; - int startseg = 0; - for (int i = 0; i < ll.numCharsInLine; i++) { + int startseg = ll->LineStart(subLine); + int subLineStart = ll->positions[startseg]; + int lineStart = 0; + int lineEnd = 0; + if (subLine < ll->lines) { + lineStart = ll->LineStart(subLine); + lineEnd = ll->LineStart(subLine+1); + } + for (int i = lineStart; i < lineEnd; 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]) || - ((ll.selStart != ll.selEnd) && ((iDoc + 1 == ll.selStart) || (iDoc + 1 == ll.selEnd))) || - (i == (ll.edgeColumn - 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 >= ll.selStart) && (iDoc < ll.selEnd) && (ll.selStart != ll.selEnd); - if (inSelection) { - if (vsDraw.selbackset) { - if (primarySelection) - textBack = vsDraw.selbackground.allocated; - else - textBack = vsDraw.selbackground2.allocated; - } - if (vsDraw.selforeset) - textFore = vsDraw.selforeground.allocated; - } else { - if (overrideBackground) - textBack = background; - if ((vsDraw.edgeState == EDGE_BACKGROUND) && (i >= ll.edgeColumn) && (ll.chars[i] != '\n') && (ll.chars[i] != '\r')) - textBack = vsDraw.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 != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) { - surface->PenColour(textFore); + if ((ll->styles[i] != ll->styles[i + 1]) || + i == (lineEnd-1) || + IsControlCharacter(ll->chars[i]) || IsControlCharacter(ll->chars[i + 1]) || + ((ll->selStart != ll->selEnd) && ((iDoc + 1 == ll->selStart) || (iDoc + 1 == ll->selEnd))) || + (i == (ll->edgeColumn - 1))) { + rcSegment.left = ll->positions[startseg] + xStart - subLineStart; + rcSegment.right = ll->positions[i + 1] + xStart - subLineStart; + // Only try to draw if really visible - enhances performance by not calling environment to + // draw strings that are completely past the right side of the window. + //if (rcSegment.left <= rcLine.right) { + if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { + int styleMain = ll->styles[i]; + ColourAllocated textBack = vsDraw.styles[styleMain].back.allocated; + ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated; + Font &textFont = vsDraw.styles[styleMain].font; + bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd); + if (inSelection) { + if (vsDraw.selbackset) { + if (primarySelection) + textBack = vsDraw.selbackground.allocated; + else + textBack = vsDraw.selbackground2.allocated; + } + if (vsDraw.selforeset) + textFore = vsDraw.selforeground.allocated; + } else { + if (overrideBackground) + textBack = background; + if ((vsDraw.edgeState == EDGE_BACKGROUND) && (i >= ll->edgeColumn) && (ll->chars[i] != '\n') && (ll->chars[i] != '\r')) + textBack = vsDraw.edgecolour.allocated; } - if (inIndentation && vsDraw.viewIndentationGuides) { - for (int xIG = ll.positions[i] / indentWidth * indentWidth; xIG < ll.positions[i + 1]; xIG += indentWidth) { - if (xIG >= ll.positions[i] && xIG > 0) { - Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); - PRectangle rcCopyArea(xIG + xStart + 1, rcSegment.top, xIG + xStart + 2, rcSegment.bottom); - surface->Copy(rcCopyArea, from, (ll.xHighlightGuide == xIG) ? - pixmapIndentGuideHighlight : pixmapIndentGuide); + if (ll->chars[i] == '\t') { + // Manage tab display + surface->FillRectangle(rcSegment, textBack); + if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) { + surface->PenColour(textFore); + } + if (inIndentation && vsDraw.viewIndentationGuides) { + for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) { + if (xIG >= ll->positions[i] && xIG > 0) { + Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); + PRectangle rcCopyArea(xIG + xStart + 1, rcSegment.top, xIG + xStart + 2, rcSegment.bottom); + surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == xIG) ? + *pixmapIndentGuideHighlight : *pixmapIndentGuide); + } } } - } - if (vsDraw.viewWhitespace != wsInvisible) { - if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, - rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); - DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2); + if (vsDraw.viewWhitespace != wsInvisible) { + if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { + PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, + rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); + DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2); + } } - } - // Manage control character display - } - else if (IsControlCharacter(ll.chars[i])) { - inIndentation = false; - 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 to draw if really visible - enhances performance by not calling environment to - // draw strings that are completely past the right side of the window. - if (rcSegment.left <= rcLine.right) { - surface->DrawText(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll.chars + startseg, + } else if (IsControlCharacter(ll->chars[i])) { + // Manage control character display + inIndentation = false; + if (controlCharSymbol < 32) { + // Draw the character + const char *ctrlChar = ControlCharacterString(ll->chars[i]); + 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); + } else { + char cc[2] = { static_cast(controlCharSymbol), '\0' }; + surface->DrawTextNoClip(rcSegment, ctrlCharsFont, + rcSegment.top + vsDraw.maxAscent, + cc, 1, textBack, textFore); + } + } else { + // Manage normal display + surface->DrawTextNoClip(rcSegment, textFont, + rcSegment.top + vsDraw.maxAscent, ll->chars + startseg, i - startseg + 1, textFore, textBack); if (vsDraw.viewWhitespace != wsInvisible || (inIndentation && vsDraw.viewIndentationGuides)) { for (int cpos = 0; cpos <= i - startseg; cpos++) { - if (ll.chars[cpos + startseg] == ' ') { + if (ll->chars[cpos + startseg] == ' ') { if (vsDraw.viewWhitespace != wsInvisible) { if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2; - PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0); + int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2; + PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0); rcDot.right = rcDot.left + 1; rcDot.bottom = rcDot.top + 1; surface->FillRectangle(rcDot, textFore); } } if (inIndentation && vsDraw.viewIndentationGuides) { - int startSpace = ll.positions[cpos + startseg]; + int startSpace = ll->positions[cpos + startseg]; if (startSpace > 0 && (startSpace % indentWidth == 0)) { Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); PRectangle rcCopyArea(startSpace + xStart + 1, rcSegment.top, startSpace + xStart + 2, rcSegment.bottom); - surface->Copy(rcCopyArea, from, (ll.xHighlightGuide == ll.positions[cpos + startseg]) ? - pixmapIndentGuideHighlight : pixmapIndentGuide); + surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == ll->positions[cpos + startseg]) ? + *pixmapIndentGuideHighlight : *pixmapIndentGuide); } } } else { @@ -1151,18 +1671,18 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis 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]) { + 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)) { + indStart[indicnum] = ll->positions[indicPos + 1]; } - if (!(ll.indicators[indicPos + 1] & mask) && (ll.indicators[indicPos] & mask)) { + if (!(ll->indicators[indicPos + 1] & mask) && (ll->indicators[indicPos] & mask)) { PRectangle rcIndic( indStart[indicnum] + xStart, rcLine.top + vsDraw.maxAscent, - ll.positions[indicPos + 1] + xStart, + ll->positions[indicPos + 1] + xStart, rcLine.top + vsDraw.maxAscent + 3); vsDraw.indicators[indicnum].Draw(surface, rcIndic); } @@ -1173,10 +1693,11 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // End of the drawing of the current line // Fill in a PRectangle representing the end of line characters - int xEol = ll.positions[ll.numCharsInLine]; + int xEol = ll->positions[lineEnd] - subLineStart; rcSegment.left = xEol + xStart; rcSegment.right = xEol + vsDraw.aveCharWidth + xStart; - bool eolInSelection = (posLineEnd > ll.selStart) && (posLineEnd <= ll.selEnd) && (ll.selStart != ll.selEnd); + bool eolInSelection = (subLine == (ll->lines-1)) && + (posLineEnd > ll->selStart) && (posLineEnd <= ll->selEnd) && (ll->selStart != ll->selEnd); if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) { if (primarySelection) surface->FillRectangle(rcSegment, vsDraw.selbackground.allocated); @@ -1185,21 +1706,21 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } else if (overrideBackground) { surface->FillRectangle(rcSegment, background); } else { - surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated); } rcSegment.left = xEol + vsDraw.aveCharWidth + xStart; rcSegment.right = rcLine.right; if (overrideBackground) { surface->FillRectangle(rcSegment, background); - } else if (vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll.styles[ll.numCharsInLine] & styleMask].back.allocated); + } else 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 (vsDraw.edgeState == EDGE_LINE) { - int edgeX = ll.edgeColumn * vsDraw.spaceWidth; + int edgeX = theEdge * vsDraw.spaceWidth; rcSegment.left = edgeX + xStart; rcSegment.right = rcSegment.left + 1; surface->FillRectangle(rcSegment, vsDraw.edgecolour.allocated); @@ -1214,53 +1735,60 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { //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); + if (WrapLines()) { + // The wrapping process has changed the height of some lines so abandon this + // paint for a complete repaint. + paintState = paintAbandoned; + return; + } + + 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); + if (vs.selbarlight.desired == ColourDesired(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); + 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); + pixmapSelPattern->FillRectangle(rcPattern, vs.selbarlight.allocated); } } - if (!pixmapIndentGuide.Initialised()) { + if (!pixmapIndentGuide->Initialised()) { // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line - pixmapIndentGuide.InitPixMap(1, vs.lineHeight + 1, surfaceWindow); - pixmapIndentGuideHighlight.InitPixMap(1, vs.lineHeight + 1, surfaceWindow); + pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow); + pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow); PRectangle rcIG(0, 0, 1, vs.lineHeight); - pixmapIndentGuide.FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated); - pixmapIndentGuide.PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated); - pixmapIndentGuideHighlight.FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); - pixmapIndentGuideHighlight.PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); + pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated); + pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated); + pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); + pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) { - pixmapIndentGuide.MoveTo(0, stripe); - pixmapIndentGuide.LineTo(2, stripe); - pixmapIndentGuideHighlight.MoveTo(0, stripe); - pixmapIndentGuideHighlight.LineTo(2, stripe); + pixmapIndentGuide->MoveTo(0, stripe); + pixmapIndentGuide->LineTo(2, stripe); + pixmapIndentGuideHighlight->MoveTo(0, stripe); + pixmapIndentGuideHighlight->LineTo(2, stripe); } } if (bufferedDraw) { - if (!pixmapLine.Initialised()) { - pixmapLine.InitPixMap(rcClient.Width(), rcClient.Height(), + if (!pixmapLine->Initialised()) { + pixmapLine->InitPixMap(rcClient.Width(), rcClient.Height(), surfaceWindow); - pixmapSelMargin.InitPixMap(vs.fixedColumnWidth, + pixmapSelMargin->InitPixMap(vs.fixedColumnWidth, rcClient.Height(), surfaceWindow); } } surfaceWindow->SetPalette(&palette, true); - pixmapLine.SetPalette(&palette, !hasFocus); + pixmapLine->SetPalette(&palette, !hasFocus); //Platform::DebugPrintf("Paint: (%3d,%3d) ... (%3d,%3d)\n", // rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); @@ -1282,7 +1810,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // Ensure we are styled as far as we are painting. pdoc->EnsureStyledTo(endPosPaint); - + bool paintAbandonedByStyling = paintState == paintAbandoned; if (needUpdateUI) { NotifyUpdateUI(); needUpdateUI = false; @@ -1300,6 +1828,13 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // Either styling or NotifyUpdateUI noticed that painting is needed // outside the current painting rectangle //Platform::DebugPrintf("Abandoning paint\n"); + if (wrapState != eWrapNone) { + if (paintAbandonedByStyling) { + // Styling has spilled over a line end, such as occurs by starting a multiline + // comment. The width of subsequent text may have changed, so rewrap. + NeedWrapping(cs.DocFromDisplay(topLine)); + } + } return; } //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); @@ -1309,12 +1844,11 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { Surface *surface = surfaceWindow; if (bufferedDraw) { - surface = &pixmapLine; + surface = pixmapLine; } - surface->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); + surface->SetUnicodeMode(IsUnicodeMode()); int visibleLine = topLine + screenLinePaintFirst; - int line = cs.DocFromDisplay(visibleLine); int posCaret = currentPos; if (posDrag >= 0) @@ -1329,133 +1863,135 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { surfaceWindow->SetClip(rcTextArea); // Loop on visible lines - //GTimer *tim=g_timer_new(); + //double durLayout = 0.0; + //double durPaint = 0.0; + //double durCopy = 0.0; + //ElapsedTime etWhole; + int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times + LineLayout *ll = 0; while (visibleLine < cs.LinesDisplayed() && yposScreen < rcArea.bottom) { - //g_timer_start(tim); + + int lineDoc = cs.DocFromDisplay(visibleLine); //Platform::DebugPrintf("Painting line %d\n", line); + // Only visible lines should be handled by the code within the loop + PLATFORM_ASSERT(cs.GetVisible(lineDoc)); + int lineStartSet = cs.DisplayFromDoc(lineDoc); + int subLine = visibleLine - lineStartSet; // Copy this line and its styles from the document into local arrays // and determine the x position at which each character starts. - LineLayout ll; - LayoutLine(line, surface, vs, ll); - - ll.selStart = SelectionStart(line); - ll.selEnd = SelectionEnd(line); - ll.containsCaret = line == lineCaret; - if (hideSelection) { - ll.selStart = -1; - ll.selEnd = -1; - ll.containsCaret = false; + //ElapsedTime et; + if (lineDoc != lineDocPrevious) { + llc.Dispose(ll); + ll = RetrieveLineLayout(lineDoc); + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + lineDocPrevious = lineDoc; } - // Need to fix this up so takes account of Unicode and DBCS - ll.edgeColumn = theEdge; - - 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; - - // Highlight the current braces if any - if ((braces[0] >= posLineStart) && (braces[0] < posLineEnd)) { - int braceOffset = braces[0] - posLineStart; - if (braceOffset < ll.numCharsInLine) - ll.styles[braceOffset] = static_cast(bracesMatchStyle); - } - if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd)) { - int braceOffset = braces[1] - posLineStart; - if (braceOffset < ll.numCharsInLine) - ll.styles[braceOffset] = static_cast(bracesMatchStyle); - } - if ((braces[0] >= posLineStart && braces[1] <= posLineEnd) || - (braces[1] >= posLineStart && braces[0] <= posLineEnd)) { - ll.xHighlightGuide = highlightGuideColumn * vs.spaceWidth; - } - - // Draw the line - if (cs.GetVisible(line)) - DrawLine(surface, vs, line, visibleLine, xStart, rcLine, ll); - - bool expanded = cs.GetExpanded(line); - if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) { - if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.bottom = rcFoldLine.top + 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); + //durLayout += et.Duration(true); + + if (ll) { + ll->selStart = SelectionStart(lineDoc); + ll->selEnd = SelectionEnd(lineDoc); + ll->containsCaret = lineDoc == lineCaret; + if (hideSelection) { + ll->selStart = -1; + ll->selEnd = -1; + ll->containsCaret = false; } - } - if ( (expanded && (foldFlags & 8)) || (!expanded && (foldFlags & 16)) ) { - if (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.top = rcFoldLine.bottom - 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); + + PRectangle rcLine = rcClient; + rcLine.top = ypos; + rcLine.bottom = ypos + vs.lineHeight; + + Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1)); + // Highlight the current braces if any + ll->SetBracesHighlight(rangeLine, braces, static_cast(bracesMatchStyle), + highlightGuideColumn * vs.spaceWidth); + + // Draw the line + DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine); + //durPaint += et.Duration(true); + + // Restore the precvious styles for the brace highlights in case layout is in cache. + ll->RestoreBracesHighlight(rangeLine, braces); + + bool expanded = cs.GetExpanded(lineDoc); + if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) { + if (pdoc->GetLevel(lineDoc) & 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 offset = Platform::Minimum(posCaret - posLineStart, LineLayout::maxLineLength); - int xposCaret = ll.positions[offset] + xStart; - int widthOverstrikeCaret; - if (posCaret == pdoc->Length()) { // At end of document - widthOverstrikeCaret = vs.aveCharWidth; - } else if ((posCaret - posLineStart) >= ll.numCharsInLine) { // At end of line - widthOverstrikeCaret = vs.aveCharWidth; - } else { - widthOverstrikeCaret = ll.positions[offset + 1] - ll.positions[offset]; + if ( (expanded && (foldFlags & 8)) || (!expanded && (foldFlags & 16)) ) { + if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) { + PRectangle rcFoldLine = rcLine; + rcFoldLine.top = rcFoldLine.bottom - 1; + surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); + } } - if (widthOverstrikeCaret < 3) // Make sure its visible - widthOverstrikeCaret = 3; - if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) { - PRectangle rcCaret = rcLine; - int caretWidthOffset = 0; - if ((offset > 0) && (vs.caretWidth > 1)) - caretWidthOffset = 1; // Move back so overlaps both character cells. - if (posDrag >= 0) { - rcCaret.left = xposCaret - caretWidthOffset; - rcCaret.right = rcCaret.left + vs.caretWidth; - } else { - if (inOverstrike) { - rcCaret.top = rcCaret.bottom - 2; - rcCaret.left = xposCaret + 1; - rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; + + // Draw the Caret + if (lineDoc == lineCaret) { + int offset = Platform::Minimum(posCaret - rangeLine.start, ll->maxLineLength); + if ((offset >= ll->LineStart(subLine)) && + ((offset < ll->LineStart(subLine+1)) || offset == ll->numCharsInLine)) { + int xposCaret = ll->positions[offset] - ll->positions[ll->LineStart(subLine)] + xStart; + int widthOverstrikeCaret; + if (posCaret == pdoc->Length()) { // At end of document + widthOverstrikeCaret = vs.aveCharWidth; + } else if ((posCaret - rangeLine.start) >= ll->numCharsInLine) { // At end of line + widthOverstrikeCaret = vs.aveCharWidth; } else { - rcCaret.left = xposCaret - caretWidthOffset; - rcCaret.right = rcCaret.left + vs.caretWidth; + widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset]; + } + if (widthOverstrikeCaret < 3) // Make sure its visible + widthOverstrikeCaret = 3; + if (((caret.active && caret.on) || (posDrag >= 0)) && xposCaret >= 0) { + PRectangle rcCaret = rcLine; + int caretWidthOffset = 0; + if ((offset > 0) && (vs.caretWidth > 1)) + caretWidthOffset = 1; // Move back so overlaps both character cells. + if (posDrag >= 0) { + rcCaret.left = xposCaret - caretWidthOffset; + rcCaret.right = rcCaret.left + vs.caretWidth; + } else { + if (inOverstrike) { + rcCaret.top = rcCaret.bottom - 2; + rcCaret.left = xposCaret + 1; + rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; + } else { + rcCaret.left = xposCaret - caretWidthOffset; + rcCaret.right = rcCaret.left + vs.caretWidth; + } + } + surface->FillRectangle(rcCaret, vs.caretcolour.allocated); } } - 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); + rcClient.right, yposScreen + vs.lineHeight); + surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); } + //durCopy += et.Duration(true); } - + 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); + llc.Dispose(ll); + //if (durPaint < 0.00000001) + // durPaint = 0.00000001; // Right column limit indicator - - - PRectangle rcBeyondEOF = rcClient; rcBeyondEOF.left = vs.fixedColumnWidth; rcBeyondEOF.right = rcBeyondEOF.right; @@ -1469,6 +2005,9 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated); } } + //Platform::DebugPrintf( + //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n", + //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); NotifyPainted(); } } @@ -1476,18 +2015,18 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // Space (3 space characters) between line numbers and text when printing. #define lineNumberPrintSpace " " -Colour InvertedLight(Colour orig) { +ColourDesired InvertedLight(ColourDesired orig) { unsigned int r = orig.GetRed(); unsigned int g = orig.GetGreen(); unsigned int b = orig.GetBlue(); unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye unsigned int il = 0xff - l; if (l == 0) - return Colour(0xff, 0xff, 0xff); + return ColourDesired(0xff, 0xff, 0xff); r = r * il / l; g = g * il / l; b = b * il / l; - return Colour(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); + return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); } // This is mostly copied from the Paint method but with some things omitted @@ -1497,12 +2036,13 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { if (!pfr) return 0; - Surface *surface = new Surface(); - surface->Init(pfr->hdc); - surface->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); - Surface *surfaceMeasure = new Surface(); - surfaceMeasure->Init(pfr->hdcTarget); - surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage); + AutoSurface surface(pfr->hdc, IsUnicodeMode()); + if (!surface) + return 0; + AutoSurface surfaceMeasure(pfr->hdcTarget, IsUnicodeMode()); + if (!surfaceMeasure) { + return 0; + } ViewStyle vsPrint(vs); @@ -1531,18 +2071,18 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired); vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired); } else if (printColourMode == SC_PRINT_BLACKONWHITE) { - vsPrint.styles[sty].fore.desired = Colour(0, 0, 0); - vsPrint.styles[sty].back.desired = Colour(0xff, 0xff, 0xff); + vsPrint.styles[sty].fore.desired = ColourDesired(0, 0, 0); + vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); } else if (printColourMode == SC_PRINT_COLOURONWHITE) { - vsPrint.styles[sty].back.desired = Colour(0xff, 0xff, 0xff); + vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); } else if (printColourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { if (sty <= STYLE_DEFAULT) { - vsPrint.styles[sty].back.desired = Colour(0xff, 0xff, 0xff); + vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); } } } // White background for the line numbers - vsPrint.styles[STYLE_LINENUMBER].back.desired = Colour(0xff, 0xff, 0xff); + vsPrint.styles[STYLE_LINENUMBER].back.desired = ColourDesired(0xff, 0xff, 0xff); vsPrint.Refresh(*surfaceMeasure); // Ensure colours are set up @@ -1589,13 +2129,11 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { // Copy this line and its styles from the document into local arrays // and determine the x position at which each character starts. - LineLayout ll; - LayoutLine(line, surfaceMeasure, vsPrint, ll); + LineLayout ll(8000); + LayoutLine(line, surfaceMeasure, vsPrint, &ll); ll.selStart = -1; ll.selEnd = -1; ll.containsCaret = false; - // Need to fix this up so takes account of Unicode and DBCS - ll.edgeColumn = theEdge; PRectangle rcLine; rcLine.left = pfr->rc.left + lineNumberWidth; @@ -1611,7 +2149,7 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { // Right justify rcNumber.left -= surface->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, number, strlen(number)); - surface->DrawText(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, + surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, ypos + vsPrint.maxAscent, number, strlen(number), vsPrint.styles[STYLE_LINENUMBER].fore.allocated, vsPrint.styles[STYLE_LINENUMBER].back.allocated); @@ -1619,27 +2157,24 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) { // Draw the line surface->FlushCachedState(); - DrawLine(surface, vsPrint, line, line, xStart, rcLine, ll); + DrawLine(surface, vsPrint, line, line, xStart, rcLine, &ll); ypos += vsPrint.lineHeight; line++; } } - delete surface; - delete surfaceMeasure; - return endPosPrint; } // Empty method is overridden on GTK+ to show / hide scrollbars void Editor::ReconfigureScrollBars() {} -void Editor::SetScrollBarsTo(PRectangle) { +void Editor::SetScrollBars() { RefreshStyleData(); int nMax = cs.LinesDisplayed(); - int nPage = cs.LinesDisplayed() - MaxScrollPos() + 1; + int nPage = nMax - MaxScrollPos() + 1; bool modified = ModifyScrollBars(nMax, nPage); // TODO: ensure always showing as many lines as possible @@ -1654,9 +2189,18 @@ void Editor::SetScrollBarsTo(PRectangle) { //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage); } -void Editor::SetScrollBars() { - PRectangle rsClient = GetClientRectangle(); - SetScrollBarsTo(rsClient); +void Editor::ChangeSize() { + DropGraphics(); + SetScrollBars(); + if (wrapState != eWrapNone) { + PRectangle rcTextArea = GetClientRectangle(); + rcTextArea.left = vs.fixedColumnWidth; + rcTextArea.right -= vs.rightMarginWidth; + if (wrapWidth != rcTextArea.Width()) { + NeedWrapping(); + Redraw(); + } + } } void Editor::AddChar(char ch) { @@ -1666,7 +2210,7 @@ void Editor::AddChar(char ch) { AddCharUTF(s, 1); } -void Editor::AddCharUTF(char *s, unsigned int len) { +void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { bool wasSelection = currentPos != anchor; ClearSelection(); if (inOverstrike && !wasSelection) { @@ -1683,37 +2227,42 @@ void Editor::AddCharUTF(char *s, unsigned int len) { ShowCaretAtCurrentPosition(); SetLastXChosen(); - int byte = static_cast(s[0]); - if ((byte < 0xC0) || (1 == len)) { - // Handles UTF-8 characters between 0x01 and 0x7F and single byte - // characters when not in UTF-8 mode. - // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid - // characters representing themselves. + if (treatAsDBCS) { + NotifyChar((static_cast(s[0]) << 8) | + static_cast(s[1])); } else { - // Unroll 1 to 3 byte UTF-8 sequences. See reference data at: - // http://www.cl.cam.ac.uk/~mgk25/unicode.html - // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt - if (byte < 0xE0) { - int byte2 = static_cast(s[1]); - if ((byte2 & 0xC0) == 0x80) { - // Two-byte-character lead-byte followed by a trail-byte. - byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F)); - } - // A two-byte-character lead-byte not followed by trail-byte - // represents itself. - } else if (byte < 0xF0) { - int byte2 = static_cast(s[1]); - int byte3 = static_cast(s[2]); - if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) { - // Three-byte-character lead byte followed by two trail bytes. - byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | - (byte3 & 0x3F)); + int byte = static_cast(s[0]); + if ((byte < 0xC0) || (1 == len)) { + // Handles UTF-8 characters between 0x01 and 0x7F and single byte + // characters when not in UTF-8 mode. + // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid + // characters representing themselves. + } else { + // Unroll 1 to 3 byte UTF-8 sequences. See reference data at: + // http://www.cl.cam.ac.uk/~mgk25/unicode.html + // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + if (byte < 0xE0) { + int byte2 = static_cast(s[1]); + if ((byte2 & 0xC0) == 0x80) { + // Two-byte-character lead-byte followed by a trail-byte. + byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F)); + } + // A two-byte-character lead-byte not followed by trail-byte + // represents itself. + } else if (byte < 0xF0) { + int byte2 = static_cast(s[1]); + int byte3 = static_cast(s[2]); + if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) { + // Three-byte-character lead byte followed by two trail bytes. + byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | + (byte3 & 0x3F)); + } + // A three-byte-character lead-byte not followed by two trail-bytes + // represents itself. } - // A three-byte-character lead-byte not followed by two trail-bytes - // represents itself. } + NotifyChar(byte); } - NotifyChar(byte); } void Editor::ClearSelection() { @@ -1776,7 +2325,6 @@ void Editor::PasteRectangular(int pos, const char *ptr, int len) { return; } currentPos = pos; - int insertPos = currentPos; int xInsert = XFromPosition(currentPos); int line = pdoc->LineFromPosition(currentPos); bool prevCr = false; @@ -1798,18 +2346,16 @@ void Editor::PasteRectangular(int pos, const char *ptr, int len) { pdoc->InsertChar(currentPos, ' '); currentPos++; } - insertPos = currentPos; } prevCr = ptr[i] == '\r'; } else { pdoc->InsertString(currentPos, ptr + i, 1); currentPos++; - insertPos = currentPos; prevCr = false; } } pdoc->EndUndoAction(); - SetEmptySelection(insertPos); + SetEmptySelection(pos); } bool Editor::CanPaste() { @@ -1853,24 +2399,26 @@ void Editor::DelChar() { ShowCaretAtCurrentPosition(); } -void Editor::DelCharBack() { +void Editor::DelCharBack(bool allowLineStartDeletion) { if (currentPos == anchor) { int lineCurrentPos = pdoc->LineFromPosition(currentPos); - if (pdoc->GetColumn(currentPos) <= pdoc->GetLineIndentation(lineCurrentPos) && - pdoc->GetColumn(currentPos) > 0 && pdoc->backspaceUnindents) { - pdoc->BeginUndoAction(); - int indentation = pdoc->GetLineIndentation(lineCurrentPos); - int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); - if (indentation % indentationStep == 0) { - pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); + if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != currentPos)) { + if (pdoc->GetColumn(currentPos) <= pdoc->GetLineIndentation(lineCurrentPos) && + pdoc->GetColumn(currentPos) > 0 && pdoc->backspaceUnindents) { + pdoc->BeginUndoAction(); + int indentation = pdoc->GetLineIndentation(lineCurrentPos); + int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars); + if (indentation % indentationStep == 0) { + pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); + } else { + pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep)); + } + SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos)); + pdoc->EndUndoAction(); } else { - pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep)); + int newPos = pdoc->DelCharBack(currentPos); + SetEmptySelection(newPos); } - SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos)); - pdoc->EndUndoAction(); - } else { - int newPos = pdoc->DelCharBack(currentPos); - SetEmptySelection(newPos); } } else { ClearSelection(); @@ -1997,11 +2545,61 @@ void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) { NotifySavePoint(atSavePoint); } +void Editor::CheckModificationForWrap(DocModification mh) { + if ((mh.modificationType & SC_MOD_INSERTTEXT) || + (mh.modificationType & SC_MOD_DELETETEXT)) { + llc.Invalidate(LineLayout::llInvalid); + if (wrapState != eWrapNone) { + int lineDoc = pdoc->LineFromPosition(mh.position); + if (mh.linesAdded == 0) { + AutoSurface surface(IsUnicodeMode()); + LineLayout *ll = RetrieveLineLayout(lineDoc); + if (surface && ll) { + LayoutLine(lineDoc, surface, vs, ll, wrapWidth); + if (cs.GetHeight(lineDoc) != ll->lines) { + NeedWrapping(lineDoc-1); + Redraw(); + } + } else { + NeedWrapping(lineDoc); + } + llc.Dispose(ll); + } else { + NeedWrapping(lineDoc); + } + } + } +} + +// Move a position so it is still after the same character as before the insertion. +static inline int MovePositionForInsertion(int position, int startInsertion, int length) { + if (position > startInsertion) { + return position + length; + } + return position; +} + +// Move a position so it is still after the same character as before the deletion if that +// character is still present else after the previous surviving character. +static inline int MovePositionForDeletion(int position, int startDeletion, int length) { + if (position > startDeletion) { + int endDeletion = startDeletion + length; + if (position > endDeletion) { + return position - length; + } else { + return startDeletion; + } + } else { + return position; + } +} + void Editor::NotifyModified(Document*, DocModification mh, void *) { needUpdateUI = true; if (paintState == painting) { CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length)); } else if (paintState == notPainting) { + CheckModificationForWrap(mh); if (mh.modificationType & SC_MOD_CHANGESTYLE) { if (mh.position < pdoc->LineStart(topLine)) { // Styling performed before this view @@ -2012,48 +2610,15 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { } 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; - } - } + currentPos = MovePositionForInsertion(currentPos, mh.position, mh.length); + anchor = MovePositionForInsertion(anchor, mh.position, mh.length); + braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length); + braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length); + } else if (mh.modificationType & SC_MOD_DELETETEXT) { + currentPos = MovePositionForDeletion(currentPos, mh.position, mh.length); + anchor = MovePositionForDeletion(anchor, mh.position, mh.length); + braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length); + braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length); } if (cs.LinesDisplayed() < cs.LinesInDoc()) { // Some lines are hidden so may need shown. @@ -2109,8 +2674,6 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { NotifyChange(); // Send EN_CHANGE } - - SCNotification scn; scn.nmhdr.code = SCN_MODIFIED; scn.position = mh.position; @@ -2192,6 +2755,9 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long case SCI_LINETRANSPOSE: case SCI_LOWERCASE: case SCI_UPPERCASE: + case SCI_LINESCROLLDOWN: + case SCI_LINESCROLLUP: + case SCI_DELETEBACKNOTLINE: break; // Filter out all others like display changes. Also, newlines are redundant @@ -2406,7 +2972,12 @@ int Editor::KeyCommand(unsigned int iMessage) { CancelModes(); break; case SCI_DELETEBACK: - DelCharBack(); + DelCharBack(true); + SetLastXChosen(); + EnsureCaretVisible(); + break; + case SCI_DELETEBACKNOTLINE: + DelCharBack(false); SetLastXChosen(); EnsureCaretVisible(); break; @@ -2453,11 +3024,13 @@ int Editor::KeyCommand(unsigned int iMessage) { case SCI_ZOOMIN: if (vs.zoomLevel < 20) vs.zoomLevel++; + NeedWrapping(); InvalidateStyleRedraw(); break; case SCI_ZOOMOUT: if (vs.zoomLevel > -10) vs.zoomLevel--; + NeedWrapping(); InvalidateStyleRedraw(); break; case SCI_DELWORDLEFT: { @@ -2654,10 +3227,10 @@ long Editor::FindText( TextToFind *ft = reinterpret_cast(lParam); int lengthFound = strlen(ft->lpstrText); int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, - wParam & SCFIND_MATCHCASE, - wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART, - wParam & SCFIND_REGEXP, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, &lengthFound); if (pos != -1) { ft->chrgText.cpMin = pos; @@ -2697,17 +3270,17 @@ long Editor::SearchText( int lengthFound = strlen(txt); if (iMessage == SCI_SEARCHNEXT) { pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, - wParam & SCFIND_MATCHCASE, - wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART, - wParam & SCFIND_REGEXP, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, &lengthFound); } else { pos = pdoc->FindText(searchAnchor, 0, txt, - wParam & SCFIND_MATCHCASE, - wParam & SCFIND_WHOLEWORD, - wParam & SCFIND_WORDSTART, - wParam & SCFIND_REGEXP, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, &lengthFound); } @@ -2725,10 +3298,10 @@ long Editor::SearchText( long Editor::SearchInTarget(const char *text, int length) { int lengthFound = length; int pos = pdoc->FindText(targetStart, targetEnd, text, - searchFlags & SCFIND_MATCHCASE, - searchFlags & SCFIND_WHOLEWORD, - searchFlags & SCFIND_WORDSTART, - searchFlags & SCFIND_REGEXP, + (searchFlags & SCFIND_MATCHCASE) != 0, + (searchFlags & SCFIND_WHOLEWORD) != 0, + (searchFlags & SCFIND_WORDSTART) != 0, + (searchFlags & SCFIND_REGEXP) != 0, &lengthFound); if (pos != -1) { targetStart = pos; @@ -3108,7 +3681,7 @@ void Editor::ButtonMove(Point pt) { SetSelection(movePos); } else if (selectionType == selWord) { // Continue selecting by word - if (currentPos > originalAnchorPos) { // Moved forward + if (movePos >= originalAnchorPos) { // Moved forward SetSelection(pdoc->ExtendWordSelect(movePos, 1), pdoc->ExtendWordSelect(originalAnchorPos, -1)); } else { // Moved backward @@ -3196,6 +3769,9 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { lastClickTime = curTime; lastClick = pt; lastXChosen = pt.x; + if (selType == selStream) { + SetLastXChosen(); + } inDragDrop = false; EnsureCaretVisible(false); } @@ -3216,7 +3792,7 @@ void Editor::Tick() { InvalidateCaret(); } } - if ((dwellDelay < SC_TIME_FOREVER) && + if ((dwellDelay < SC_TIME_FOREVER) && (ticksToDwell > 0) && (!HaveMouseCapture())) { ticksToDwell -= timer.tickSize; @@ -3232,7 +3808,6 @@ void Editor::SetFocusState(bool focusState) { NotifyFocus(hasFocus); if (hasFocus) { ShowCaretAtCurrentPosition(); - InvalidateCaret(); } else { DropCaret(); } @@ -3381,6 +3956,8 @@ void Editor::SetDocPointer(Document *document) { // Reset the contraction state to fully shown. cs.Clear(); cs.InsertLines(0, pdoc->LinesTotal() - 1); + llc.Deallocate(); + NeedWrapping(); pdoc->AddWatcher(this, 0); Redraw(); @@ -3427,8 +4004,12 @@ void Editor::ToggleContraction(int line) { } // Recurse up from this line to find any folds that prevent this line from being visible -// and unfold them all. +// and unfold them all-> void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { + + // In case in need of wrapping to ensure DisplayFromDoc works. + WrapLines(); + if (!cs.GetVisible(lineDoc)) { int lineParent = pdoc->GetFoldParent(lineDoc); if (lineParent >= 0) { @@ -3483,6 +4064,10 @@ int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) { return length; } +bool Editor::IsUnicodeMode() const { + return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage); +} + static bool ValidMargin(unsigned long wParam) { return wParam < ViewStyle::margins; } @@ -3511,11 +4096,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETTEXT: { if (lParam == 0) - return FALSE; + return 0; pdoc->DeleteChars(0, pdoc->Length()); SetEmptySelection(0); pdoc->InsertString(0, reinterpret_cast(lParam)); - return TRUE; + return 1; } case SCI_GETTEXTLENGTH: @@ -3547,7 +4132,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_CANUNDO: - return pdoc->CanUndo() ? TRUE : FALSE; + return pdoc->CanUndo() ? 1 : 0; case SCI_EMPTYUNDOBUFFER: pdoc->DeleteUndoHistory(); @@ -3681,15 +4266,23 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_LINESCROLL: ScrollTo(topLine + lParam); HorizontalScrollTo(xOffset + wParam * vs.spaceWidth); - return TRUE; + return 1; + + case SCI_SETXOFFSET: + xOffset = wParam; + Redraw(); + break; + + case SCI_GETXOFFSET: + return xOffset; case SCI_SCROLLCARET: EnsureCaretVisible(); break; case SCI_SETREADONLY: - pdoc->SetReadOnly(wParam); - return TRUE; + pdoc->SetReadOnly(wParam != 0); + return 1; case SCI_GETREADONLY: return pdoc->IsReadOnly(); @@ -3731,12 +4324,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } case SCI_HIDESELECTION: - hideSelection = wParam; + hideSelection = wParam != 0; Redraw(); break; case SCI_FORMATRANGE: - return FormatRange(wParam, reinterpret_cast(lParam)); + return FormatRange(wParam != 0, reinterpret_cast(lParam)); case SCI_GETMARGINLEFT: return vs.leftMarginWidth; @@ -3746,11 +4339,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINLEFT: vs.leftMarginWidth = lParam; + NeedWrapping(); InvalidateStyleRedraw(); break; case SCI_SETMARGINRIGHT: vs.rightMarginWidth = lParam; + NeedWrapping(); InvalidateStyleRedraw(); break; @@ -3799,7 +4394,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return 0; case SCI_SETUNDOCOLLECTION: - pdoc->SetUndoCollection(wParam); + pdoc->SetUndoCollection(wParam != 0); return 0; case SCI_GETUNDOCOLLECTION: @@ -3908,7 +4503,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } case SCI_CANREDO: - return pdoc->CanRedo() ? TRUE : FALSE; + return pdoc->CanRedo() ? 1 : 0; case SCI_MARKERLINEFROMHANDLE: return pdoc->LineFromHandle(wParam); @@ -3982,7 +4577,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_SETBUFFEREDDRAW: - bufferedDraw = wParam; + bufferedDraw = wParam != 0; break; case SCI_GETBUFFEREDDRAW: @@ -4006,7 +4601,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->indentInChars; case SCI_SETUSETABS: - pdoc->useTabs = wParam; + pdoc->useTabs = wParam != 0; InvalidateStyleRedraw(); break; @@ -4024,14 +4619,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->GetLineIndentPosition(wParam); case SCI_SETTABINDENTS: - pdoc->tabIndents = wParam; + pdoc->tabIndents = wParam != 0; break; case SCI_GETTABINDENTS: return pdoc->tabIndents; case SCI_SETBACKSPACEUNINDENTS: - pdoc->backspaceUnindents = wParam; + pdoc->backspaceUnindents = wParam != 0; break; case SCI_GETBACKSPACEUNINDENTS: @@ -4041,24 +4636,50 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { dwellDelay = wParam; ticksToDwell = dwellDelay; break; - + case SCI_GETMOUSEDWELLTIME: return dwellDelay; - + + case SCI_WORDSTARTPOSITION: + return pdoc->ExtendWordSelect(wParam, -1, lParam != 0); + + case SCI_WORDENDPOSITION: + return pdoc->ExtendWordSelect(wParam, 1, lParam != 0); + + case SCI_SETWRAPMODE: + wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone; + NeedWrapping(); + xOffset = 0; + InvalidateStyleRedraw(); + ReconfigureScrollBars(); + break; + + case SCI_GETWRAPMODE: + return wrapState; + + case SCI_SETLAYOUTCACHE: + llc.SetLevel(wParam); + break; + + case SCI_GETLAYOUTCACHE: + return llc.GetLevel(); + case SCI_GETCOLUMN: return pdoc->GetColumn(wParam); case SCI_SETHSCROLLBAR : - horizontalScrollBarVisible = wParam; - SetScrollBars(); - ReconfigureScrollBars(); + if (horizontalScrollBarVisible != (wParam != 0)) { + horizontalScrollBarVisible = wParam != 0; + SetScrollBars(); + ReconfigureScrollBars(); + } break; case SCI_GETHSCROLLBAR: return horizontalScrollBarVisible; case SCI_SETINDENTATIONGUIDES: - vs.viewIndentationGuides = wParam; + vs.viewIndentationGuides = wParam != 0; Redraw(); break; @@ -4086,7 +4707,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return pdoc->dbcsCodePage; case SCI_SETUSEPALETTE: - palette.allowRealization = wParam; + palette.allowRealization = wParam != 0; InvalidateStyleRedraw(); break; @@ -4102,13 +4723,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_MARKERSETFORE: if (wParam <= MARKER_MAX) - vs.markers[wParam].fore.desired = Colour(lParam); + vs.markers[wParam].fore.desired = ColourDesired(lParam); InvalidateStyleData(); RedrawSelMargin(); break; case SCI_MARKERSETBACK: if (wParam <= MARKER_MAX) - vs.markers[wParam].back.desired = Colour(lParam); + vs.markers[wParam].back.desired = ColourDesired(lParam); InvalidateStyleData(); RedrawSelMargin(); break; @@ -4161,6 +4782,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINWIDTHN: if (ValidMargin(wParam)) { vs.ms[wParam].width = lParam; + NeedWrapping(); InvalidateStyleRedraw(); } break; @@ -4186,7 +4808,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETMARGINSENSITIVEN: if (ValidMargin(wParam)) { - vs.ms[wParam].sensitive = lParam; + vs.ms[wParam].sensitive = lParam != 0; InvalidateStyleRedraw(); } break; @@ -4204,31 +4826,31 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_STYLESETFORE: if (wParam <= STYLE_MAX) { - vs.styles[wParam].fore.desired = Colour(lParam); + vs.styles[wParam].fore.desired = ColourDesired(lParam); InvalidateStyleRedraw(); } break; case SCI_STYLESETBACK: if (wParam <= STYLE_MAX) { - vs.styles[wParam].back.desired = Colour(lParam); + vs.styles[wParam].back.desired = ColourDesired(lParam); InvalidateStyleRedraw(); } break; case SCI_STYLESETBOLD: if (wParam <= STYLE_MAX) { - vs.styles[wParam].bold = lParam; + vs.styles[wParam].bold = lParam != 0; InvalidateStyleRedraw(); } break; case SCI_STYLESETITALIC: if (wParam <= STYLE_MAX) { - vs.styles[wParam].italic = lParam; + vs.styles[wParam].italic = lParam != 0; InvalidateStyleRedraw(); } break; case SCI_STYLESETEOLFILLED: if (wParam <= STYLE_MAX) { - vs.styles[wParam].eolFilled = lParam; + vs.styles[wParam].eolFilled = lParam != 0; InvalidateStyleRedraw(); } break; @@ -4248,7 +4870,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_STYLESETUNDERLINE: if (wParam <= STYLE_MAX) { - vs.styles[wParam].underline = lParam; + vs.styles[wParam].underline = lParam != 0; InvalidateStyleRedraw(); } break; @@ -4266,7 +4888,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_STYLESETVISIBLE: if (wParam <= STYLE_MAX) { - vs.styles[wParam].visible = lParam; + vs.styles[wParam].visible = lParam != 0; + InvalidateStyleRedraw(); + } + break; + case SCI_STYLESETCHANGEABLE: + if (wParam <= STYLE_MAX) { + vs.styles[wParam].changeable = lParam != 0; InvalidateStyleRedraw(); } break; @@ -4294,7 +4922,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCARETLINEVISIBLE: return vs.showCaretLineBackground; case SCI_SETCARETLINEVISIBLE: - vs.showCaretLineBackground = wParam; + vs.showCaretLineBackground = wParam != 0; InvalidateStyleRedraw(); break; case SCI_GETCARETLINEBACK: @@ -4344,7 +4972,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return cs.GetVisible(wParam); case SCI_SETFOLDEXPANDED: - if (cs.SetExpanded(wParam, lParam)) { + if (cs.SetExpanded(wParam, lParam != 0)) { RedrawSelMargin(); } break; @@ -4391,19 +5019,19 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return LinesOnScreen(); case SCI_SETSELFORE: - vs.selforeset = wParam; - vs.selforeground.desired = Colour(lParam); + vs.selforeset = wParam != 0; + vs.selforeground.desired = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETSELBACK: - vs.selbackset = wParam; - vs.selbackground.desired = Colour(lParam); + vs.selbackset = wParam != 0; + vs.selbackground.desired = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETCARETFORE: - vs.caretcolour.desired = Colour(wParam); + vs.caretcolour.desired = ColourDesired(wParam); InvalidateStyleRedraw(); break; @@ -4449,7 +5077,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETFORE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].fore.desired = Colour(lParam); + vs.indicators[wParam].fore.desired = ColourDesired(lParam); InvalidateStyleRedraw(); } break; @@ -4507,6 +5135,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_WORDPARTLEFTEXTEND: case SCI_WORDPARTRIGHT: case SCI_WORDPARTRIGHTEXTEND: + case SCI_DELETEBACKNOTLINE: return KeyCommand(iMessage); case SCI_BRACEHIGHLIGHT: @@ -4526,12 +5155,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.viewEOL; case SCI_SETVIEWEOL: - vs.viewEOL = wParam; + vs.viewEOL = wParam != 0; Redraw(); break; case SCI_SETZOOM: vs.zoomLevel = wParam; + NeedWrapping(); InvalidateStyleRedraw(); break; @@ -4558,12 +5188,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.edgecolour.desired.AsLong(); case SCI_SETEDGECOLOUR: - vs.edgecolour.desired = Colour(wParam); + vs.edgecolour.desired = ColourDesired(wParam); InvalidateStyleRedraw(); break; case SCI_GETDOCPOINTER: - return reinterpret_cast(pdoc); + return reinterpret_cast(pdoc); case SCI_SETDOCPOINTER: SetDocPointer(reinterpret_cast(lParam)); @@ -4572,7 +5202,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_CREATEDOCUMENT: { Document *doc = new Document(); doc->AddRef(); - return reinterpret_cast(doc); + return reinterpret_cast(doc); } case SCI_ADDREFDOCUMENT: @@ -4599,14 +5229,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return (selType == selRectangle) ? 1 : 0; case SCI_SETOVERTYPE: - inOverstrike = wParam; + inOverstrike = wParam != 0; break; case SCI_GETOVERTYPE: - return inOverstrike ? TRUE : FALSE; + return inOverstrike ? 1 : 0; case SCI_SETFOCUS: - SetFocusState(wParam); + SetFocusState(wParam != 0); break; case SCI_GETFOCUS: @@ -4620,7 +5250,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return errorStatus; case SCI_SETMOUSEDOWNCAPTURES: - mouseDownCaptures = wParam; + mouseDownCaptures = wParam != 0; break; case SCI_GETMOUSEDOWNCAPTURES: @@ -4634,6 +5264,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCURSOR: return cursorMode; + case SCI_SETCONTROLCHARSYMBOL: + controlCharSymbol = wParam; + break; + + case SCI_GETCONTROLCHARSYMBOL: + return controlCharSymbol; + case SCI_STARTRECORD: recordingMacro = true; return 0; diff --git a/contrib/src/stc/scintilla/src/Editor.h b/contrib/src/stc/scintilla/src/Editor.h index a51fd86f91..d9719dc534 100644 --- a/contrib/src/stc/scintilla/src/Editor.h +++ b/contrib/src/stc/scintilla/src/Editor.h @@ -2,7 +2,7 @@ /** @file Editor.h ** Defines the main editor class. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef EDITOR_H @@ -15,7 +15,7 @@ public: bool active; bool on; int period; - + Caret(); }; @@ -26,28 +26,89 @@ public: bool ticking; int ticksToWait; enum {tickSize = 100}; - int tickerID; - + TickerID tickerID; + Timer(); }; /** */ class LineLayout { -public: +private: + friend class LineLayoutCache; + int *lineStarts; + int lenLineStarts; /// Drawing is only performed for @a maxLineLength characters on each line. - enum {maxLineLength = 4000}; + int lineNumber; + bool inCache; +public: + enum { wrapWidthInfinite = 0x7ffffff }; + int maxLineLength; int numCharsInLine; + enum validLevel { llInvalid, llPositions, llLines } validity; int xHighlightGuide; bool highlightColumn; int selStart; int selEnd; bool containsCaret; int edgeColumn; - char chars[maxLineLength+1]; - char styles[maxLineLength+1]; - char indicators[maxLineLength+1]; - int positions[maxLineLength+1]; + char *chars; + char *styles; + char *indicators; + int *positions; + char bracePreviousStyles[2]; + + // Wrapped line support + int widthLine; + int lines; + + LineLayout(int maxLineLength_); + virtual ~LineLayout(); + void Resize(int maxLineLength_); + void Free(); + void Invalidate(validLevel validity_); + int LineStart(int line) { + if (line <= 0) { + return 0; + } else if ((line >= lines) || !lineStarts) { + return numCharsInLine; + } else { + return lineStarts[line]; + } + } + void SetLineStart(int line, int start); + void SetBracesHighlight(Range rangeLine, Position braces[], + char bracesMatchStyle, int xHighlight); + void RestoreBracesHighlight(Range rangeLine, Position braces[]); +}; + +/** + */ +class LineLayoutCache { + int level; + int length; + int size; + LineLayout **cache; + bool allInvalidated; + int styleClock; + void Allocate(int length_); + void AllocateForLevel(int linesOnScreen, int linesInDoc); +public: + LineLayoutCache(); + virtual ~LineLayoutCache(); + void Deallocate(); + enum { + llcNone=SC_CACHE_NONE, + llcCaret=SC_CACHE_CARET, + llcPage=SC_CACHE_PAGE, + llcDocument=SC_CACHE_DOCUMENT + }; + void Invalidate(LineLayout::validLevel validity_); + void SetLevel(int level_); + int GetLevel() { return level; } + LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, + int linesOnScreen, int linesInDoc); + void Dispose(LineLayout *ll); }; class SelectionText { @@ -70,6 +131,38 @@ public: } }; +/** + * A smart pointer class to ensure Surfaces are set up and deleted correctly. + */ +class AutoSurface { +private: + Surface *surf; +public: + AutoSurface(bool unicodeMode) { + surf = Surface::Allocate(); + if (surf) { + surf->Init(); + surf->SetUnicodeMode(unicodeMode); + } + } + AutoSurface(SurfaceID sid, bool unicodeMode) { + surf = Surface::Allocate(); + if (surf) { + surf->Init(sid); + surf->SetUnicodeMode(unicodeMode); + } + } + ~AutoSurface() { + delete surf; + } + Surface *operator->() const { + return surf; + } + operator Surface *() const { + return surf; + } +}; + /** */ class Editor : public DocWatcher { @@ -85,20 +178,21 @@ protected: // ScintillaBase subclass needs access to much of Editor /** Style resources may be expensive to allocate so are cached between uses. * When a style attribute is changed, this cache is flushed. */ - bool stylesValid; + bool stylesValid; ViewStyle vs; Palette palette; int printMagnification; int printColourMode; int cursorMode; + int controlCharSymbol; bool hasFocus; bool hideSelection; bool inOverstrike; int errorStatus; bool mouseDownCaptures; - + /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to * the screen. This avoids flashing but is about 30% slower. */ bool bufferedDraw; @@ -106,12 +200,14 @@ protected: // ScintillaBase subclass needs access to much of Editor int xOffset; ///< Horizontal scrolled amount in pixels int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret bool horizontalScrollBarVisible; - - Surface pixmapLine; - Surface pixmapSelMargin; - Surface pixmapSelPattern; - Surface pixmapIndentGuide; - Surface pixmapIndentGuideHighlight; + + Surface *pixmapLine; + Surface *pixmapSelMargin; + Surface *pixmapSelPattern; + Surface *pixmapIndentGuide; + Surface *pixmapIndentGuideHighlight; + + LineLayoutCache llc; KeyMap kmap; @@ -141,32 +237,32 @@ protected: // ScintillaBase subclass needs access to much of Editor int searchFlags; int topLine; int posTopLine; - + bool needUpdateUI; Position braces[2]; int bracesMatchStyle; int highlightGuideColumn; - + int theEdge; enum { notPainting, painting, paintAbandoned } paintState; PRectangle rcPaint; bool paintingAllText; - + int modEventMask; - + SelectionText drag; enum { selStream, selRectangle, selRectangleFixed } selType; int xStartSelect; int xEndSelect; bool primarySelection; - + int caretPolicy; int caretSlop; int visiblePolicy; int visibleSlop; - + int searchAnchor; bool recordingMacro; @@ -174,6 +270,11 @@ protected: // ScintillaBase subclass needs access to much of Editor int foldFlags; ContractionState cs; + // Wrapping support + enum { eWrapNone, eWrapWord } wrapState; + int wrapWidth; + int docLineLastWrapped; + Document *pdoc; Editor(); @@ -189,7 +290,7 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual PRectangle GetClientRectangle(); PRectangle GetTextRectangle(); - + int LinesOnScreen(); int LinesToScroll(); int MaxScrollPos(); @@ -200,13 +301,13 @@ protected: // ScintillaBase subclass needs access to much of Editor 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); @@ -223,16 +324,22 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void ScrollText(int linesToMove); void HorizontalScrollTo(int xPos); void MoveCaretInsideView(); + int DisplayFromPosition(int pos); void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); void ShowCaretAtCurrentPosition(); void DropCaret(); void InvalidateCaret(); + void NeedWrapping(int docLineStartWrapping=0); + bool WrapLines(); + int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault); 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 lineVisible, int xStart, - PRectangle rcLine, LineLayout &ll); + LineLayout *RetrieveLineLayout(int lineNumber); + void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, + int width=LineLayout::wrapWidthInfinite); + void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, + PRectangle rcLine, LineLayout *ll, int subLine=0); void Paint(Surface *surfaceWindow, PRectangle rcArea); long FormatRange(bool draw, RangeToFormat *pfr); @@ -240,11 +347,11 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void SetHorizontalScrollPos() = 0; virtual bool ModifyScrollBars(int nMax, int nPage) = 0; virtual void ReconfigureScrollBars(); - void SetScrollBarsTo(PRectangle rsClient); void SetScrollBars(); + void ChangeSize(); void AddChar(char ch); - virtual void AddCharUTF(char *s, unsigned int len); + virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); void ClearSelection(); void ClearAll(); void ClearDocumentStyle(); @@ -258,11 +365,12 @@ protected: // ScintillaBase subclass needs access to much of Editor void Undo(); void Redo(); void DelChar(); - void DelCharBack(); + void DelCharBack(bool allowLineStartDeletion); virtual void ClaimSelection() = 0; virtual void NotifyChange() = 0; virtual void NotifyFocus(bool focus); + virtual int GetCtrlID() { return ctrlID; } virtual void NotifyParent(SCNotification scn) = 0; virtual void NotifyStyleToNeeded(int endStyleNeeded); void NotifyChar(int ch); @@ -275,9 +383,10 @@ protected: // ScintillaBase subclass needs access to much of Editor bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt); void NotifyNeedShown(int pos, int len); void NotifyDwelling(Point pt, bool state); - + void NotifyModifyAttempt(Document *document, void *userData); void NotifySavePoint(Document *document, void *userData, bool atSavePoint); + void CheckModificationForWrap(DocModification mh); void NotifyModified(Document *document, DocModification mh, void *userData); void NotifyDeleted(Document *document, void *userData); void NotifyStyleNeeded(Document *doc, void *userData, int endPos); @@ -328,21 +437,23 @@ protected: // ScintillaBase subclass needs access to much of Editor 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 lineDoc, bool enforcePolicy); int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; - + public: - // Public so scintilla_send_message can use it + // Public so the COM thunks can access it. + bool IsUnicodeMode() const; + // Public so scintilla_send_message can use it. virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - // Public so scintilla_set_id can use it - int ctrlID; + // Public so scintilla_set_id can use it. + int ctrlID; }; #endif diff --git a/contrib/src/stc/scintilla/src/Indicator.h b/contrib/src/stc/scintilla/src/Indicator.h index a19b46b5e2..56e9420bcc 100644 --- a/contrib/src/stc/scintilla/src/Indicator.h +++ b/contrib/src/stc/scintilla/src/Indicator.h @@ -14,7 +14,7 @@ class Indicator { public: int style; ColourPair fore; - Indicator() : style(INDIC_PLAIN), fore(Colour(0,0,0)) { + Indicator() : style(INDIC_PLAIN), fore(ColourDesired(0,0,0)) { } void Draw(Surface *surface, PRectangle &rc); }; diff --git a/contrib/src/stc/scintilla/src/KeyMap.cxx b/contrib/src/stc/scintilla/src/KeyMap.cxx index e1fe8e0322..761df4c8ff 100644 --- a/contrib/src/stc/scintilla/src/KeyMap.cxx +++ b/contrib/src/stc/scintilla/src/KeyMap.cxx @@ -62,7 +62,7 @@ unsigned int KeyMap::Find(int key, int modifiers) { return 0; } -KeyToCommand KeyMap::MapDefault[] = { +const KeyToCommand KeyMap::MapDefault[] = { {SCK_DOWN, SCI_NORM, SCI_LINEDOWN}, {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND}, {SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN}, diff --git a/contrib/src/stc/scintilla/src/KeyMap.h b/contrib/src/stc/scintilla/src/KeyMap.h index 8232b7160b..364df684f6 100644 --- a/contrib/src/stc/scintilla/src/KeyMap.h +++ b/contrib/src/stc/scintilla/src/KeyMap.h @@ -30,7 +30,7 @@ class KeyMap { KeyToCommand *kmap; int len; int alloc; - static KeyToCommand MapDefault[]; + static const KeyToCommand MapDefault[]; public: KeyMap(); diff --git a/contrib/src/stc/scintilla/src/KeyWords.cxx b/contrib/src/stc/scintilla/src/KeyWords.cxx index 756037a9a4..d1eddef5ff 100644 --- a/contrib/src/stc/scintilla/src/KeyWords.cxx +++ b/contrib/src/stc/scintilla/src/KeyWords.cxx @@ -2,7 +2,7 @@ /** @file KeyWords.cxx ** Colourise for particular languages. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -19,15 +19,15 @@ #include "Scintilla.h" #include "SciLexer.h" -LexerModule *LexerModule::base = 0; +const LexerModule *LexerModule::base = 0; int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1; LexerModule::LexerModule(int language_, LexerFunction fnLexer_, const char *languageName_, LexerFunction fnFolder_) : language(language_), - languageName(languageName_), fnLexer(fnLexer_), - fnFolder(fnFolder_) { + fnFolder(fnFolder_), + languageName(languageName_) { next = base; base = this; if (language == SCLEX_AUTOMATIC) { @@ -36,8 +36,8 @@ LexerModule::LexerModule(int language_, LexerFunction fnLexer_, } } -LexerModule *LexerModule::Find(int language) { - LexerModule *lm = base; +const LexerModule *LexerModule::Find(int language) { + const LexerModule *lm = base; while (lm) { if (lm->language == language) { return lm; @@ -47,9 +47,9 @@ LexerModule *LexerModule::Find(int language) { return 0; } -LexerModule *LexerModule::Find(const char *languageName) { +const LexerModule *LexerModule::Find(const char *languageName) { if (languageName) { - LexerModule *lm = base; + const LexerModule *lm = base; while (lm) { if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) { return lm; @@ -61,13 +61,13 @@ LexerModule *LexerModule::Find(const char *languageName) { } void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) { + WordList *keywordlists[], Accessor &styler) const { if (fnLexer) fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler); } void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) { + WordList *keywordlists[], Accessor &styler) const { if (fnFolder) { int lineCurrent = styler.GetLine(startPos); // Move back one line in case deletion wrecked current line fold state @@ -98,6 +98,10 @@ static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[ LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); #ifdef __vms +#define LINK_LEXERS +#endif + +#ifdef LINK_LEXERS // The following code forces a reference to all of the Scintilla lexers. // If we don't do something like this, then the linker tends to "optimize" @@ -106,8 +110,13 @@ LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); // Taken from wxWindow's stc.cpp. Walter. int wxForceScintillaLexers(void) { + return Scintilla_LinkLexers(); +} + +int Scintilla_LinkLexers() { extern LexerModule lmAda; extern LexerModule lmAVE; + extern LexerModule lmBaan; extern LexerModule lmBatch; extern LexerModule lmConf; extern LexerModule lmCPP; @@ -120,6 +129,7 @@ int wxForceScintillaLexers(void) { extern LexerModule lmLISP; extern LexerModule lmLua; extern LexerModule lmMake; + extern LexerModule lmMatlab; extern LexerModule lmPascal; extern LexerModule lmPerl; extern LexerModule lmProps; @@ -128,10 +138,12 @@ int wxForceScintillaLexers(void) { extern LexerModule lmSQL; extern LexerModule lmVB; extern LexerModule lmXML; + extern LexerModule lmBullant; if ( &lmAda && &lmAVE + && &lmBaan && &lmConf && &lmDiff && &lmLatex @@ -142,6 +154,7 @@ int wxForceScintillaLexers(void) { && &lmProps && &lmErrorList && &lmMake + && &lmMatlab && &lmBatch && &lmPerl && &lmPython @@ -153,6 +166,7 @@ int wxForceScintillaLexers(void) { && &lmLISP && &lmLua && &lmNull + && &lmBullant ) { return 1; diff --git a/contrib/src/stc/scintilla/src/LexAVE.cxx b/contrib/src/stc/scintilla/src/LexAVE.cxx index a7422743fa..dfd15f02f1 100644 --- a/contrib/src/stc/scintilla/src/LexAVE.cxx +++ b/contrib/src/stc/scintilla/src/LexAVE.cxx @@ -26,7 +26,7 @@ static void ColouriseAveDoc(unsigned int startPos, int length, int initStyle, Wo styler.StartAt(startPos); - bool fold = styler.GetPropertyInt("fold"); + bool fold = styler.GetPropertyInt("fold") != 0; int lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; diff --git a/contrib/src/stc/scintilla/src/LexAda.cxx b/contrib/src/stc/scintilla/src/LexAda.cxx index 91bf00ede8..0d8fb9d5dd 100644 --- a/contrib/src/stc/scintilla/src/LexAda.cxx +++ b/contrib/src/stc/scintilla/src/LexAda.cxx @@ -49,7 +49,7 @@ inline void classifyWordAda(unsigned int start, unsigned int end, } -inline bool isAdaOperator(char ch) { +static inline bool isAdaOperator(char ch) { if (ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' || ch == '-' || diff --git a/contrib/src/stc/scintilla/src/LexBaan.cxx b/contrib/src/stc/scintilla/src/LexBaan.cxx new file mode 100644 index 0000000000..3a36eb8f27 --- /dev/null +++ b/contrib/src/stc/scintilla/src/LexBaan.cxx @@ -0,0 +1,189 @@ +// Scintilla source code edit control +/** @file LexBaan.cxx + ** Lexer for Baan. + ** Based heavily on LexCPP.cxx + **/ +// Copyright 2001- by Vamsi Potluru & Praveen Ambekar +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + if (initStyle == SCE_BAAN_STRINGEOL) // Does not leak onto next line + initStyle = SCE_BAAN_DEFAULT; + + int visibleChars = 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.state == SCE_BAAN_OPERATOR) { + sc.SetState(SCE_BAAN_DEFAULT); + } else if (sc.state == SCE_BAAN_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_BAAN_WORD2); + } + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_PREPROCESSOR) { + if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else { + if (sc.atLineEnd && (sc.chNext != '^')) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } + } else if (sc.state == SCE_BAAN_COMMENT) { + if (sc.atLineEnd) { + sc.SetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_COMMENTDOC) { + if (sc.MatchIgnoreCase("enddllusage")) { + for (unsigned int i = 0; i < 10; i++){ + sc.Forward(); + } + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } + } else if (sc.state == SCE_BAAN_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_BAAN_DEFAULT); + } else if ((sc.atLineEnd) && (sc.chNext != '^')) { + sc.ChangeState(SCE_BAAN_STRINGEOL); + sc.ForwardSetState(SCE_C_DEFAULT); + visibleChars = 0; + } + } + + if (sc.state == SCE_BAAN_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_BAAN_NUMBER); + } else if (sc.MatchIgnoreCase("dllusage")){ + sc.SetState(SCE_BAAN_COMMENTDOC); + do { + sc.Forward(); + } while ((!sc.atLineEnd) && sc.More()); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_BAAN_IDENTIFIER); + } else if (sc.Match('|')){ + sc.SetState(SCE_BAAN_COMMENT); + } else if (sc.ch == '\"') { + sc.SetState(SCE_BAAN_STRING); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_BAAN_PREPROCESSOR); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while (IsASpace(sc.ch) && sc.More()); + } else if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_BAAN_OPERATOR); + } + } + if (sc.atLineEnd) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[], + Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && + (style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) { + if (style != stylePrev) { + levelCurrent++; + } else if ((style != styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (style == SCE_BAAN_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc); diff --git a/contrib/src/stc/scintilla/src/LexBullant.cxx b/contrib/src/stc/scintilla/src/LexBullant.cxx new file mode 100644 index 0000000000..1f76ffcf00 --- /dev/null +++ b/contrib/src/stc/scintilla/src/LexBullant.cxx @@ -0,0 +1,233 @@ +// SciTE - Scintilla based Text Editor +// LexBullant.cxx - lexer for Bullant + +#include +#include +#include +#include +#include + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + + +static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { + char s[100]; + for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { + s[i] = static_cast(tolower(styler[start + i])); + s[i + 1] = '\0'; + } + int lev= 0; + char chAttr = SCE_C_IDENTIFIER; + if (isdigit(s[0]) || (s[0] == '.')){ + chAttr = SCE_C_NUMBER; + } + else { + if (keywords.InList(s)) { + chAttr = SCE_C_WORD; +/* if (strcmp(s, "end method") == 0 || + strcmp(s, "end case") == 0 || + strcmp(s, "end class") == 0 || + strcmp(s, "end debug") == 0 || + strcmp(s, "end test") == 0 || + strcmp(s, "end if") == 0 || + strcmp(s, "end lock") == 0 || + strcmp(s, "end transaction") == 0 || + strcmp(s, "end trap") == 0 || + strcmp(s, "end until") == 0 || + strcmp(s, "end while") == 0) + lev = -1;*/ + if (strcmp(s, "end") == 0) + lev = -1; + else if (strcmp(s, "method") == 0 || + strcmp(s, "case") == 0 || + strcmp(s, "class") == 0 || + strcmp(s, "debug") == 0 || + strcmp(s, "test") == 0 || + strcmp(s, "if") == 0 || + strcmp(s, "lock") == 0 || + strcmp(s, "transaction") == 0 || + strcmp(s, "trap") == 0 || + strcmp(s, "until") == 0 || + strcmp(s, "while") == 0) + lev = 1; + } + } + styler.ColourTo(end, chAttr); + return lev; +} + +static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords = *keywordlists[0]; + + styler.StartAt(startPos); + + bool fold = styler.GetPropertyInt("fold") != 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + + int state = initStyle; + if (state == SCE_C_STRINGEOL) // Does not leak onto next line + state = SCE_C_DEFAULT; + char chPrev = ' '; + char chNext = styler[startPos]; + unsigned int lengthDoc = startPos + length; + int visibleChars = 0; + // int blockChange = 0; + styler.StartSegment(startPos); + int endFoundThisLine = 0; + for (unsigned int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // End of line + endFoundThisLine = 0; + if (state == SCE_C_STRINGEOL) { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + levelPrev = levelCurrent; + } + visibleChars = 0; + +/* int indentBlock = GetLineIndentation(lineCurrent); + if (blockChange==1){ + lineCurrent++; + int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize); + } else if (blockChange==-1) { + indentBlock -= indentSize; + if (indentBlock < 0) + indentBlock = 0; + SetLineIndentation(lineCurrent, indentBlock); + lineCurrent++; + } + blockChange=0; +*/ } + if (!isspace(ch)) + visibleChars++; + + if (styler.IsLeadByte(ch)) { + chNext = styler.SafeGetCharAt(i + 2); + chPrev = ' '; + i += 1; + continue; + } + + if (state == SCE_C_DEFAULT) { + if (iswordstart(ch)) { + styler.ColourTo(i-1, state); + state = SCE_C_IDENTIFIER; + } else if (ch == '@' && chNext == 'o') { + if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENT; + } + } else if (ch == '#') { + styler.ColourTo(i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i-1, state); + state = SCE_C_STRING; + } else if (ch == '\'') { + styler.ColourTo(i-1, state); + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i-1, state); + styler.ColourTo(i, SCE_C_OPERATOR); + } + } else if (state == SCE_C_IDENTIFIER) { + if (!iswordchar(ch)) { + int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler); + state = SCE_C_DEFAULT; + chNext = styler.SafeGetCharAt(i + 1); + if (ch == '#') { + state = SCE_C_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_C_STRING; + } else if (ch == '\'') { + state = SCE_C_CHARACTER; + } else if (isoperator(ch)) { + styler.ColourTo(i, SCE_C_OPERATOR); + } + if (endFoundThisLine == 0) + levelCurrent+=levelChange; + if (levelChange == -1) + endFoundThisLine=1; + } + } else if (state == SCE_C_COMMENT) { + if (ch == '@' && chNext == 'o') { + if (styler.SafeGetCharAt(i+2) == 'n') { + styler.ColourTo(i+2, state); + state = SCE_C_DEFAULT; + i+=2; + } + } + } else if (state == SCE_C_COMMENTLINE) { + if (ch == '\r' || ch == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, state); + state = SCE_C_DEFAULT; + } + } else if (state == SCE_C_STRING) { + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\"') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } else if (chNext == '\r' || chNext == '\n') { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } + } else if (state == SCE_C_CHARACTER) { + if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) { + endFoundThisLine = 0; + styler.ColourTo(i-1, SCE_C_STRINGEOL); + state = SCE_C_STRINGEOL; + } else if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + } + } else if (ch == '\'') { + styler.ColourTo(i, state); + state = SCE_C_DEFAULT; + } + } + chPrev = ch; + } + styler.ColourTo(lengthDoc - 1, state); + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + //styler.SetLevel(lineCurrent, levelCurrent | flagsNext); + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + + } +} + +LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant"); diff --git a/contrib/src/stc/scintilla/src/LexCPP.cxx b/contrib/src/stc/scintilla/src/LexCPP.cxx index b0471b8e52..c85664fd5b 100644 --- a/contrib/src/stc/scintilla/src/LexCPP.cxx +++ b/contrib/src/stc/scintilla/src/LexCPP.cxx @@ -2,7 +2,7 @@ /** @file LexCPP.cxx ** Lexer for C++, C, Java, and Javascript. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -24,22 +24,22 @@ static bool IsOKBeforeRE(const int ch) { return (ch == '(') || (ch == '=') || (ch == ','); } -inline bool IsAWordChar(const int ch) { +static inline bool IsAWordChar(const int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); } -inline bool IsAWordStart(const int ch) { +static inline bool IsAWordStart(const int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '_'); } -inline bool IsADoxygenChar(const int ch) { +static inline bool IsADoxygenChar(const int ch) { return (islower(ch) || ch == '$' || ch == '@' || ch == '\\' || ch == '&' || ch == '<' || ch == '>' || ch == '#' || ch == '{' || ch == '}' || ch == '[' || ch == ']'); } -inline bool IsStateComment(const int state) { +static inline bool IsStateComment(const int state) { return ((state == SCE_C_COMMENT) || (state == SCE_C_COMMENTLINE) || (state == SCE_C_COMMENTDOC) || @@ -47,7 +47,7 @@ inline bool IsStateComment(const int state) { (state == SCE_C_COMMENTDOCKEYWORDERROR)); } -inline bool IsStateString(const int state) { +static inline bool IsStateString(const int state) { return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM)); } @@ -58,7 +58,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor"); + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; // Do not leak onto next line if (initStyle == SCE_C_STRINGEOL) @@ -66,7 +66,6 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo int chPrevNonWhite = ' '; int visibleChars = 0; - int noDocChars = 0; bool lastWordWasUUID = false; StyleContext sc(startPos, length, initStyle, styler); @@ -126,12 +125,8 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_C_DEFAULT); - } else if ((sc.ch == '@' || sc.ch == '\\') && (noDocChars == 0)) { + } else if (sc.ch == '@' || sc.ch == '\\') { sc.SetState(SCE_C_COMMENTDOCKEYWORD); - } else if (sc.atLineEnd) { - noDocChars = 0; - } else if (!isspace(sc.ch) && (sc.ch != '*')) { - noDocChars++; } } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) { if (sc.atLineEnd) { @@ -219,7 +214,6 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } } else if (sc.Match('/', '*')) { if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - noDocChars = 0; sc.SetState(SCE_C_COMMENTDOC); } else { sc.SetState(SCE_C_COMMENT); @@ -268,8 +262,8 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment"); - bool foldCompact = styler.GetPropertyInt("fold.compact", 1); + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); diff --git a/contrib/src/stc/scintilla/src/LexConf.cxx b/contrib/src/stc/scintilla/src/LexConf.cxx index 2dbb65c371..c8441f41ec 100644 --- a/contrib/src/stc/scintilla/src/LexConf.cxx +++ b/contrib/src/stc/scintilla/src/LexConf.cxx @@ -172,6 +172,7 @@ static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *k } } + delete []buffer; } LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf"); diff --git a/contrib/src/stc/scintilla/src/LexCrontab.cxx b/contrib/src/stc/scintilla/src/LexCrontab.cxx index 94a172cfca..ce35fedec5 100644 --- a/contrib/src/stc/scintilla/src/LexCrontab.cxx +++ b/contrib/src/stc/scintilla/src/LexCrontab.cxx @@ -199,6 +199,7 @@ static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordLi break; } } + delete []buffer; } LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab"); diff --git a/contrib/src/stc/scintilla/src/LexEiffel.cxx b/contrib/src/stc/scintilla/src/LexEiffel.cxx index 6470943208..a0bf26a5ea 100644 --- a/contrib/src/stc/scintilla/src/LexEiffel.cxx +++ b/contrib/src/stc/scintilla/src/LexEiffel.cxx @@ -21,7 +21,7 @@ #include "Scintilla.h" #include "SciLexer.h" -inline bool isEiffelOperator(unsigned int ch) { +static inline bool isEiffelOperator(unsigned int ch) { // '.' left out as it is used to make up numbers return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' || ch == '(' || ch == ')' || ch == '=' || @@ -32,11 +32,11 @@ inline bool isEiffelOperator(unsigned int ch) { ch == '!' || ch == '@' || ch == '?'; } -inline bool IsAWordChar(unsigned int ch) { +static inline bool IsAWordChar(unsigned int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); } -inline bool IsAWordStart(unsigned int ch) { +static inline bool IsAWordStart(unsigned int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '_'); } diff --git a/contrib/src/stc/scintilla/src/LexHTML.cxx b/contrib/src/stc/scintilla/src/LexHTML.cxx index 3a03096f8a..67ee29c5e7 100644 --- a/contrib/src/stc/scintilla/src/LexHTML.cxx +++ b/contrib/src/stc/scintilla/src/LexHTML.cxx @@ -1,8 +1,8 @@ // Scintilla source code edit control /** @file LexHTML.cxx ** Lexer for HTML. - **/ -// Copyright 1998-2001 by Neil Hodgson + **/ +// Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include @@ -15,6 +15,7 @@ #include "PropSet.h" #include "Accessor.h" +#include "StyleContext.h" #include "KeyWords.h" #include "Scintilla.h" #include "SciLexer.h" @@ -23,10 +24,18 @@ #define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) #define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) -enum { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock }; -enum { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; +enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock }; +enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; -static int segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, int prevValue) { +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { char s[30 + 1]; unsigned int i = 0; for (; i < end - start + 1 && i < 30; i++) { @@ -67,7 +76,7 @@ static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, u return iResult; } -static int ScriptOfState(int state) { +static script_type ScriptOfState(int state) { if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { return eScriptPython; } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { @@ -76,7 +85,7 @@ static int ScriptOfState(int state) { return eScriptJS; } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { return eScriptPHP; - } else if ((state >= SCE_H_SGML_DEFAULT) && (state <= SCE_H_SGML_BLOCK_DEFAULT)) { + } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { return eScriptSGML; } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { return eScriptSGMLblock; @@ -85,7 +94,7 @@ static int ScriptOfState(int state) { } } -static int statePrintForState(int state, int inScriptType) { +static int statePrintForState(int state, script_mode inScriptType) { int StateToPrint; if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { @@ -219,7 +228,7 @@ static int classifyTagHTML(unsigned int start, unsigned int end, } static void classifyWordHTJS(unsigned int start, unsigned int end, - WordList &keywords, Accessor &styler, int inScriptType) { + WordList &keywords, Accessor &styler, script_mode inScriptType) { char chAttr = SCE_HJ_WORD; bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); if (wordIsNumber) @@ -237,7 +246,7 @@ static void classifyWordHTJS(unsigned int start, unsigned int end, styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); } -static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, int inScriptType) { +static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { char chAttr = SCE_HB_IDENTIFIER; bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); if (wordIsNumber) @@ -262,8 +271,8 @@ static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keyw return SCE_HB_DEFAULT; } -static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, int inScriptType) { - bool wordIsNumber = isdigit(styler[start]); +static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) { + bool wordIsNumber = isdigit(styler[start]) != 0; char s[30 + 1]; unsigned int i = 0; for (; i < end - start + 1 && i < 30; i++) { @@ -287,14 +296,14 @@ static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &key // Called when in a PHP word static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { char chAttr = SCE_HPHP_DEFAULT; - bool wordIsNumber = isdigit(styler[start]); + bool wordIsNumber = isdigit(styler[start]) != 0; if (wordIsNumber) chAttr = SCE_HPHP_NUMBER; else { - char s[30 + 1]; + char s[100 + 1]; unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; + for (; i < end - start + 1 && i < 100; i++) { + s[i] = static_cast(tolower(styler[start + i])); } s[i] = '\0'; if (keywords.InList(s)) @@ -324,7 +333,7 @@ static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) } // Return the first state to reach when entering a scripting language -static int StateForScript(int scriptLanguage) { +static int StateForScript(script_type scriptLanguage) { int Result; switch (scriptLanguage) { case eScriptVBS: @@ -349,11 +358,11 @@ static int StateForScript(int scriptLanguage) { return Result; } -inline bool ishtmlwordchar(char ch) { +static inline bool ishtmlwordchar(char ch) { return isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#'; } -inline bool issgmlwordchar(char ch) { +static inline bool issgmlwordchar(char ch) { return isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['; } @@ -419,18 +428,18 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty lineState = eScriptJS << 8; lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; } - int inScriptType = (lineState >> 0) & 0x03; // 2 bits of scripting type + script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag - int aspScript = (lineState >> 4) & 0x0F; // 4 bits of script name - int clientScript = (lineState >> 8) & 0x0F; // 4 bits of script name + script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name + script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state - int scriptLanguage = ScriptOfState(state); + script_type scriptLanguage = ScriptOfState(state); - const bool foldHTML = styler.GetPropertyInt("fold.html", 0); + const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; const bool fold = foldHTML && styler.GetPropertyInt("fold"); - const bool foldCompact = styler.GetPropertyInt("fold.compact", 1); + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; @@ -502,6 +511,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } } break; + default: + break; } } @@ -729,8 +740,9 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } break; case SCE_H_SGML_DEFAULT: - if (scriptLanguage == eScriptSGMLblock) - StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; + case SCE_H_SGML_BLOCK_DEFAULT: +// if (scriptLanguage == eScriptSGMLblock) +// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; if (ch == '\"') { styler.ColourTo(i - 1, StateToPrint); @@ -750,6 +762,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } else if (ch == '[') { styler.ColourTo(i - 1, StateToPrint); scriptLanguage = eScriptSGMLblock; + state = SCE_H_SGML_BLOCK_DEFAULT; } else if (ch == ']') { if (scriptLanguage == eScriptSGMLblock) { styler.ColourTo(i, StateToPrint); @@ -758,6 +771,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.ColourTo(i - 1, StateToPrint); styler.ColourTo(i, SCE_H_SGML_ERROR); } + state = SCE_H_SGML_DEFAULT; } else if (scriptLanguage == eScriptSGMLblock) { if ((ch == '!') && (chPrev == '<')) { styler.ColourTo(i - 2, StateToPrint); @@ -805,7 +819,11 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty i += size - 1; visibleChars += size - 1; ch = styler.SafeGetCharAt(i); - state = SCE_H_SGML_DEFAULT; + if (scriptLanguage == eScriptSGMLblock) { + state = SCE_H_SGML_BLOCK_DEFAULT; + } else { + state = SCE_H_SGML_DEFAULT; + } continue; } break; @@ -1541,5 +1559,299 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } } +static bool isASPScript(int state) { + return + (state >= SCE_HJA_START && state <= SCE_HJA_REGEX) || + (state >= SCE_HBA_START && state <= SCE_HBA_STRINGEOL) || + (state >= SCE_HPA_DEFAULT && state <= SCE_HPA_IDENTIFIER); +} + +static void ColouriseHBAPiece(StyleContext &sc, WordList *keywordlists[]) { + WordList &keywordsVBS = *keywordlists[2]; + if (sc.state == SCE_HBA_WORD) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywordsVBS.InList(s)) { + if (strcmp(s, "rem") == 0) { + sc.ChangeState(SCE_HBA_COMMENTLINE); + if (sc.atLineEnd) { + sc.SetState(SCE_HBA_DEFAULT); + } + } else { + sc.SetState(SCE_HBA_DEFAULT); + } + } else { + sc.ChangeState(SCE_HBA_IDENTIFIER); + sc.SetState(SCE_HBA_DEFAULT); + } + } + } else if (sc.state == SCE_HBA_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_HBA_DEFAULT); + } + } else if (sc.state == SCE_HBA_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_HBA_DEFAULT); + } else if (sc.ch == '\r' || sc.ch == '\n') { + sc.ChangeState(SCE_HBA_STRINGEOL); + sc.ForwardSetState(SCE_HBA_DEFAULT); + } + } else if (sc.state == SCE_HBA_COMMENTLINE) { + if (sc.ch == '\r' || sc.ch == '\n') { + sc.SetState(SCE_HBA_DEFAULT); + } + } + + if (sc.state == SCE_HBA_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_HBA_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_HBA_WORD); + } else if (sc.ch == '\'') { + sc.SetState(SCE_HBA_COMMENTLINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_HBA_STRING); + } + } +} + +static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) { + WordList &keywordsTags = *keywordlists[0]; + if (sc.state == SCE_H_COMMENT) { + if (sc.Match("-->")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } + } else if (sc.state == SCE_H_ENTITY) { + if (sc.ch == ';') { + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch)) { // Should check that '#' follows '&', but it is unlikely anyway... + sc.ChangeState(SCE_H_TAGUNKNOWN); + sc.SetState(SCE_H_DEFAULT); + } + } else if (sc.state == SCE_H_TAGUNKNOWN) { + if (!ishtmlwordchar(static_cast(sc.ch)) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (s[1] == '/') { + if (keywordsTags.InList(s + 2)) { + sc.ChangeState(SCE_H_TAG); + } + } else { + if (keywordsTags.InList(s + 1)) { + sc.ChangeState(SCE_H_TAG); + } + } + if (sc.ch == '>') { + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.Match('/', '>')) { + sc.SetState(SCE_H_TAGEND); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } else { + sc.SetState(SCE_H_OTHER); + } + } + } else if (sc.state == SCE_H_ATTRIBUTE) { + if (!ishtmlwordchar(static_cast(sc.ch))) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!keywordsTags.InList(s)) { + sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN); + } + sc.SetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_OTHER) { + if (sc.ch == '>') { + sc.SetState(SCE_H_TAG); + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.Match('/', '>')) { + sc.SetState(SCE_H_TAG); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.chPrev == '=') { + sc.SetState(SCE_H_VALUE); + } + } else if (sc.state == SCE_H_DOUBLESTRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_SINGLESTRING) { + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_H_OTHER); + } + } + + if (sc.state == SCE_H_DEFAULT) { + if (sc.ch == '<') { + if (sc.Match("")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } + } else if (sc.state == SCE_H_ENTITY) { + if (sc.ch == ';') { + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch)) { // Should check that '#' follows '&', but it is unlikely anyway... + sc.ChangeState(SCE_H_TAGUNKNOWN); + sc.SetState(SCE_H_DEFAULT); + } + } else if (sc.state == SCE_H_TAGUNKNOWN) { + if (!ishtmlwordchar(static_cast(sc.ch)) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (s[1] == '/') { + if (keywordsTags.InList(s + 2)) { + sc.ChangeState(SCE_H_TAG); + } + } else { + if (keywordsTags.InList(s + 1)) { + sc.ChangeState(SCE_H_TAG); + } + } + if (sc.ch == '>') { + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.Match('/', '>')) { + sc.SetState(SCE_H_TAGEND); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } else { + sc.SetState(SCE_H_OTHER); + } + } + } else if (sc.state == SCE_H_ATTRIBUTE) { + if (!ishtmlwordchar(static_cast(sc.ch))) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!keywordsTags.InList(s)) { + sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN); + } + sc.SetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_OTHER) { + if (sc.ch == '>') { + sc.SetState(SCE_H_TAG); + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.Match('/', '>')) { + sc.SetState(SCE_H_TAG); + sc.Forward(); + sc.ForwardSetState(SCE_H_DEFAULT); + } else if (sc.chPrev == '=') { + sc.SetState(SCE_H_VALUE); + } + } else if (sc.state == SCE_H_DOUBLESTRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_SINGLESTRING) { + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_H_OTHER); + } + } else if (sc.state == SCE_H_NUMBER) { + if (!IsADigit(sc.ch)) { + sc.SetState(SCE_H_OTHER); + } + } + + if (sc.state == SCE_H_DEFAULT) { + if (sc.ch == '<') { + if (sc.Match("