96042352eb41d357d4d71509cc65c0b9eca3e9f2
diff --git a/src/reflect.c b/src/reflect.c
index f78d341..3d8f64b 100644
--- a/src/reflect.c
+++ b/src/reflect.c
@@ -59,6 +59,33 @@ static void
 terminal_init_vte(GtkWidget **terminal)
 {
 	*terminal = vte_terminal_new();
+#define USERCHARS "-A-Za-z0-9"
+#define PASSCHARS "-A-Za-z0-9,?;.:/!%$^*&~\"#'"
+#define HOSTCHARS "-A-Za-z0-9"
+#define PATHCHARS "-A-Za-z0-9_$.+!*(),;:@&=?/~#%"
+#define SCHEME    "(news:|telnet:|nntp:|file:/|https?:|ftps?:|webcal:)"
+#define USER      "[" USERCHARS "]+(:["PASSCHARS "]+)?"
+#define URLPATH   "/[" PATHCHARS "]*[^]'.}>) \t\r\n,\\\"]"
+  vte_terminal_match_add (*terminal,
+                             "\\<" SCHEME "//(" USER "@)?[" HOSTCHARS ".]+"
+                             "(:[0-9]+)?(" URLPATH ")?\\>/?");
+
+
+  vte_terminal_match_add (*terminal,
+                             "\\<(www|ftp)[" HOSTCHARS "]*\\.[" HOSTCHARS ".]+"
+                             "(:[0-9]+)?(" URLPATH ")?\\>/?");
+
+
+  vte_terminal_match_add (*terminal,
+                             "\\<(mailto:)?[a-z0-9][a-z0-9.-]*@[a-z0-9]"
+                             "[a-z0-9-]*(\\.[a-z0-9][a-z0-9-]*)+\\>");
+
+
+  vte_terminal_match_add (*terminal,
+                             "\\<news:[-A-Z\\^_a-z{|}~!\"#$%&'()*+,./0-9;:=?`]+"
+                             "@[" HOSTCHARS ".]+(:[0-9]+)?\\>");
+
+
 	g_signal_connect(G_OBJECT(*terminal), "eof",
 			 G_CALLBACK(gtk_main_quit), NULL);
 	g_signal_connect(G_OBJECT(*terminal), "child-exited",
diff --git a/src/vte-private.h b/src/vte-private.h
index ceed7ad..a43e5c3 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -124,9 +124,22 @@ struct vte_charcell {
 	} 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;
 };
diff --git a/src/vte.c b/src/vte.c
index 102065d..e043e94 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -1126,6 +1126,23 @@ vte_terminal_match_contents_refresh(VteTerminal *terminal)
 	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_VTE)
+        {
+                _vte_regex_free(regex->regex.reg);
+                regex->regex.reg = NULL;
+        }
+
+        regex->tag = -1;
+}
+
 /**
  * vte_terminal_match_clear_all:
  * @terminal: a #VteTerminal
@@ -1146,13 +1163,7 @@ vte_terminal_match_clear_all(VteTerminal *terminal)
 				       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 +1195,7 @@ vte_terminal_match_remove(VteTerminal *terminal, int tag)
 			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);
 }
@@ -1226,8 +1231,9 @@ vte_terminal_match_add(VteTerminal *terminal, const char *match)
 	g_return_val_if_fail(match != NULL, -1);
 	g_return_val_if_fail(strlen(match) > 0, -1);
 	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;
@@ -1443,7 +1449,7 @@ vte_terminal_match_check_internal(VteTerminal *terminal,
 		 * 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 +1530,7 @@ vte_terminal_match_check_internal(VteTerminal *terminal,
 			if (k > offset) {
 				break;
 			}
-			ret = _vte_regex_exec(regex->reg,
+			ret = _vte_regex_exec(regex->regex.reg,
 					      line + k,
 					      G_N_ELEMENTS(matches),
 					      matches);
@@ -7821,10 +7827,7 @@ vte_terminal_finalize(GObject *object)
 			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);
 	}
diff --git a/src/vte.h b/src/vte.h
index 375a9b1..f7faa4c 100644
--- a/src/vte.h
+++ b/src/vte.h
@@ -363,7 +363,10 @@ void vte_terminal_match_clear_all(VteTerminal *terminal);
 
 /* 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);
