[geany/geany] 0a58f5: Update Scintilla to version 3.5.2

Colomban Wendling git-noreply at xxxxx
Tue Dec 2 12:51:18 UTC 2014


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Tue, 02 Dec 2014 12:51:18 UTC
Commit:      0a58f5012ba8e379f92c2f6751b16b9bea363db6
             https://github.com/geany/geany/commit/0a58f5012ba8e379f92c2f6751b16b9bea363db6

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 &regexp, 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).


More information about the Commits mailing list