vte r2063 - in trunk: . doc/reference doc/reference/tmpl src



Author: chpe
Date: Tue Jun 24 18:12:23 2008
New Revision: 2063
URL: http://svn.gnome.org/viewvc/vte?rev=2063&view=rev

Log:
Bug 418918 â Switch to GRegex

Modified:
   trunk/ChangeLog
   trunk/doc/reference/tmpl/vte.sgml
   trunk/doc/reference/vte-sections.txt
   trunk/src/vte-private.h
   trunk/src/vte.c
   trunk/src/vte.h

Modified: trunk/doc/reference/tmpl/vte.sgml
==============================================================================
--- trunk/doc/reference/tmpl/vte.sgml	(original)
+++ trunk/doc/reference/tmpl/vte.sgml	Tue Jun 24 18:12:23 2008
@@ -847,6 +847,17 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION vte_terminal_match_add_gregex ##### -->
+<para>
+
+</para>
+
+ terminal: 
+ regex: 
+ flags: 
+ Returns: 
+
+
 <!-- ##### FUNCTION vte_terminal_match_remove ##### -->
 <para>
 

Modified: trunk/doc/reference/vte-sections.txt
==============================================================================
--- trunk/doc/reference/vte-sections.txt	(original)
+++ trunk/doc/reference/vte-sections.txt	Tue Jun 24 18:12:23 2008
@@ -63,6 +63,7 @@
 vte_terminal_get_cursor_position
 vte_terminal_match_clear_all
 vte_terminal_match_add
+vte_terminal_match_add_gregex
 vte_terminal_match_remove
 vte_terminal_match_check
 vte_terminal_match_set_cursor

Modified: trunk/src/vte-private.h
==============================================================================
--- trunk/src/vte-private.h	(original)
+++ trunk/src/vte-private.h	Tue Jun 24 18:12:23 2008
@@ -124,9 +124,22 @@
 	} attr;
 };
 
+typedef enum {
+        VTE_REGEX_GREGEX,
+        VTE_REGEX_VTE,
+        VTE_REGEX_UNDECIDED
+} VteRegexMode;
+
 /* A match regex, with a tag. */
 struct vte_match_regex {
-	struct _vte_regex *reg;
+        VteRegexMode mode;
+        union { /* switched on |mode| */
+              struct {
+                    GRegex *regex;
+                    GRegexMatchFlags flags;
+              } gregex;
+              struct _vte_regex *reg;
+        } regex;
 	gint tag;
 	GdkCursor *cursor;
 };
@@ -313,6 +326,7 @@
 	/* State variables for handling match checks. */
 	char *match_contents;
 	GArray *match_attributes;
+        VteRegexMode match_regex_mode;
 	GArray *match_regexes;
 	char *match;
 	int match_tag;

Modified: trunk/src/vte.c
==============================================================================
--- trunk/src/vte.c	(original)
+++ trunk/src/vte.c	Tue Jun 24 18:12:23 2008
@@ -1126,6 +1126,28 @@
 	terminal->pvt->match_attributes = array;
 }
 
+static void
+regex_match_clear (struct vte_match_regex *regex)
+{
+        if (regex->cursor != NULL) {
+                gdk_cursor_unref(regex->cursor);
+                regex->cursor = NULL;
+        }
+
+        if (regex->mode == VTE_REGEX_GREGEX)
+        {
+                g_regex_unref(regex->regex.gregex.regex);
+                regex->regex.gregex.regex = NULL;
+        }
+        else if (regex->mode == VTE_REGEX_VTE)
+        {
+                _vte_regex_free(regex->regex.reg);
+                regex->regex.reg = NULL;
+        }
+
+        regex->tag = -1;
+}
+
 /**
  * vte_terminal_match_clear_all:
  * @terminal: a #VteTerminal
@@ -1146,13 +1168,7 @@
 				       i);
 		/* Unless this is a hole, clean it up. */
 		if (regex->tag >= 0) {
-			if (regex->cursor != NULL) {
-				gdk_cursor_unref(regex->cursor);
-				regex->cursor = NULL;
-			}
-			_vte_regex_free(regex->reg);
-			regex->reg = NULL;
-			regex->tag = -1;
+                        regex_match_clear (regex);
 		}
 	}
 	g_array_set_size(terminal->pvt->match_regexes, 0);
