Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Tue, 02 Dec 2014 12:51:18 UTC Commit: 0a58f5012ba8e379f92c2f6751b16b9bea363db6 https://github.com/geany/geany/commit/0a58f5012ba8e379f92c2f6751b16b9bea363d...
Log Message: ----------- Update Scintilla to version 3.5.2
Modified Paths: -------------- scintilla/gtk/PlatGTK.cxx scintilla/gtk/ScintillaGTK.cxx scintilla/include/Scintilla.h scintilla/include/Scintilla.iface scintilla/lexers/LexCoffeeScript.cxx scintilla/lexers/LexVHDL.cxx scintilla/src/Catalogue.cxx scintilla/src/CellBuffer.cxx scintilla/src/Decoration.cxx scintilla/src/Document.cxx scintilla/src/Document.h scintilla/src/EditModel.cxx scintilla/src/EditView.cxx scintilla/src/EditView.h scintilla/src/Editor.cxx scintilla/src/Editor.h scintilla/src/LineMarker.cxx scintilla/src/LineMarker.h scintilla/src/MarginView.cxx scintilla/src/MarginView.h scintilla/src/PositionCache.cxx scintilla/src/RESearch.h scintilla/src/ScintillaBase.cxx scintilla/src/UniConversion.cxx scintilla/src/UniConversion.h scintilla/version.txt
Modified: scintilla/gtk/PlatGTK.cxx 4 lines changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -708,7 +708,7 @@ void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) {
void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) { SurfaceImpl &surfi = static_cast<SurfaceImpl &>(surfacePattern); - bool canDraw = surfi.psurf; + bool canDraw = surfi.psurf != NULL; if (canDraw) { PLATFORM_ASSERT(context); // Tile pattern over rectangle @@ -842,7 +842,7 @@ void SurfaceImpl::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)
void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { SurfaceImpl &surfi = static_cast<SurfaceImpl &>(surfaceSource); - bool canDraw = surfi.psurf; + bool canDraw = surfi.psurf != NULL; if (canDraw) { PLATFORM_ASSERT(context); cairo_set_source_surface(context, surfi.psurf,
Modified: scintilla/gtk/ScintillaGTK.cxx 37 lines changed, 24 insertions(+), 13 deletions(-) =================================================================== @@ -10,6 +10,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <new> #include <string> #include <vector> @@ -424,6 +425,7 @@ ScintillaGTK::~ScintillaGTK() { gdk_event_free(reinterpret_cast<GdkEvent *>(evbtn)); evbtn = 0; } + wPreedit.Destroy(); }
static void UnRefCursor(GdkCursor *cursor) { @@ -482,20 +484,8 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) { gdk_window_show(widget->window); UnRefCursor(cursor); #endif - wPreedit = gtk_window_new(GTK_WINDOW_POPUP); - wPreeditDraw = gtk_drawing_area_new(); - GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro -#if GTK_CHECK_VERSION(3,0,0) - g_signal_connect(G_OBJECT(predrw), "draw", - G_CALLBACK(DrawPreedit), this); -#else - g_signal_connect(G_OBJECT(predrw), "expose_event", - G_CALLBACK(ExposePreedit), this); -#endif - gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw); gtk_widget_realize(PWidget(wPreedit)); - gtk_widget_realize(predrw); - gtk_widget_show(predrw); + gtk_widget_realize(PWidget(wPreeditDraw));
im_context = gtk_im_multicontext_new(); g_signal_connect(G_OBJECT(im_context), "commit", @@ -843,6 +833,20 @@ void ScintillaGTK::Initialise() { GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets, static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));
+ /* create pre-edit window */ + wPreedit = gtk_window_new(GTK_WINDOW_POPUP); + wPreeditDraw = gtk_drawing_area_new(); + GtkWidget *predrw = PWidget(wPreeditDraw); // No code inside the G_OBJECT macro +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect(G_OBJECT(predrw), "draw", + G_CALLBACK(DrawPreedit), this); +#else + g_signal_connect(G_OBJECT(predrw), "expose_event", + G_CALLBACK(ExposePreedit), this); +#endif + gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw); + gtk_widget_show(predrw); + // Set caret period based on GTK settings gboolean blinkOn = false; if (g_object_class_find_property(G_OBJECT_GET_CLASS( @@ -1563,6 +1567,13 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio len--; // Forget the extra '\0' #endif
+#if PLAT_GTK_WIN32 + // Win32 includes an ending '\0' byte in 'len' for clipboard text from + // external applications; ignore it. + if ((len > 0) && (data[len - 1] == '\0')) + len--; +#endif + std::string dest(data, len); if (selectionTypeData == GDK_TARGET_STRING) { if (IsUnicodeMode()) {
Modified: scintilla/include/Scintilla.h 9 lines changed, 8 insertions(+), 1 deletions(-) =================================================================== @@ -274,7 +274,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define INDIC_DOTBOX 12 #define INDIC_SQUIGGLEPIXMAP 13 #define INDIC_COMPOSITIONTHICK 14 -#define INDIC_MAX 31 +#define INDIC_IME 32 +#define INDIC_IME_MAX 35 +#define INDIC_MAX 35 #define INDIC_CONTAINER 8 #define INDIC0_MASK 0x20 #define INDIC1_MASK 0x40 @@ -372,6 +374,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCFIND_WORDSTART 0x00100000 #define SCFIND_REGEXP 0x00200000 #define SCFIND_POSIX 0x00400000 +#define SCFIND_CXX11REGEX 0x00800000 #define SCI_FINDTEXT 2150 #define SCI_FORMATRANGE 2151 #define SCI_GETFIRSTVISIBLELINE 2152 @@ -643,6 +646,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_STATUS_OK 0 #define SC_STATUS_FAILURE 1 #define SC_STATUS_BADALLOC 2 +#define SC_STATUS_WARN_START 1000 +#define SC_STATUS_WARN_REGEX 1001 #define SCI_SETSTATUS 2382 #define SCI_GETSTATUS 2383 #define SCI_SETMOUSEDOWNCAPTURES 2384 @@ -813,6 +818,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define ANNOTATION_HIDDEN 0 #define ANNOTATION_STANDARD 1 #define ANNOTATION_BOXED 2 +#define ANNOTATION_INDENTED 3 #define SCI_ANNOTATIONSETVISIBLE 2548 #define SCI_ANNOTATIONGETVISIBLE 2549 #define SCI_ANNOTATIONSETSTYLEOFFSET 2550 @@ -893,6 +899,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_TECHNOLOGY_DEFAULT 0 #define SC_TECHNOLOGY_DIRECTWRITE 1 #define SC_TECHNOLOGY_DIRECTWRITERETAIN 2 +#define SC_TECHNOLOGY_DIRECTWRITEDC 3 #define SCI_SETTECHNOLOGY 2630 #define SCI_GETTECHNOLOGY 2631 #define SCI_CREATELOADER 2632
Modified: scintilla/include/Scintilla.iface 9 lines changed, 8 insertions(+), 1 deletions(-) =================================================================== @@ -605,7 +605,9 @@ val INDIC_SQUIGGLELOW=11 val INDIC_DOTBOX=12 val INDIC_SQUIGGLEPIXMAP=13 val INDIC_COMPOSITIONTHICK=14 -val INDIC_MAX=31 +val INDIC_IME=32 +val INDIC_IME_MAX=35 +val INDIC_MAX=35 val INDIC_CONTAINER=8 val INDIC0_MASK=0x20 val INDIC1_MASK=0x40 @@ -884,6 +886,7 @@ val SCFIND_MATCHCASE=0x4 val SCFIND_WORDSTART=0x00100000 val SCFIND_REGEXP=0x00200000 val SCFIND_POSIX=0x00400000 +val SCFIND_CXX11REGEX=0x00800000
# Find some text in the document. fun position FindText=2150(int flags, findtext ft) @@ -1661,6 +1664,8 @@ enu Status=SC_STATUS_ val SC_STATUS_OK=0 val SC_STATUS_FAILURE=1 val SC_STATUS_BADALLOC=2 +val SC_STATUS_WARN_START=1000 +val SC_STATUS_WARN_REGEX=1001
# Change error status - 0 = OK. set void SetStatus=2382(int statusCode,) @@ -2152,6 +2157,7 @@ enu AnnotationVisible=ANNOTATION_ val ANNOTATION_HIDDEN=0 val ANNOTATION_STANDARD=1 val ANNOTATION_BOXED=2 +val ANNOTATION_INDENTED=3
# Set the visibility for the annotations for a view set void AnnotationSetVisible=2548(int visible,) @@ -2360,6 +2366,7 @@ fun void ScrollToEnd=2629(,) val SC_TECHNOLOGY_DEFAULT=0 val SC_TECHNOLOGY_DIRECTWRITE=1 val SC_TECHNOLOGY_DIRECTWRITERETAIN=2 +val SC_TECHNOLOGY_DIRECTWRITEDC=3
# Set the technology used. set void SetTechnology=2630(int technology,)
Modified: scintilla/lexers/LexCoffeeScript.cxx 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -407,7 +407,7 @@ static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int, static const char *const csWordLists[] = { "Keywords", "Secondary keywords", - "Unused" + "Unused", "Global classes", 0, };
Modified: scintilla/lexers/LexVHDL.cxx 3 lines changed, 2 insertions(+), 1 deletions(-) =================================================================== @@ -207,7 +207,7 @@ static void FoldNoBoxVHDLDoc( // Decided it would be smarter to have the lexer have all keywords included. Therefore I // don't check if the style for the keywords that I use to adjust the levels. char words[] = - "architecture begin case component else elsif end entity generate loop package process record then " + "architecture begin block case component else elsif end entity generate loop package process record then " "procedure function when"; WordList keywords; keywords.Set(words); @@ -369,6 +369,7 @@ static void FoldNoBoxVHDLDoc( strcmp(s, "architecture") == 0 || strcmp(s, "case") == 0 || strcmp(s, "generate") == 0 || + strcmp(s, "block") == 0 || strcmp(s, "loop") == 0 || strcmp(s, "package") ==0 || strcmp(s, "process") == 0 ||
Modified: scintilla/src/Catalogue.cxx 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -84,8 +84,8 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmCaml); LINK_LEXER(lmCmake); LINK_LEXER(lmCOBOL); - LINK_LEXER(lmCPP); LINK_LEXER(lmCoffeeScript); + LINK_LEXER(lmCPP); LINK_LEXER(lmCss); LINK_LEXER(lmD); LINK_LEXER(lmDiff);
Modified: scintilla/src/CellBuffer.cxx 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -378,7 +378,7 @@ char CellBuffer::CharAt(int position) const { }
void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const { - if (lengthRetrieve < 0) + if (lengthRetrieve <= 0) return; if (position < 0) return;
Modified: scintilla/src/Decoration.cxx 4 lines changed, 3 insertions(+), 1 deletions(-) =================================================================== @@ -163,7 +163,9 @@ int DecorationList::AllOnFor(int position) const { int mask = 0; for (Decoration *deco=root; deco; deco = deco->next) { if (deco->rs.ValueAt(position)) { - mask |= 1 << deco->indicator; + if (deco->indicator < INDIC_IME) { + mask |= 1 << deco->indicator; + } } } return mask;
Modified: scintilla/src/Document.cxx 504 lines changed, 464 insertions(+), 40 deletions(-) =================================================================== @@ -11,10 +11,15 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <algorithm>
+#ifdef CXX11_REGEX +#include <regex> +#endif + #include "Platform.h"
#include "ILexer.h" @@ -335,6 +340,10 @@ int SCI_METHOD Document::LineStart(int line) const { return cb.LineStart(line); }
+bool Document::IsLineStartPosition(int position) const { + return LineStart(LineFromPosition(position)) == position; +} + int SCI_METHOD Document::LineEnd(int line) const { if (line >= LinesTotal() - 1) { return LineStart(line + 1); @@ -601,7 +610,7 @@ bool Document::InGoodUTF8(int pos, int &start, int &end) const { // When lines are terminated with \r\n pairs which should be treated as one character. // When displaying DBCS text such as Japanese. // If moving, move the position in the indicated direction. -int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { +int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const { //Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir); // If out of range, just return minimum/maximum value. if (pos <= 0) @@ -1297,7 +1306,7 @@ int Document::GetColumn(int pos) { return column; }
-int Document::CountCharacters(int startPos, int endPos) { +int Document::CountCharacters(int startPos, int endPos) const { startPos = MovePositionOutsideChar(startPos, 1, false); endPos = MovePositionOutsideChar(endPos, -1, false); int count = 0; @@ -1586,6 +1595,25 @@ void Document::SetCaseFolder(CaseFolder *pcf_) { pcf = pcf_; }
+Document::CharacterExtracted Document::ExtractCharacter(int position) const { + const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(position)); + if (UTF8IsAscii(leadByte)) { + // Common case: ASCII character + return CharacterExtracted(leadByte, 1); + } + const int widthCharBytes = UTF8BytesOfLead[leadByte]; + unsigned char charBytes[UTF8MaxBytes] = { leadByte, 0, 0, 0 }; + for (int b=1; b<widthCharBytes; b++) + charBytes[b] = static_cast<unsigned char>(cb.CharAt(position + b)); + int utf8status = UTF8Classify(charBytes, widthCharBytes); + if (utf8status & UTF8MaskInvalid) { + // Treat as invalid and use up just one byte + return CharacterExtracted(unicodeReplacementChar, 1); + } else { + return CharacterExtracted(UnicodeFromBytes(charBytes), utf8status & UTF8MaskWidth); + } +} + /** * Find text in document, supporting both forward and backward * searches (just pass minPos > maxPos to do a backward search) @@ -2177,6 +2205,61 @@ class BuiltinRegex : public RegexSearchBase { std::string substituted; };
+namespace { + +/** +* RESearchRange keeps track of search range. +*/ +class RESearchRange { +public: + const Document *doc; + int increment; + int startPos; + int endPos; + int lineRangeStart; + int lineRangeEnd; + int lineRangeBreak; + RESearchRange(const Document *doc_, int minPos, int maxPos) : doc(doc_) { + increment = (minPos <= maxPos) ? 1 : -1; + + // Range endpoints should not be inside DBCS characters, but just in case, move them. + startPos = doc->MovePositionOutsideChar(minPos, 1, false); + endPos = doc->MovePositionOutsideChar(maxPos, 1, false); + + lineRangeStart = doc->LineFromPosition(startPos); + lineRangeEnd = doc->LineFromPosition(endPos); + if ((increment == 1) && + (startPos >= doc->LineEnd(lineRangeStart)) && + (lineRangeStart < lineRangeEnd)) { + // the start position is at end of line or between line end characters. + lineRangeStart++; + startPos = doc->LineStart(lineRangeStart); + } else if ((increment == -1) && + (startPos <= doc->LineStart(lineRangeStart)) && + (lineRangeStart > lineRangeEnd)) { + // the start position is at beginning of line. + lineRangeStart--; + startPos = doc->LineEnd(lineRangeStart); + } + lineRangeBreak = lineRangeEnd + increment; + } + Range LineRange(int line) const { + Range range(doc->LineStart(line), doc->LineEnd(line)); + if (increment == 1) { + if (line == lineRangeStart) + range.start = startPos; + if (line == lineRangeEnd) + range.end = endPos; + } else { + if (line == lineRangeEnd) + range.start = endPos; + if (line == lineRangeStart) + range.end = startPos; + } + return range; + } +}; + // Define a way for the Regular Expression code to access the document class DocumentIndexer : public CharacterIndexer { Document *pdoc; @@ -2197,18 +2280,375 @@ class DocumentIndexer : public CharacterIndexer { } };
+#ifdef CXX11_REGEX + +class ByteIterator : public std::iterator<std::bidirectional_iterator_tag, char> { +public: + const Document *doc; + Position position; + ByteIterator(const Document *doc_ = 0, Position position_ = 0) : doc(doc_), position(position_) { + } + ByteIterator(const ByteIterator &other) { + doc = other.doc; + position = other.position; + } + ByteIterator &operator=(const ByteIterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + } + return *this; + } + char operator*() const { + return doc->CharAt(position); + } + ByteIterator &operator++() { + position++; + return *this; + } + ByteIterator operator++(int) { + ByteIterator retVal(*this); + position++; + return retVal; + } + ByteIterator &operator--() { + position--; + return *this; + } + bool operator==(const ByteIterator &other) const { + return doc == other.doc && position == other.position; + } + bool operator!=(const ByteIterator &other) const { + return doc != other.doc || position != other.position; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + return position; + } +}; + +// On Windows, wchar_t is 16 bits wide and on Unix it is 32 bits wide. +// Would be better to use sizeof(wchar_t) or similar to differentiate +// but easier for now to hard-code platforms. +// C++11 has char16_t and char32_t but neither Clang nor Visual C++ +// appear to allow specializing basic_regex over these. + +#ifdef _WIN32 +#define WCHAR_T_IS_16 1 +#else +#define WCHAR_T_IS_16 0 +#endif + +#if WCHAR_T_IS_16 + +// On Windows, report non-BMP characters as 2 separate surrogates as that +// matches wregex since it is based on wchar_t. +class UTF8Iterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t> { + // These 3 fields determine the iterator position and are used for comparisons + const Document *doc; + Position position; + size_t characterIndex; + // Remaining fields are derived from the determining fields so are excluded in comparisons + unsigned int lenBytes; + size_t lenCharacters; + wchar_t buffered[2]; +public: + UTF8Iterator(const Document *doc_ = 0, Position position_ = 0) : + doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0) { + buffered[0] = 0; + buffered[1] = 0; + } + UTF8Iterator(const UTF8Iterator &other) { + doc = other.doc; + position = other.position; + characterIndex = other.characterIndex; + lenBytes = other.lenBytes; + lenCharacters = other.lenCharacters; + buffered[0] = other.buffered[0]; + buffered[1] = other.buffered[1]; + } + UTF8Iterator &operator=(const UTF8Iterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + characterIndex = other.characterIndex; + lenBytes = other.lenBytes; + lenCharacters = other.lenCharacters; + buffered[0] = other.buffered[0]; + buffered[1] = other.buffered[1]; + } + return *this; + } + wchar_t operator*() { + if (lenCharacters == 0) { + ReadCharacter(); + } + return buffered[characterIndex]; + } + UTF8Iterator &operator++() { + if ((characterIndex + 1) < (lenCharacters)) { + characterIndex++; + } else { + position += lenBytes; + ReadCharacter(); + characterIndex = 0; + } + return *this; + } + UTF8Iterator operator++(int) { + UTF8Iterator retVal(*this); + if ((characterIndex + 1) < (lenCharacters)) { + characterIndex++; + } else { + position += lenBytes; + ReadCharacter(); + characterIndex = 0; + } + return retVal; + } + UTF8Iterator &operator--() { + if (characterIndex) { + characterIndex--; + } else { + position = doc->NextPosition(position, -1); + ReadCharacter(); + characterIndex = lenCharacters - 1; + } + return *this; + } + bool operator==(const UTF8Iterator &other) const { + // Only test the determining fields, not the character widths and values derived from this + return doc == other.doc && + position == other.position && + characterIndex == other.characterIndex; + } + bool operator!=(const UTF8Iterator &other) const { + // Only test the determining fields, not the character widths and values derived from this + return doc != other.doc || + position != other.position || + characterIndex != other.characterIndex; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + if (characterIndex) + return position + lenBytes; // Force to end of character + else + return position; + } +private: + void ReadCharacter() { + Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); + lenBytes = charExtracted.widthBytes; + if (charExtracted.character == unicodeReplacementChar) { + lenCharacters = 1; + buffered[0] = static_cast<wchar_t>(charExtracted.character); + } else { + lenCharacters = UTF16FromUTF32Character(charExtracted.character, buffered); + } + } +}; + +#else + +// On Unix, report non-BMP characters as single characters + +class UTF8Iterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t> { + const Document *doc; + Position position; +public: + UTF8Iterator(const Document *doc_=0, Position position_=0) : doc(doc_), position(position_) { + } + UTF8Iterator(const UTF8Iterator &other) { + doc = other.doc; + position = other.position; + } + UTF8Iterator &operator=(const UTF8Iterator &other) { + if (this != &other) { + doc = other.doc; + position = other.position; + } + return *this; + } + wchar_t operator*() const { + Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); + return charExtracted.character; + } + UTF8Iterator &operator++() { + position = doc->NextPosition(position, 1); + return *this; + } + UTF8Iterator operator++(int) { + UTF8Iterator retVal(*this); + position = doc->NextPosition(position, 1); + return retVal; + } + UTF8Iterator &operator--() { + position = doc->NextPosition(position, -1); + return *this; + } + bool operator==(const UTF8Iterator &other) const { + return doc == other.doc && position == other.position; + } + bool operator!=(const UTF8Iterator &other) const { + return doc != other.doc || position != other.position; + } + int Pos() const { + return position; + } + int PosRoundUp() const { + return position; + } +}; + +#endif + +std::regex_constants::match_flag_type MatchFlags(const Document *doc, int startPos, int endPos) { + std::regex_constants::match_flag_type flagsMatch = std::regex_constants::match_default; + if (!doc->IsLineStartPosition(startPos)) + flagsMatch |= std::regex_constants::match_not_bol; + if (!doc->IsLineEndPosition(endPos)) + flagsMatch |= std::regex_constants::match_not_eol; + return flagsMatch; +} + +template<typename Iterator, typename Regex> +bool MatchOnLines(const Document *doc, const Regex ®exp, const RESearchRange &resr, RESearch &search) { + bool matched = false; + std::match_results<Iterator> match; + + // MSVC and libc++ have problems with ^ and $ matching line ends inside a range + // If they didn't then the line by line iteration could be removed for the forwards + // case and replaced with the following 4 lines: + // Iterator uiStart(doc, startPos); + // Iterator uiEnd(doc, endPos); + // flagsMatch = MatchFlags(doc, startPos, endPos); + // matched = std::regex_search(uiStart, uiEnd, match, regexp, flagsMatch); + + // Line by line. + for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { + const Range lineRange = resr.LineRange(line); + Iterator itStart(doc, lineRange.start); + Iterator itEnd(doc, lineRange.end); + std::regex_constants::match_flag_type flagsMatch = MatchFlags(doc, lineRange.start, lineRange.end); + matched = std::regex_search(itStart, itEnd, match, regexp, flagsMatch); + // Check for the last match on this line. + if (matched) { + if (resr.increment == -1) { + while (matched) { + Iterator itNext(doc, match[0].second.PosRoundUp()); + flagsMatch = MatchFlags(doc, itNext.Pos(), lineRange.end); + std::match_results<Iterator> matchNext; + matched = std::regex_search(itNext, itEnd, matchNext, regexp, flagsMatch); + if (matched) { + if (match[0].first == match[0].second) { + // Empty match means failure so exit + return false; + } + match = matchNext; + } + } + matched = true; + } + break; + } + } + if (matched) { + for (size_t co = 0; co < match.size(); co++) { + search.bopat[co] = match[co].first.Pos(); + search.eopat[co] = match[co].second.PosRoundUp(); + size_t lenMatch = search.eopat[co] - search.bopat[co]; + search.pat[co].resize(lenMatch); + for (size_t iPos = 0; iPos < lenMatch; iPos++) { + search.pat[co][iPos] = doc->CharAt(iPos + search.bopat[co]); + } + } + } + return matched; +} + +long Cxx11RegexFindText(Document *doc, int minPos, int maxPos, const char *s, + bool caseSensitive, int *length, RESearch &search) { + const RESearchRange resr(doc, minPos, maxPos); + try { + //ElapsedTime et; + std::regex::flag_type flagsRe = std::regex::ECMAScript; + // Flags that apper to have no effect: + // | std::regex::collate | std::regex::extended; + if (!caseSensitive) + flagsRe = flagsRe | std::regex::icase; + + // Clear the RESearch so can fill in matches + search.Clear(); + + bool matched = false; + if (SC_CP_UTF8 == doc->dbcsCodePage) { + unsigned int lenS = static_cast<unsigned int>(strlen(s)); + std::vector<wchar_t> ws(lenS + 1); +#if WCHAR_T_IS_16 + size_t outLen = UTF16FromUTF8(s, lenS, &ws[0], lenS); +#else + size_t outLen = UTF32FromUTF8(s, lenS, reinterpret_cast<unsigned int *>(&ws[0]), lenS); +#endif + ws[outLen] = 0; + std::wregex regexp; +#if defined(__APPLE__) + // Using a UTF-8 locale doesn't change to Unicode over a byte buffer so '.' + // is one byte not one character. + // However, on OS X this makes wregex act as Unicode + std::locale localeU("en_US.UTF-8"); + regexp.imbue(localeU); +#endif + regexp.assign(&ws[0], flagsRe); + matched = MatchOnLines<UTF8Iterator>(doc, regexp, resr, search); + + } else { + std::regex regexp; + regexp.assign(s, flagsRe); + matched = MatchOnLines<ByteIterator>(doc, regexp, resr, search); + } + + int posMatch = -1; + if (matched) { + posMatch = search.bopat[0]; + *length = search.eopat[0] - search.bopat[0]; + } + // Example - search in doc/ScintillaHistory.html for + // [[:upper:]]eta[[:space:]] + // On MacBook, normally around 1 second but with locale imbued -> 14 seconds. + //double durSearch = et.Duration(true); + //Platform::DebugPrintf("Search:%9.6g \n", durSearch); + return posMatch; + } catch (std::regex_error &) { + // Failed to create regular expression + throw RegexError(); + } catch (...) { + // Failed in some other way + return -1; + } +} + +#endif + +} + long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s, bool caseSensitive, bool, bool, int flags, int *length) { - const bool posix = (flags & SCFIND_POSIX) != 0; - const int increment = (minPos <= maxPos) ? 1 : -1;
- int startPos = minPos; - int endPos = maxPos; +#ifdef CXX11_REGEX + if (flags & SCFIND_CXX11REGEX) { + return Cxx11RegexFindText(doc, minPos, maxPos, s, + caseSensitive, length, search); + } +#endif
- // Range endpoints should not be inside DBCS characters, but just in case, move them. - startPos = doc->MovePositionOutsideChar(startPos, 1, false); - endPos = doc->MovePositionOutsideChar(endPos, 1, false); + const RESearchRange resr(doc, minPos, maxPos); + + const bool posix = (flags & SCFIND_POSIX) != 0;
const char *errmsg = search.Compile(s, *length, caseSensitive, posix); if (errmsg) { @@ -2218,50 +2658,34 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s // Replace first '.' with '-' in each property file variable reference: // Search: $(([A-Za-z0-9_-]+).([A-Za-z0-9_.]+)) // Replace: $(\1-\2) - int lineRangeStart = doc->LineFromPosition(startPos); - const int lineRangeEnd = doc->LineFromPosition(endPos); - if ((increment == 1) && - (startPos >= doc->LineEnd(lineRangeStart)) && - (lineRangeStart < lineRangeEnd)) { - // the start position is at end of line or between line end characters. - lineRangeStart++; - startPos = doc->LineStart(lineRangeStart); - } else if ((increment == -1) && - (startPos <= doc->LineStart(lineRangeStart)) && - (lineRangeStart > lineRangeEnd)) { - // the start position is at beginning of line. - lineRangeStart--; - startPos = doc->LineEnd(lineRangeStart); - } int pos = -1; int lenRet = 0; const char searchEnd = s[*length - 1]; const char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0'; - const int lineRangeBreak = lineRangeEnd + increment; - for (int line = lineRangeStart; line != lineRangeBreak; line += increment) { + for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { int startOfLine = doc->LineStart(line); int endOfLine = doc->LineEnd(line); - if (increment == 1) { - if (line == lineRangeStart) { - if ((startPos != startOfLine) && (s[0] == '^')) + if (resr.increment == 1) { + if (line == resr.lineRangeStart) { + if ((resr.startPos != startOfLine) && (s[0] == '^')) continue; // Can't match start of line if start position after start of line - startOfLine = startPos; + startOfLine = resr.startPos; } - if (line == lineRangeEnd) { - if ((endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\')) + if (line == resr.lineRangeEnd) { + if ((resr.endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\')) continue; // Can't match end of line if end position before end of line - endOfLine = endPos; + endOfLine = resr.endPos; } } else { - if (line == lineRangeEnd) { - if ((endPos != startOfLine) && (s[0] == '^')) + if (line == resr.lineRangeEnd) { + if ((resr.endPos != startOfLine) && (s[0] == '^')) continue; // Can't match start of line if end position after start of line - startOfLine = endPos; + startOfLine = resr.endPos; } - if (line == lineRangeStart) { - if ((startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\')) + if (line == resr.lineRangeStart) { + if ((resr.startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\')) continue; // Can't match end of line if start position before end of line - endOfLine = startPos; + endOfLine = resr.startPos; } }
@@ -2273,7 +2697,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s search.eopat[0] = doc->MovePositionOutsideChar(search.eopat[0], 1, false); lenRet = search.eopat[0] - search.bopat[0]; // There can be only one start of a line, so no need to look for last match in line - if ((increment == -1) && (s[0] != '^')) { + if ((resr.increment == -1) && (s[0] != '^')) { // Check for the last match on this line. int repetitions = 1000; // Break out of infinite loop while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
Modified: scintilla/src/Document.h 19 lines changed, 17 insertions(+), 2 deletions(-) =================================================================== @@ -188,6 +188,10 @@ class LexInterface { } };
+struct RegexError : public std::runtime_error { + RegexError() : std::runtime_error("regex failure") {} +}; + /** */ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { @@ -271,7 +275,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { bool IsCrLf(int pos) const; int LenChar(int pos); bool InGoodUTF8(int pos, int &start, int &end) const; - int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); + int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; int NextPosition(int pos, int moveDir) const; bool NextCharacter(int &pos, int moveDir) const; // Returns true if pos changed int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const; @@ -317,7 +321,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { int SetLineIndentation(int line, int indent); int GetLineIndentPosition(int line) const; int GetColumn(int position); - int CountCharacters(int startPos, int endPos); + int CountCharacters(int startPos, int endPos) const; int FindColumn(int line, int column); void Indent(bool forwards, int lineBottom, int lineTop); static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted); @@ -345,6 +349,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { void DeleteAllMarks(int markerNum); int LineFromHandle(int markerHandle); int SCI_METHOD LineStart(int line) const; + bool IsLineStartPosition(int position) const; int SCI_METHOD LineEnd(int line) const; int LineEndPosition(int position) const; bool IsLineEndPosition(int position) const; @@ -364,6 +369,16 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { int NextWordEnd(int pos, int delta); int SCI_METHOD Length() const { return cb.Length(); } void Allocate(int newSize) { cb.Allocate(newSize); } + + struct CharacterExtracted { + unsigned int character; + unsigned int widthBytes; + CharacterExtracted(unsigned int character_, unsigned int widthBytes_) : + character(character_), widthBytes(widthBytes_) { + } + }; + CharacterExtracted ExtractCharacter(int position) const; + bool MatchesWordOptions(bool word, bool wordStart, int pos, int length) const; bool HasCaseFolder(void) const; void SetCaseFolder(CaseFolder *pcf_);
Modified: scintilla/src/EditModel.cxx 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -12,6 +12,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map>
Modified: scintilla/src/EditView.cxx 45 lines changed, 31 insertions(+), 14 deletions(-) =================================================================== @@ -12,6 +12,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map> @@ -185,6 +186,9 @@ EditView::EditView() { pixmapIndentGuideHighlight = 0; llc.SetLevel(LineLayoutCache::llcCaret); posCache.SetSize(0x400); + tabArrowHeight = 4; + customDrawTabArrow = NULL; + customDrawWrapMarker = NULL; }
EditView::~EditView() { @@ -927,7 +931,11 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle rcPlace.right = rcLine.right; rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; } - DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); + } else { + customDrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); + } } }
@@ -991,6 +999,10 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS } }
+static bool AnnotationBoxedOrIndented(int annotationVisible) { + return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED; +} + void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) { int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth); @@ -1002,18 +1014,16 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi surface->FillRectangle(rcSegment, vsDraw.styles[0].back); } rcSegment.left = static_cast<XYPOSITION>(xStart); - if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) { - // Only care about calculating width if tracking or need to draw box + if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { + // Only care about calculating width if tracking or need to draw indented box int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); - if (vsDraw.annotationVisible == ANNOTATION_BOXED) { + if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins - } - if (widthAnnotation > lineWidthMaxSeen) - lineWidthMaxSeen = widthAnnotation; - if (vsDraw.annotationVisible == ANNOTATION_BOXED) { rcSegment.left = static_cast<XYPOSITION>(xStart + indent); rcSegment.right = rcSegment.left + widthAnnotation; } + if (widthAnnotation > lineWidthMaxSeen) + lineWidthMaxSeen = widthAnnotation; } const int annotationLines = model.pdoc->AnnotationLines(line); size_t start = 0; @@ -1025,7 +1035,7 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi lineInAnnotation++; } PRectangle rcText = rcSegment; - if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) { + if ((phase & drawBack) && AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { surface->FillRectangle(rcText, vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); rcText.left += vsDraw.spaceWidth; @@ -1201,7 +1211,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt }
static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, - int xStart, PRectangle rcLine, ColourOptional background) { + int xStart, PRectangle rcLine, ColourOptional background, DrawWrapMarkerFn customDrawWrapMarker) { // default bgnd here.. surface->FillRectangle(rcLine, background.isSet ? background : vsDraw.styles[STYLE_DEFAULT].back); @@ -1219,7 +1229,11 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c else rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
- DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); + } else { + customDrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); + } } }
@@ -1463,9 +1477,12 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi if (vsDraw.whitespaceColours.fore.isSet) textFore = vsDraw.whitespaceColours.fore; surface->PenColour(textFore); - PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, + PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight, rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); - DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2)); + if (customDrawTabArrow == NULL) + DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2)); + else + customDrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2)); } } } else { @@ -1632,7 +1649,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
if ((ll->wrapIndent != 0) && (subLine > 0)) { if (phase & drawBack) { - DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background); + DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker); } xStart += static_cast<int>(ll->wrapIndent); }
Modified: scintilla/src/EditView.h 10 lines changed, 10 insertions(+), 0 deletions(-) =================================================================== @@ -42,6 +42,8 @@ void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XY void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, const StyledText &st, size_t start, size_t length, DrawPhase phase);
+typedef void (*DrawTabArrowFn)(Surface *surface, PRectangle rcTab, int ymid); + /** * EditView draws the main text area. */ @@ -78,6 +80,14 @@ class EditView { LineLayoutCache llc; PositionCache posCache;
+ int tabArrowHeight; // draw arrow heads this many pixels above/below line midpoint + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * DrawTabArrow function for drawing tab characters. Allow those platforms to + * override it instead of creating a new method in the Surface class that + * existing platforms must implement as empty. */ + DrawTabArrowFn customDrawTabArrow; + DrawWrapMarkerFn customDrawWrapMarker; + EditView(); virtual ~EditView();
Modified: scintilla/src/Editor.cxx 105 lines changed, 63 insertions(+), 42 deletions(-) =================================================================== @@ -12,6 +12,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map> @@ -112,6 +113,7 @@ Editor::Editor() { mouseDownCaptures = true;
lastClickTime = 0; + doubleClickCloseThreshold = Point(3, 3); dwellDelay = SC_TIME_FOREVER; ticksToDwell = SC_TIME_FOREVER; dwelling = false; @@ -1789,12 +1791,15 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { { UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
+ // Vector elements point into selection in order to change selection. std::vector<SelectionRange *> selPtrs; for (size_t r = 0; r < sel.Count(); r++) { selPtrs.push_back(&sel.Range(r)); } + // Order selections by position in document. std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs);
+ // Loop in reverse to avoid disturbing positions of selections yet to be processed. for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin(); rit != selPtrs.rend(); ++rit) { SelectionRange *currentSel = *rit; @@ -2105,6 +2110,7 @@ void Editor::Clear() { ClearSelection(); } sel.RemoveDuplicates(); + ShowCaretAtCurrentPosition(); // Avoid blinking }
void Editor::SelectAll() { @@ -3638,18 +3644,23 @@ long Editor::FindText( int lengthFound = istrlen(ft->lpstrText); if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast<int>(wParam), - &lengthFound); - if (pos != -1) { - ft->chrgText.cpMin = pos; - ft->chrgText.cpMax = pos + lengthFound; + try { + int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast<int>(wParam), + &lengthFound); + if (pos != -1) { + ft->chrgText.cpMin = pos; + ft->chrgText.cpMax = pos + lengthFound; + } + return pos; + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } - return pos; }
/** @@ -3683,22 +3694,27 @@ long Editor::SearchText( int lengthFound = istrlen(txt); if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - if (iMessage == SCI_SEARCHNEXT) { - pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast<int>(wParam), - &lengthFound); - } else { - pos = pdoc->FindText(searchAnchor, 0, txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast<int>(wParam), - &lengthFound); + try { + if (iMessage == SCI_SEARCHNEXT) { + pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast<int>(wParam), + &lengthFound); + } else { + pos = pdoc->FindText(searchAnchor, 0, txt, + (wParam & SCFIND_MATCHCASE) != 0, + (wParam & SCFIND_WHOLEWORD) != 0, + (wParam & SCFIND_WORDSTART) != 0, + (wParam & SCFIND_REGEXP) != 0, + static_cast<int>(wParam), + &lengthFound); + } + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } if (pos != -1) { SetSelection(pos, pos + lengthFound); @@ -3733,18 +3749,23 @@ long Editor::SearchInTarget(const char *text, int length) {
if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); - int pos = pdoc->FindText(targetStart, targetEnd, text, - (searchFlags & SCFIND_MATCHCASE) != 0, - (searchFlags & SCFIND_WHOLEWORD) != 0, - (searchFlags & SCFIND_WORDSTART) != 0, - (searchFlags & SCFIND_REGEXP) != 0, - searchFlags, - &lengthFound); - if (pos != -1) { - targetStart = pos; - targetEnd = pos + lengthFound; + try { + int pos = pdoc->FindText(targetStart, targetEnd, text, + (searchFlags & SCFIND_MATCHCASE) != 0, + (searchFlags & SCFIND_WHOLEWORD) != 0, + (searchFlags & SCFIND_WORDSTART) != 0, + (searchFlags & SCFIND_REGEXP) != 0, + searchFlags, + &lengthFound); + if (pos != -1) { + targetStart = pos; + targetEnd = pos + lengthFound; + } + return pos; + } catch (RegexError &) { + errorStatus = SC_STATUS_WARN_REGEX; + return -1; } - return pos; }
void Editor::GoToLine(int lineNo) { @@ -3757,10 +3778,10 @@ void Editor::GoToLine(int lineNo) { EnsureCaretVisible(); }
-static bool Close(Point pt1, Point pt2) { - if (abs(pt1.x - pt2.x) > 3) +static bool Close(Point pt1, Point pt2, Point threshold) { + if (abs(pt1.x - pt2.x) > threshold.x) return false; - if (abs(pt1.y - pt2.y) > 3) + if (abs(pt1.y - pt2.y) > threshold.y) return false; return true; } @@ -4116,7 +4137,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie if (shift && !inSelMargin) { SetSelection(newPos); } - if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) { + if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick, doubleClickCloseThreshold)) { //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); SetMouseCapture(true); if (FineTickerAvailable()) {
Modified: scintilla/src/Editor.h 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -203,6 +203,7 @@ class Editor : public EditModel, public DocWatcher {
Point lastClick; unsigned int lastClickTime; + Point doubleClickCloseThreshold; int dwellDelay; int ticksToDwell; bool dwelling;
Modified: scintilla/src/LineMarker.cxx 5 lines changed, 5 insertions(+), 0 deletions(-) =================================================================== @@ -72,6 +72,11 @@ static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, C }
void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const { + if (customDraw != NULL) { + customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this); + return; + } + ColourDesired colourHead = back; ColourDesired colourBody = back; ColourDesired colourTail = back;
Modified: scintilla/src/LineMarker.h 10 lines changed, 10 insertions(+), 0 deletions(-) =================================================================== @@ -12,6 +12,8 @@ namespace Scintilla { #endif
+typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker); + /** */ class LineMarker { @@ -25,6 +27,11 @@ class LineMarker { int alpha; XPM *pxpm; RGBAImage *image; + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * Draw function for drawing line markers. Allow those platforms to override + * it instead of creating a new method(s) in the Surface class that existing + * platforms must implement as empty. */ + DrawLineMarkerFn customDraw; LineMarker() { markType = SC_MARK_CIRCLE; fore = ColourDesired(0,0,0); @@ -33,6 +40,7 @@ class LineMarker { alpha = SC_ALPHA_NOALPHA; pxpm = NULL; image = NULL; + customDraw = NULL; } LineMarker(const LineMarker &) { // Defined to avoid pxpm being blindly copied, not as a complete copy constructor @@ -43,6 +51,7 @@ class LineMarker { alpha = SC_ALPHA_NOALPHA; pxpm = NULL; image = NULL; + customDraw = NULL; } ~LineMarker() { delete pxpm; @@ -60,6 +69,7 @@ class LineMarker { pxpm = NULL; delete image; image = NULL; + customDraw = NULL; } return *this; }
Modified: scintilla/src/MarginView.cxx 11 lines changed, 9 insertions(+), 2 deletions(-) =================================================================== @@ -12,6 +12,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map> @@ -102,6 +103,8 @@ MarginView::MarginView() { pixmapSelMargin = 0; pixmapSelPattern = 0; pixmapSelPatternOffset1 = 0; + wrapMarkerPaddingRight = 3; + customDrawWrapMarker = NULL; }
void MarginView::DropGraphics(bool freeObjects) { @@ -391,9 +394,13 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect rcNumber.top + vs.maxAscent, number, static_cast<int>(strlen(number)), drawAll); } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { PRectangle rcWrapMarker = rcMarker; - rcWrapMarker.right -= 3; + rcWrapMarker.right -= wrapMarkerPaddingRight; rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; - DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); + if (customDrawWrapMarker == NULL) { + DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); + } else { + customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); + } } } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { if (firstSubLine) {
Modified: scintilla/src/MarginView.h 9 lines changed, 9 insertions(+), 0 deletions(-) =================================================================== @@ -14,6 +14,8 @@ namespace Scintilla {
void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
+typedef void (*DrawWrapMarkerFn)(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); + /** * MarginView draws the margins. */ @@ -25,6 +27,13 @@ class MarginView { // Highlight current folding block HighlightDelimiter highlightDelimiter;
+ int wrapMarkerPaddingRight; // right-most pixel padding of wrap markers + /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native + * DrawWrapMarker function for drawing wrap markers. Allow those platforms to + * override it instead of creating a new method in the Surface class that + * existing platforms must implement as empty. */ + DrawWrapMarkerFn customDrawWrapMarker; + MarginView();
void DropGraphics(bool freeObjects);
Modified: scintilla/src/PositionCache.cxx 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -10,6 +10,7 @@ #include <stdio.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map>
Modified: scintilla/src/RESearch.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -33,6 +33,7 @@ class RESearch { public: explicit RESearch(CharClassify *charClassTable); ~RESearch(); + void Clear(); void GrabMatches(CharacterIndexer &ci); const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix); int Execute(CharacterIndexer &ci, int lp, int endp); @@ -46,7 +47,6 @@ class RESearch { std::string pat[MAXTAG];
private: - void Clear(); void ChSet(unsigned char c); void ChSetWithCase(unsigned char c, bool caseSensitive); int GetBackslashExpression(const char *pattern, int &incr);
Modified: scintilla/src/ScintillaBase.cxx 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -11,6 +11,7 @@ #include <assert.h> #include <ctype.h>
+#include <stdexcept> #include <string> #include <vector> #include <map>
Modified: scintilla/src/UniConversion.cxx 46 lines changed, 46 insertions(+), 0 deletions(-) =================================================================== @@ -20,6 +20,7 @@ namespace Scintilla { enum { SURROGATE_LEAD_FIRST = 0xD800 }; enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; enum { SURROGATE_TRAIL_LAST = 0xDFFF }; +enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 };
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) { unsigned int len = 0; @@ -138,6 +139,51 @@ unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsig return ui; }
+unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen) { + unsigned int ui=0; + const unsigned char *us = reinterpret_cast<const unsigned char *>(s); + unsigned int i=0; + while ((i<len) && (ui<tlen)) { + unsigned char ch = us[i++]; + wchar_t value = 0; + if (ch < 0x80) { + value = ch; + } else if (((len-i) >= 1) && (ch < 0x80 + 0x40 + 0x20)) { + value = (ch & 0x1F) << 6; + ch = us[i++]; + value += ch & 0x7F; + } else if (((len-i) >= 2) && (ch < 0x80 + 0x40 + 0x20 + 0x10)) { + value = (ch & 0xF) << 12; + ch = us[i++]; + value += (ch & 0x7F) << 6; + ch = us[i++]; + value += ch & 0x7F; + } else if ((len-i) >= 3) { + value = (ch & 0x7) << 18; + ch = us[i++]; + value += (ch & 0x3F) << 12; + ch = us[i++]; + value += (ch & 0x3F) << 6; + ch = us[i++]; + value += ch & 0x3F; + } + tbuf[ui] = value; + ui++; + } + return ui; +} + +unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) { + if (val < SUPPLEMENTAL_PLANE_FIRST) { + tbuf[0] = static_cast<wchar_t>(val); + return 1; + } else { + tbuf[0] = static_cast<wchar_t>(((val - SUPPLEMENTAL_PLANE_FIRST) >> 10) + SURROGATE_LEAD_FIRST); + tbuf[1] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST); + return 2; + } +} + int UTF8BytesOfLead[256]; static bool initialisedBytesOfLead = false;
Modified: scintilla/src/UniConversion.h 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -14,11 +14,15 @@ namespace Scintilla {
const int UTF8MaxBytes = 4;
+const int unicodeReplacementChar = 0xFFFD; + unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen); void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len); unsigned int UTF8CharLength(unsigned char ch); unsigned int UTF16Length(const char *s, unsigned int len); unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen); +unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen); +unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf);
extern int UTF8BytesOfLead[256]; void UTF8BytesOfLeadInitialise();
Modified: scintilla/version.txt 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -1 +1 @@ -351 +352
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).