diff -r 5693714a8b0b src/Catalogue.cxx --- a/src/Catalogue.cxx Fri Dec 06 16:19:52 2013 +1100 +++ b/src/Catalogue.cxx Sun Dec 15 21:21:20 2013 -0500 @@ -74,6 +74,7 @@ // Shorten the code that declares a lexer and ensures it is linked in by calling a method. #define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer); +#if 0 //++Autogenerated -- run scripts/LexGen.py to regenerate //**\(\tLINK_LEXER(\*);\n\) LINK_LEXER(lmA68k); @@ -187,6 +188,8 @@ LINK_LEXER(lmYAML); //--Autogenerated -- end of automatically generated section +#endif + LINK_LEXER(lmLPeg); return 1; } diff -r eb69b2b4bb85 gtk/ScintillaGTK.cxx --- a/gtk/ScintillaGTK.cxx Mon Jan 18 09:02:53 2016 +1100 +++ b/gtk/ScintillaGTK.cxx Wed Jan 20 00:52:11 2016 -0500 @@ -3110,7 +3110,7 @@ // of the signal handlers here (those that currently attached to wDraw // in Initialise() may require coordinate translation?) - object_class->dispose = Dispose; + //object_class->dispose = Dispose; object_class->finalize = Destroy; #if GTK_CHECK_VERSION(3,0,0) widget_class->get_preferred_width = GetPreferredWidth; diff -r bfdfb44eb777 src/Document.cxx --- a/src/Document.cxx Sun May 22 08:57:20 2016 +1000 +++ b/src/Document.cxx Mon Jul 04 15:23:05 2016 -0400 @@ -2845,3 +2845,157 @@ #endif #endif + +#include "tre.h" + +class TreRegex : public RegexSearchBase { +public: + explicit TreRegex() : lastS(NULL), lastSLen(0) {} + virtual ~TreRegex() { if (lastS) free(lastS), tre_regfree(&preg); } + virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, + bool caseSensitive, bool word, bool wordStart, int flags, + int *length); + virtual const char *SubstituteByPosition(Document *doc, const char *text, + int *length); +private: + char *lastS; + int lastSLen; + regex_t preg; + regmatch_t pmatch[10]; + std::string substituted; +}; + +long TreRegex::FindText(Document *doc, int minPos, int maxPos, const char *s, + bool caseSensitive, bool, bool, int, + int *length) { + // Determine the search range. (From Document.cxx::RESearchRange.) + int increment, startPos, endPos; + if (minPos <= maxPos) + increment = 1, startPos = minPos, endPos = maxPos; + else + increment = -1, startPos = maxPos, endPos = minPos; + // 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); + int lineRangeStart = doc->LineFromPosition(startPos); + int lineRangeEnd = doc->LineFromPosition(endPos); + if (increment == 1 && startPos >= doc->LineEnd(lineRangeStart) && + lineRangeStart < lineRangeEnd) { + // The start position is at end of line or between line end characters. + lineRangeStart++; + startPos = doc->LineStart(lineRangeStart); + } else if (increment == -1 && startPos <= doc->LineStart(lineRangeStart) && + lineRangeStart > lineRangeEnd) { + // The start position is at beginning of line. + lineRangeStart--; + startPos = doc->LineEnd(lineRangeStart); + } + + // Compile the regex or used the cached one. + if (!lastS || lastSLen != *length || strncmp(lastS, s, *length) != 0) { + int cflags = REG_EXTENDED | (!caseSensitive ? REG_ICASE : 0) | REG_NEWLINE; + if (tre_regncomp(&preg, s, *length, cflags) != REG_OK) return -1; + if (lastS) free(lastS); + lastS = static_cast(malloc(*length + 1)); + strncpy(lastS, s, *length); + lastS[*length] = '\0'; + lastSLen = *length; + } + + // Perform the matching. + int pos = -1, lenRet = 0; + const char *string = doc->BufferPointer(); + size_t len = endPos - startPos; + int eflags = ((startPos != doc->LineStart(lineRangeStart)) ? REG_NOTBOL : 0) | + ((endPos != doc->LineEnd(lineRangeEnd)) ? REG_NOTEOL : 0); + int success = tre_regnexec(&preg, string + startPos, len, 10, pmatch, eflags) == REG_OK; + if (success) { + for (int i = 0; i < 10 && pmatch[i].rm_so != -1; i++) + pmatch[i].rm_so += startPos, pmatch[i].rm_eo += startPos; // adjust + pos = pmatch[0].rm_so, lenRet = pmatch[0].rm_eo - pmatch[0].rm_so; + if (increment == -1) { + // Check for the last match on this line. + int repetitions = 1000; // break out of infinite loop + while (success && pmatch[0].rm_eo <= endPos && repetitions--) { + success = tre_regnexec(&preg, string + pos + 1, len - (pos + 1), 10, + pmatch, eflags) == REG_OK; + if (success) { + for (int i = 0; i < 10 && pmatch[i].rm_so != -1; i++) + pmatch[i].rm_so += pos + 1, pmatch[i].rm_eo += pos + 1; // adjust + if (pmatch[0].rm_eo <= minPos) + pos = pmatch[0].rm_so, lenRet = pmatch[0].rm_eo - pmatch[0].rm_so; + else + success = 0; + } + } + } + } + *length = lenRet; + return pos; +} + +const char *TreRegex::SubstituteByPosition(Document *doc, const char *text, + int *length) { + substituted.clear(); + for (int j = 0; j < *length; j++) { + if (text[j] == '\\') { + if (text[j + 1] >= '0' && text[j + 1] <= '9') { + unsigned int patNum = text[j + 1] - '0'; + unsigned int len = pmatch[patNum].rm_eo - pmatch[patNum].rm_so; + if (len > 0) // will be -1 for a match that did not occur + substituted.append(doc->BufferPointer() + pmatch[patNum].rm_so, len); + j++; + } else { + j++; + switch (text[j]) { + case 'a': + substituted.push_back('\a'); + break; + case 'b': + substituted.push_back('\b'); + break; + case 'f': + substituted.push_back('\f'); + break; + case 'n': + substituted.push_back('\n'); + break; + case 'r': + substituted.push_back('\r'); + break; + case 't': + substituted.push_back('\t'); + break; + case 'v': + substituted.push_back('\v'); + break; + case '\\': + substituted.push_back('\\'); + break; + default: + substituted.push_back('\\'); + j--; + } + } + } else { + substituted.push_back(text[j]); + } + } + *length = static_cast(substituted.length()); + return substituted.c_str(); +} + +#ifdef SCI_NAMESPACE + +RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) { + return new TreRegex(); +} + +#else + +RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) { + return new TreRegex(); +} + +#endif diff --git a/gtk/ScintillaGTKAccessible.cxx b/gtk/ScintillaGTKAccessible.cxx --- a/gtk/ScintillaGTKAccessible.cxx +++ b/gtk/ScintillaGTKAccessible.cxx @@ -1064,10 +1064,12 @@ // @p cache pointer to store the AtkObject between repeated calls. Might or might not be filled. // @p widget_parent_class pointer to the widget's parent class (to chain up method calls). AtkObject *ScintillaGTKAccessible::WidgetGetAccessibleImpl(GtkWidget *widget, AtkObject **cache, gpointer widget_parent_class G_GNUC_UNUSED) { + if (*cache != NULL) { + return *cache; + } + #if HAVE_GTK_A11Y_H // just instantiate the accessible - if (*cache == NULL) { - *cache = scintilla_object_accessible_new(0, G_OBJECT(widget)); - } + *cache = scintilla_object_accessible_new(0, G_OBJECT(widget)); #elif HAVE_GTK_FACTORY // register in the factory and let GTK instantiate static volatile gsize registered = 0; @@ -1085,24 +1087,22 @@ } g_once_init_leave(®istered, 1); } - *cache = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget); + AtkObject *obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget); + *cache = static_cast(g_object_ref(obj)); #else // no public API, no factory, so guess from the parent and instantiate - if (*cache == NULL) { - static GType parent_atk_type = 0; + static GType parent_atk_type = 0; - if (parent_atk_type == 0) { - AtkObject *parent_obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget); - if (parent_obj) { - GType parent_atk_type = G_OBJECT_TYPE(parent_obj); + if (parent_atk_type == 0) { + AtkObject *parent_obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget); + if (parent_obj) { + GType parent_atk_type = G_OBJECT_TYPE(parent_obj); - // Figure out whether accessibility is enabled by looking at the type of the accessible - // object which would be created for the parent type of ScintillaObject. - if (g_type_is_a(parent_atk_type, GTK_TYPE_ACCESSIBLE)) { - *cache = scintilla_object_accessible_new(parent_atk_type, G_OBJECT(widget)); - g_object_unref(parent_obj); - } else { - *cache = parent_obj; - } + // Figure out whether accessibility is enabled by looking at the type of the accessible + // object which would be created for the parent type of ScintillaObject. + if (g_type_is_a(parent_atk_type, GTK_TYPE_ACCESSIBLE)) { + *cache = scintilla_object_accessible_new(parent_atk_type, G_OBJECT(widget)); + } else { + *cache = static_cast(g_object_ref(parent_obj)); } } }