@@ -1184,13 +1200,7 @@
 			return;
 		}
 		/* Remove this item and leave a hole in its place. */
-		if (regex->cursor != NULL) {
-			gdk_cursor_unref(regex->cursor);
-			regex->cursor = NULL;
-		}
-		_vte_regex_free(regex->reg);
-		regex->reg = NULL;
-		regex->tag = -1;
+                regex_match_clear (regex);
 	}
 	vte_terminal_match_hilite_clear(terminal);
 }
@@ -1216,6 +1226,8 @@
  * this expression, the text will be highlighted.
  *
  * Returns: an integer associated with this expression
+ *
+ * @Deprecated: 0.16.15
  */
 int
 vte_terminal_match_add(VteTerminal *terminal, const char *match)
@@ -1223,11 +1235,16 @@
 	struct vte_match_regex new_regex, *regex;
 	guint ret;
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
+        g_return_val_if_fail(terminal->pvt->match_regex_mode != VTE_REGEX_GREGEX, -1);
 	g_return_val_if_fail(match != NULL, -1);
 	g_return_val_if_fail(strlen(match) > 0, -1);
+
+        terminal->pvt->match_regex_mode = VTE_REGEX_VTE;
+
 	memset(&new_regex, 0, sizeof(new_regex));
-	new_regex.reg = _vte_regex_compile(match);
-	if (new_regex.reg == NULL) {
+        new_regex.mode = VTE_REGEX_VTE;
+	new_regex.regex.reg = _vte_regex_compile(match);
+	if (new_regex.regex.reg == NULL) {
 		g_warning(_("Error compiling regular expression \"%s\"."),
 			  match);
 		return -1;
@@ -1259,6 +1276,65 @@
 }
 
 /**
+ * vte_terminal_match_add_gregex:
+ * @terminal: a #VteTerminal
+ * @regex: a #GRegex
+ * @flags: the #GRegexMatchFlags to use when matching the regex
+ *
+ * Adds the regular expression @regex to the list of matching expressions.  When the
+ * user moves the mouse cursor over a section of displayed text which matches
+ * this expression, the text will be highlighted.
+ *
+ * Returns: an integer associated with this expression
+ *
+ * Since: 0.16.15
+ */
+int
+vte_terminal_match_add_gregex(VteTerminal *terminal, GRegex *regex, GRegexMatchFlags flags)
+{
+	VteTerminalPrivate *pvt;
+	struct vte_match_regex new_regex_match, *regex_match;
+	guint ret, len;
+
+	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), -1);
+        g_return_val_if_fail(terminal->pvt->match_regex_mode != VTE_REGEX_VTE, -1);
+	g_return_val_if_fail(regex != NULL, -1);
+
+        pvt = terminal->pvt;
+        pvt->match_regex_mode = VTE_REGEX_GREGEX;
+
+	/* Search for a hole. */
+        len = pvt->match_regexes->len;
+	for (ret = 0; ret < len; ret++) {
+		regex_match = &g_array_index(pvt->match_regexes,
+                                             struct vte_match_regex,
+                                             ret);
+		if (regex_match->tag == -1) {
+			break;
+		}
+	}
+
+	/* Set the tag to the insertion point. */
+        new_regex_match.mode = VTE_REGEX_GREGEX;
+        new_regex_match.regex.gregex.regex = g_regex_ref(regex);
+        new_regex_match.regex.gregex.flags = flags;
+	new_regex_match.tag = ret;
+	new_regex_match.cursor = vte_terminal_cursor_new(terminal,
+                                                         VTE_DEFAULT_CURSOR);
+	if (ret < pvt->match_regexes->len) {
+		/* Overwrite. */
+		g_array_index(pvt->match_regexes,
+			      struct vte_match_regex,
+			      ret) = new_regex_match;
+	} else {
+		/* Append. */
+		g_array_append_val(pvt->match_regexes, new_regex_match);
+	}
+
+	return new_regex_match.tag;
+}
+
+/**
  * vte_terminal_match_set_cursor:
  * @terminal: a #VteTerminal
  * @tag: the tag of the regex which should use the specified cursor
@@ -1314,9 +1390,9 @@
  * it does, return the string, and store the match tag in the optional tag
  * argument. */
 static char *
-vte_terminal_match_check_internal(VteTerminal *terminal,
-				  long column, glong row,
-				  int *tag, int *start, int *end)
+vte_terminal_match_check_internal_vte(VteTerminal *terminal,
+                                      long column, glong row,
+                                      int *tag, int *start, int *end)
 {
 	struct _vte_regex_match matches[256];
 	gint i, j, k;
@@ -1443,7 +1519,7 @@
 		 * matches, so we'll have to skip each match until we
 		 * stop getting matches. */
 		k = 0;
-		ret = _vte_regex_exec(regex->reg,
+		ret = _vte_regex_exec(regex->regex.reg,
 				      line + k,
 				      G_N_ELEMENTS(matches),
 				      matches);
@@ -1524,7 +1600,7 @@
 			if (k > offset) {
 				break;
 			}
-			ret = _vte_regex_exec(regex->reg,
+			ret = _vte_regex_exec(regex->regex.reg,
 					      line + k,
 					      G_N_ELEMENTS(matches),
 					      matches);
@@ -1540,6 +1616,243 @@
 	return NULL;
 }
 
+/* Check if a given cell on the screen contains part of a matched string.  If
+ * it does, return the string, and store the match tag in the optional tag
+ * argument. */
+static char *
+vte_terminal_match_check_internal_gregex(VteTerminal *terminal,
+                                         long column, glong row,
+                                         int *tag, int *start, int *end)
+{
+	gint start_blank, end_blank;
+        guint i;
+	int offset;
+	struct vte_match_regex *regex = NULL;
+	struct _VteCharAttributes *attr = NULL;
+	gssize sattr, eattr;
+	gchar *line, eol;
+        GMatchInfo *match_info;
+
+	_vte_debug_print(VTE_DEBUG_EVENTS,
+			"Checking for match at (%ld,%ld).\n", row, column);
+	*tag = -1;
+	if (start != NULL) {
+		*start = 0;
+	}
+	if (end != NULL) {
+		*end = 0;
+	}
+	if (terminal->pvt->match_contents == NULL) {
+		vte_terminal_match_contents_refresh(terminal);
+	}
+	/* Map the pointer position to a portion of the string. */
+	eattr = terminal->pvt->match_attributes->len;
+	for (offset = eattr; offset--; ) {
+		attr = &g_array_index(terminal->pvt->match_attributes,
+				      struct _VteCharAttributes,
+				      offset);
+		if (row < attr->row) {
+			eattr = offset;
+		}
+		if (row == attr->row &&
+		    column == attr->column &&
+		    terminal->pvt->match_contents[offset] != ' ') {
+			break;
+		}
+	}
+
+	_VTE_DEBUG_IF(VTE_DEBUG_EVENTS) {
+		if (offset < 0)
+			g_printerr("Cursor is not on a character.\n");
+		else
+			g_printerr("Cursor is on character '%c' at %d.\n",
+					g_utf8_get_char (terminal->pvt->match_contents + offset),
+					offset);
+	}
+
+	/* If the pointer isn't on a matchable character, bug out. */
+	if (offset < 0) {
+		return NULL;
+	}
+
+	/* If the pointer is on a newline, bug out. */
+	if ((g_ascii_isspace(terminal->pvt->match_contents[offset])) ||
+	    (terminal->pvt->match_contents[offset] == '\0')) {
+		_vte_debug_print(VTE_DEBUG_EVENTS,
+				"Cursor is on whitespace.\n");
+		return NULL;
+	}
+
+	/* Snip off any final newlines. */
+	while (terminal->pvt->match_contents[eattr] == '\n' ||
+			terminal->pvt->match_contents[eattr] == '\0') {
+		eattr--;
+	}
+	/* and scan forwards to find the end of this line */
+	while (!(terminal->pvt->match_contents[eattr] == '\n' ||
+			terminal->pvt->match_contents[eattr] == '\0')) {
+		eattr++;
+	}
+
+	/* find the start of row */
+	if (row == 0) {
+		sattr = 0;
+	} else {
+		for (sattr = offset; sattr > 0; sattr--) {
+			attr = &g_array_index(terminal->pvt->match_attributes,
+					      struct _VteCharAttributes,
+					      sattr);
+			if (row > attr->row) {
+				break;
+			}
+		}
+	}
+	/* Scan backwards to find the start of this line */
+	while (sattr > 0 &&
+		! (terminal->pvt->match_contents[sattr] == '\n' ||
+		    terminal->pvt->match_contents[sattr] == '\0')) {
+		sattr--;
+	}
+	/* and skip any initial newlines. */
+	while (terminal->pvt->match_contents[sattr] == '\n' ||
+		terminal->pvt->match_contents[sattr] == '\0') {
+		sattr++;
+	}
+	if (eattr <= sattr) { /* blank line */
+		return NULL;
+	}
+	if (eattr <= offset || sattr > offset) {
+		/* nothing to match on this line */
+		return NULL;
+	}
+	offset -= sattr;
+	eattr -= sattr;
+
+	/* temporarily shorten the contents to this row */
+	line = terminal->pvt->match_contents + sattr;
+	eol = line[eattr];
+	line[eattr] = '\0';
+
+	start_blank = 0;
+	end_blank = eattr;
+
+	/* Now iterate over each regex we need to match against. */
+	for (i = 0; i < terminal->pvt->match_regexes->len; i++) {
+		regex = &g_array_index(terminal->pvt->match_regexes,
+				       struct vte_match_regex,
+				       i);
+		/* Skip holes. */
+		if (regex->tag < 0) {
+			continue;
+		}
+		/* We'll only match the first item in the buffer which
+		 * matches, so we'll have to skip each match until we
+		 * stop getting matches. */
+                if (!g_regex_match_full(regex->regex.gregex.regex,
+                                        line, -1, 0,
+                                        regex->regex.gregex.flags,
+                                        &match_info,
+                                        NULL))
+                        continue;
+
+                while (g_match_info_matches(match_info)) {
+			gint ko = offset;
+			gint sblank=G_MININT, eblank=G_MAXINT;
+                        gint rm_so, rm_eo;
+
+                        if (g_match_info_fetch_pos (match_info, 0, &rm_so, &rm_eo)) {
+				/* The offsets should be "sane". */
+				g_assert(rm_so < eattr);
+				g_assert(rm_eo <= eattr);
+				_VTE_DEBUG_IF(VTE_DEBUG_MISC) {
+					gchar *match;
+					struct _VteCharAttributes *_sattr, *_eattr;
+					match = g_strndup(line + rm_so, rm_eo - rm_so);
+					_sattr = &g_array_index(terminal->pvt->match_attributes,
+							struct _VteCharAttributes,
+							rm_so);
+					_eattr = &g_array_index(terminal->pvt->match_attributes,
+							struct _VteCharAttributes,
+							rm_eo - 1);
+					g_printerr("Match `%s' from %d(%ld,%ld) to %d(%ld,%ld) (%d).\n",
+							match,
+							rm_so,
+							_sattr->column,
+							_sattr->row,
+							rm_eo - 1,
+							_eattr->column,
+							_eattr->row,
+							offset);
+					g_free(match);
+
+				}
+				/* If the pointer is in this substring,
+				 * then we're done. */
+				if (ko >= rm_so &&
+				    ko < rm_eo) {
+					gchar *result;
+					if (tag != NULL) {
+						*tag = regex->tag;
+					}
+					if (start != NULL) {
+						*start = sattr + rm_so;
+					}
+					if (end != NULL) {
+						*end = sattr + rm_eo - 1;
+					}
+					if (GTK_WIDGET_REALIZED(terminal)) {
+						gdk_window_set_cursor(terminal->widget.window,
+								      regex->cursor);
+					}
+                                        result = g_match_info_fetch(match_info, 0);
+					line[eattr] = eol;
+
+                                        g_match_info_free(match_info);
+					return result;
+				}
+				if (ko > rm_eo &&
+						rm_eo > sblank) {
+					sblank = rm_eo;
+				}
+				if (ko < rm_so &&
+						rm_so < eblank) {
+					eblank = rm_so;
+				}
+			}
+			if (sblank > start_blank) {
+				start_blank = sblank;
+			}
+			if (eblank < end_blank) {
+				end_blank = eblank;
+			}
+
+                        g_match_info_next(match_info, NULL);
+		}
+
+                g_match_info_free(match_info);
+	}
+	line[eattr] = eol;
+	if (start != NULL) {
+		*start = sattr + start_blank;
+	}
+	if (end != NULL) {
+		*end = sattr + end_blank;
+	}
+	return NULL;
+}
+
+static char *
+vte_terminal_match_check_internal(VteTerminal *terminal,
+                                  long column, glong row,
+                                  int *tag, int *start, int *end)
+{
+        if (terminal->pvt->match_regex_mode == VTE_REGEX_GREGEX)
+                return vte_terminal_match_check_internal_gregex(terminal, column, row, tag, start, end);
+        if (terminal->pvt->match_regex_mode == VTE_REGEX_VTE)
+                return vte_terminal_match_check_internal_vte(terminal, column, row, tag, start, end);
+        return NULL;
+}
+
 static gboolean
 rowcol_inside_match (VteTerminal *terminal, glong row, glong col)
 {
@@ -7502,6 +7815,7 @@
 	pvt->cursor_blink_timeout = 500;
 
 	/* Matching data. */
+        pvt->match_regex_mode = VTE_REGEX_UNDECIDED;
 	pvt->match_regexes = g_array_new(FALSE, FALSE,
 					 sizeof(struct vte_match_regex));
 	vte_terminal_match_hilite_clear(terminal);
@@ -7821,10 +8135,7 @@
 			if (regex->tag < 0) {
 				continue;
 			}
-			if (regex->cursor != NULL) {
-				gdk_cursor_unref(regex->cursor);
-			}
-			_vte_regex_free(regex->reg);
+                        regex_match_clear(regex);
 		}
 		g_array_free(terminal->pvt->match_regexes, TRUE);
 	}

Modified: trunk/src/vte.h
==============================================================================
--- trunk/src/vte.h	(original)
+++ trunk/src/vte.h	Tue Jun 24 18:12:23 2008
@@ -365,7 +365,10 @@
 
 /* Add a matching expression, returning the tag the widget assigns to that
  * expression. */
-int vte_terminal_match_add(VteTerminal *terminal, const char *match);
+#ifndef VTE_DISABLE_DEPRECATED
+int vte_terminal_match_add(VteTerminal *terminal, const char *match) G_GNUC_DEPRECATED;
+#endif /* VTE_DISABLE_DEPRECATED */
+int vte_terminal_match_add_gregex(VteTerminal *terminal, GRegex *regex, GRegexMatchFlags flags);
 /* Set the cursor to be used when the pointer is over a given match. */
 void vte_terminal_match_set_cursor(VteTerminal *terminal, int tag,
 				   GdkCursor *cursor);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]