? reflect-zvt
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/vte/src/Makefile.am,v
retrieving revision 1.74
diff -u -p -r1.74 Makefile.am
--- Makefile.am	2 Mar 2005 08:48:59 -0000	1.74
+++ Makefile.am	10 Mar 2005 19:37:12 -0000
@@ -155,6 +155,8 @@ iso2022_CFLAGS = @CFLAGS@ @GTK_CFLAGS@ -
 iso2022_SOURCES = \
 	buffer.c \
 	buffer.h \
+	caps.c \
+	caps.h \
 	debug.c \
 	debug.h \
 	iso2022.c \
@@ -166,13 +168,17 @@ iso2022_SOURCES = \
 	trie.c \
 	trie.h \
 	vteconv.c \
-	vteconv.h
+	vteconv.h \
+	vtetc.c \
+	vtetc.h
 iso2022_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
 
 utf8echo_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DUTF8ECHO_MAIN
 utf8echo_SOURCES = \
 	buffer.c \
 	buffer.h \
+	caps.c \
+	caps.h \
 	debug.c \
 	debug.h \
 	matcher.c \
@@ -183,7 +189,9 @@ utf8echo_SOURCES = \
 	trie.h \
 	utf8echo.c \
 	vteconv.c \
-	vteconv.h
+	vteconv.h \
+	vtetc.c \
+	vtetc.h
 utf8echo_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
 
 nativeecho_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DNATIVEECHO_MAIN
@@ -207,6 +215,8 @@ table_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@
 table_SOURCES = \
 	buffer.c \
 	buffer.h \
+	caps.c \
+	caps.h \
 	debug.c \
 	debug.h \
 	matcher.c \
@@ -216,13 +226,17 @@ table_SOURCES = \
 	trie.c \
 	trie.h \
 	vteconv.c \
-	vteconv.h
+	vteconv.h \
+	vtetc.c \
+	vtetc.h
 table_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
 
 trie_CFLAGS = @CFLAGS@ @GOBJECT_CFLAGS@ -DTRIE_MAIN
 trie_SOURCES = \
 	buffer.c \
 	buffer.h \
+	caps.c \
+	caps.h \
 	debug.c \
 	debug.h \
 	matcher.c \
@@ -234,7 +248,7 @@ trie_SOURCES = \
 	vteconv.c \
 	vteconv.h \
 	vtetc.c \
-	vtetc.h
+	vtetc.h 
 trie_LDADD = @LDFLAGS@ @LIBS@ @GOBJECT_LIBS@
 
 vtetc_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@ -DTERMCAP_MAIN
Index: interpret.c
===================================================================
RCS file: /cvs/gnome/vte/src/interpret.c,v
retrieving revision 1.21
diff -u -p -r1.21 interpret.c
--- interpret.c	15 Sep 2003 18:57:33 -0000	1.21
+++ interpret.c	10 Mar 2005 19:37:12 -0000
@@ -72,7 +72,6 @@ main(int argc, char **argv)
 
 	g_type_init();
 	terminal = argv[1];
-	matcher = _vte_matcher_new(terminal);
 	termcap = _vte_termcap_new(g_strdup_printf(DATADIR "/" PACKAGE
 						   "/termcap/%s", terminal));
 	if (termcap == NULL) {
@@ -81,29 +80,7 @@ main(int argc, char **argv)
 	buffer = _vte_buffer_new();
 	array = g_array_new(TRUE, TRUE, sizeof(gunichar));
 
-	for (i = 0;
-	     _vte_terminal_capability_strings[i].capability != NULL;
-	     i++) {
-		const char *capability;
-		char *tmp;
-		capability = _vte_terminal_capability_strings[i].capability;
-		if (_vte_terminal_capability_strings[i].key) {
-			continue;
-		}
-		tmp = _vte_termcap_find_string(termcap, terminal, capability);
-		if ((tmp != NULL) && (strlen(tmp) > 0)) {
-			_vte_matcher_add(matcher, tmp, strlen(tmp), capability,
-				       g_quark_from_static_string(capability));
-		}
-		g_free(tmp);
-	}
-	for (i = 0; _vte_xterm_capability_strings[i].value != NULL; i++) {
-		const char *code, *value;
-		code = _vte_xterm_capability_strings[i].code;
-		value = _vte_xterm_capability_strings[i].value;
-		_vte_matcher_add(matcher, code, strlen(code), value,
-				 g_quark_from_static_string(code));
-	}
+	matcher = _vte_matcher_new(terminal, termcap);
 
 	subst = _vte_iso2022_state_new(NULL, NULL, NULL);
 
Index: matcher.c
===================================================================
RCS file: /cvs/gnome/vte/src/matcher.c,v
retrieving revision 1.5
diff -u -p -r1.5 matcher.c
--- matcher.c	21 May 2003 21:42:16 -0000	1.5
+++ matcher.c	10 Mar 2005 19:37:13 -0000
@@ -24,11 +24,13 @@
 #include <string.h>
 #include <glib-object.h>
 #include "debug.h"
+#include "caps.h"
 #include "matcher.h"
 #include "table.h"
 #include "trie.h"
 
 struct _vte_matcher {
+	gboolean initialized;
 	enum {
 		_vte_matcher_table,
 		_vte_matcher_trie
@@ -37,23 +39,128 @@ struct _vte_matcher {
 	struct _vte_trie *trie;
 };
 
-/* Create an initial matcher. */
-struct _vte_matcher *
-_vte_matcher_new(const char *emulation_hint)
+static GStaticMutex _vte_matcher_mutex = G_STATIC_MUTEX_INIT;
+static GCache *_vte_matcher_cache = NULL;
+
+/* Add a string to the matcher. */
+static void
+_vte_matcher_add(struct _vte_matcher *matcher,
+		 const char *pattern, gssize length,
+		 const char *result, GQuark quark)
 {
+	switch (matcher->type) {
+	case _vte_matcher_table:
+		_vte_table_add(matcher->table, pattern, length, result, quark);
+		break;
+	case _vte_matcher_trie:
+		_vte_trie_add(matcher->trie, pattern, length, result, quark);
+		break;
+	}
+}
+
+/* Loads all sequences into matcher */
+static void
+_vte_matcher_init(struct _vte_matcher *matcher, char *emulation,
+		  struct _vte_termcap *termcap)
+{
+	const char *code, *value;
+	gboolean found_cr = FALSE, found_lf = FALSE;
+	gssize stripped_length;
+	char *stripped;
+	char *tmp;
+	int i;
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
+		fprintf(stderr, "_vte_matcher_init()\n");
+	}
+#endif
+
+	/* Load the known capability strings from the termcap structure into
+	 * the table for recognition. */
+	for (i = 0;
+	     _vte_terminal_capability_strings[i].capability != NULL;
+	     i++) {
+		if (_vte_terminal_capability_strings[i].key) {
+			continue;
+		}
+		code = _vte_terminal_capability_strings[i].capability;
+		tmp = _vte_termcap_find_string(termcap, emulation, code);
+		if ((tmp != NULL) && (tmp[0] != '\0')) {
+			_vte_termcap_strip(tmp, &stripped, &stripped_length);
+			_vte_matcher_add(matcher, stripped, stripped_length,
+					 code, 0);
+			if (stripped[0] == '\r') {
+				found_cr = TRUE;
+			} else
+			if (stripped[0] == '\n') {
+				if ((strcmp(code, "sf") == 0) ||
+				    (strcmp(code, "do") == 0)) {
+					found_lf = TRUE;
+				}
+			}
+			g_free(stripped);
+		}
+		g_free(tmp);
+	}
+
+	/* Add emulator-specific sequences. */
+	if (strstr(emulation, "xterm") || strstr(emulation, "dtterm")) {
+		/* Add all of the xterm-specific stuff. */
+		for (i = 0;
+		     _vte_xterm_capability_strings[i].value != NULL;
+		     i++) {
+			code = _vte_xterm_capability_strings[i].code;
+			value = _vte_xterm_capability_strings[i].value;
+			_vte_termcap_strip(code, &stripped, &stripped_length);
+			_vte_matcher_add(matcher, stripped, stripped_length,
+					 value, 0);
+			g_free(stripped);
+		}
+	}
+
+	/* Always define cr and lf. */
+	if (!found_cr) {
+		_vte_matcher_add(matcher, "\r", 1, "cr", 0);
+	}
+	if (!found_lf) {
+		_vte_matcher_add(matcher, "\n", 1, "sf", 0);
+	}
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_MISC)) {
+		fprintf(stderr, "Trie contents:\n");
+		_vte_matcher_print(matcher);
+		fprintf(stderr, "\n");
+	}
+#endif
+}
+
+/* Allocates new matcher structure. */
+static gpointer
+_vte_matcher_create(gpointer key)
+{
+	char *emulation = key;
 	struct _vte_matcher *ret = NULL;
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
+		fprintf(stderr, "_vte_matcher_create()\n");
+	}
+#endif
 	ret = g_malloc(sizeof(struct _vte_matcher));
+	ret->initialized = FALSE;
 	ret->type = _vte_matcher_trie;
 	ret->table = NULL;
 	ret->trie = NULL;
-	if (emulation_hint != NULL) {
-		if (strcmp(emulation_hint, "xterm") == 0) {
-			ret->type = _vte_matcher_table;
-		} else
-		if (strcmp(emulation_hint, "dtterm") == 0) {
-			ret->type = _vte_matcher_table;
-		}
+
+	if (strcmp(emulation, "xterm") == 0) {
+		ret->type = _vte_matcher_table;
+	} else
+	if (strcmp(emulation, "dtterm") == 0) {
+		ret->type = _vte_matcher_table;
 	}
+
 	switch (ret->type) {
 	case _vte_matcher_table:
 		ret->table = _vte_table_new();
@@ -62,13 +169,21 @@ _vte_matcher_new(const char *emulation_h
 		ret->trie = _vte_trie_new();
 		break;
 	}
+
 	return ret;
 }
 
-/* Free a matcher. */
-void
-_vte_matcher_free(struct _vte_matcher *matcher)
+/* Noone uses this matcher, free it. */
+static void
+_vte_matcher_destroy(gpointer value)
 {
+	struct _vte_matcher *matcher = value;
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
+		fprintf(stderr, "_vte_matcher_destroy()\n");
+	}
+#endif
 	if (matcher->table != NULL) {
 		_vte_table_free(matcher->table);
 	}
@@ -78,20 +193,42 @@ _vte_matcher_free(struct _vte_matcher *m
 	g_free(matcher);
 }
 
-/* Add a string to the matcher. */
-void
-_vte_matcher_add(struct _vte_matcher *matcher,
-		 const char *pattern, gssize length,
-		 const char *result, GQuark quark)
+/* Create and init matcher. */
+struct _vte_matcher *
+_vte_matcher_new(char *emulation, struct _vte_termcap *termcap)
 {
-	switch (matcher->type) {
-	case _vte_matcher_table:
-		_vte_table_add(matcher->table, pattern, length, result, quark);
-		break;
-	case _vte_matcher_trie:
-		_vte_trie_add(matcher->trie, pattern, length, result, quark);
-		break;
+	struct _vte_matcher *ret = NULL;
+	g_static_mutex_lock(&_vte_matcher_mutex);
+
+	if (emulation == NULL) {
+		emulation = "";
+	}
+
+	if (_vte_matcher_cache == NULL) {
+		_vte_matcher_cache = g_cache_new(_vte_matcher_create,
+				_vte_matcher_destroy, g_strdup, g_free,
+				g_str_hash, g_direct_hash, g_str_equal);
+	}
+
+	ret = g_cache_insert(_vte_matcher_cache, emulation);
+
+	if (!ret->initialized) {
+		_vte_matcher_init(ret, emulation, termcap);
+		ret->initialized = TRUE;
 	}
+
+	g_static_mutex_unlock(&_vte_matcher_mutex);
+	return ret;
+}
+
+/* Free a matcher. */
+void
+_vte_matcher_free(struct _vte_matcher *matcher)
+{
+	g_assert(_vte_matcher_cache != NULL);
+	g_static_mutex_lock(&_vte_matcher_mutex);
+	g_cache_remove(_vte_matcher_cache, matcher);
+	g_static_mutex_unlock(&_vte_matcher_mutex);
 }
 
 /* Check if a string matches a sequence the matcher knows about. */
Index: matcher.h
===================================================================
RCS file: /cvs/gnome/vte/src/matcher.h,v
retrieving revision 1.5
diff -u -p -r1.5 matcher.h
--- matcher.h	21 May 2003 21:42:16 -0000	1.5
+++ matcher.h	10 Mar 2005 19:37:13 -0000
@@ -24,21 +24,18 @@
 #ident "$Id: matcher.h,v 1.5 2003/05/21 21:42:16 nalin Exp $"
 
 #include <glib-object.h>
+#include "vtetc.h"
 
 G_BEGIN_DECLS
 
 struct _vte_matcher;
 
-/* Create an initial matcher. */
-struct _vte_matcher *_vte_matcher_new(const char *emulation_hint);
+/* Create and init matcher. */
+struct _vte_matcher *_vte_matcher_new(char *emulation,
+				      struct _vte_termcap *termcap);
 
 /* Free a matcher. */
 void _vte_matcher_free(struct _vte_matcher *matcher);
-
-/* Add a string to the matcher. */
-void _vte_matcher_add(struct _vte_matcher *matcher,
-		      const char *pattern, gssize length,
-		      const char *result, GQuark quark);
 
 /* Check if a string matches a sequence the matcher knows about. */
 const char *_vte_matcher_match(struct _vte_matcher *matcher,
Index: vte.c
===================================================================
RCS file: /cvs/gnome/vte/src/vte.c,v
retrieving revision 1.417
diff -u -p -r1.417 vte.c
--- vte.c	3 Mar 2005 06:40:44 -0000	1.417
+++ vte.c	10 Mar 2005 19:37:29 -0000
@@ -11011,13 +11011,9 @@ vte_terminal_set_scroll_adjustment(VteTe
 void
 vte_terminal_set_emulation(VteTerminal *terminal, const char *emulation)
 {
-	const char *code, *value;
-	gboolean found_cr = FALSE, found_lf = FALSE;
-	char *stripped;
-	gssize stripped_length;
+	const char *code;
 	int columns, rows;
 	GQuark quark;
-	char *tmp;
 	int i;
 
 	/* Set the emulation type, for reference. */
@@ -11038,7 +11034,7 @@ vte_terminal_set_emulation(VteTerminal *
 	if (terminal->pvt->matcher != NULL) {
 		_vte_matcher_free(terminal->pvt->matcher);
 	}
-	terminal->pvt->matcher = _vte_matcher_new(emulation);
+	terminal->pvt->matcher = _vte_matcher_new(emulation, terminal->pvt->termcap);
 
 	/* Create a tree to hold the handlers. */
 	if (terminal->pvt->sequences) {
@@ -11054,69 +11050,6 @@ vte_terminal_set_emulation(VteTerminal *
 		}
 	}
 
-	/* Load the known capability strings from the termcap structure into
-	 * the table for recognition. */
-	for (i = 0;
-	     _vte_terminal_capability_strings[i].capability != NULL;
-	     i++) {
-		if (_vte_terminal_capability_strings[i].key) {
-			continue;
-		}
-		code = _vte_terminal_capability_strings[i].capability;
-		tmp = _vte_termcap_find_string(terminal->pvt->termcap,
-					       terminal->pvt->emulation,
-					       code);
-		if ((tmp != NULL) && (tmp[0] != '\0')) {
-			_vte_termcap_strip(tmp, &stripped, &stripped_length);
-			_vte_matcher_add(terminal->pvt->matcher,
-					 stripped, stripped_length,
-					 code, 0);
-			if (stripped[0] == '\r') {
-				found_cr = TRUE;
-			} else
-			if (stripped[0] == '\n') {
-				if ((strcmp(code, "sf") == 0) ||
-				    (strcmp(code, "do") == 0)) {
-					found_lf = TRUE;
-				}
-			}
-			g_free(stripped);
-		}
-		g_free(tmp);
-	}
-
-	/* Add emulator-specific sequences. */
-	if (strstr(emulation, "xterm") || strstr(emulation, "dtterm")) {
-		/* Add all of the xterm-specific stuff. */
-		for (i = 0;
-		     _vte_xterm_capability_strings[i].value != NULL;
-		     i++) {
-			code = _vte_xterm_capability_strings[i].code;
-			value = _vte_xterm_capability_strings[i].value;
-			_vte_termcap_strip(code, &stripped, &stripped_length);
-			_vte_matcher_add(terminal->pvt->matcher,
-					 stripped, stripped_length,
-					 value, 0);
-			g_free(stripped);
-		}
-	}
-
-	/* Always define cr and lf. */
-	if (!found_cr) {
-		_vte_matcher_add(terminal->pvt->matcher, "\r", 1, "cr", 0);
-	}
-	if (!found_lf) {
-		_vte_matcher_add(terminal->pvt->matcher, "\n", 1, "sf", 0);
-	}
-
-#ifdef VTE_DEBUG
-	if (_vte_debug_on(VTE_DEBUG_MISC)) {
-		fprintf(stderr, "Trie contents:\n");
-		_vte_matcher_print(terminal->pvt->matcher);
-		fprintf(stderr, "\n");
-	}
-#endif
-
 	/* Read emulation flags. */
 	terminal->pvt->flags.am = _vte_termcap_find_boolean(terminal->pvt->termcap,
 							    terminal->pvt->emulation,
@@ -11405,7 +11338,6 @@ vte_terminal_init(VteTerminal *terminal,
 	/* Setting the terminal type and size requires the PTY master to
 	 * be set up properly first. */
 	pvt->pty_master = -1;
-	vte_terminal_set_termcap(terminal, NULL, FALSE);
 	vte_terminal_set_emulation(terminal, NULL);
 	vte_terminal_set_size(terminal,
 			      pvt->default_column_count,
Index: vtetc.c
===================================================================
RCS file: /cvs/gnome/vte/src/vtetc.c,v
retrieving revision 1.3
diff -u -p -r1.3 vtetc.c
--- vtetc.c	19 May 2003 22:48:58 -0000	1.3
+++ vtetc.c	10 Mar 2005 19:37:30 -0000
@@ -50,6 +50,9 @@ struct _vte_termcap {
 	GTree *nametree;
 };
 
+static GStaticMutex _vte_termcap_mutex = G_STATIC_MUTEX_INIT;
+static GCache *_vte_termcap_cache = NULL;
+
 static char *
 nextline(FILE *fp, gssize *outlen)
 {
@@ -334,12 +337,20 @@ _vte_direct_compare(gconstpointer a, gco
 	return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
 }
 
-TERMCAP_MAYBE_STATIC struct _vte_termcap *
-_vte_termcap_new(const char *filename)
+/* Allocates and initializes new termcap instance. */
+static gpointer
+_vte_termcap_create(gpointer key)
 {
+	const char *filename = key;
+	struct _vte_termcap *ret = NULL;
 	FILE *fp;
 	char *s, *stripped, *comment = NULL;
-	struct _vte_termcap *ret = NULL;
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
+		fprintf(stderr, "_vte_termcap_create()\n");
+	}
+#endif
 	fp = fopen(filename, "r");
 	if (fp != NULL) {
 		while ((s = nextline_with_continuation(fp)) != NULL) {
@@ -392,18 +403,19 @@ _vte_termcap_new(const char *filename)
 	return ret;
 }
 
-/**
- * _vte_termcap_free:
- * @termcap: the structure to be freed
- *
- * Frees the indicated structure.
- *
- */
-TERMCAP_MAYBE_STATIC void
-_vte_termcap_free(struct _vte_termcap *termcap)
+/* Noone uses termcap, destroy it. */
+static void
+_vte_termcap_destroy(gpointer key)
 {
+	struct _vte_termcap *termcap = key;
 	struct _vte_termcap_entry *entry, *nextentry;
 	struct _vte_termcap_alias *alias, *nextalias;
+
+#ifdef VTE_DEBUG
+	if (_vte_debug_on(VTE_DEBUG_LIFECYCLE)) {
+		fprintf(stderr, "_vte_termcap_destroy()\n");
+	}
+#endif
 	for (entry = termcap->entries; entry != NULL; entry = nextentry) {
 		nextentry = entry->next;
 		g_free(entry->comment);
@@ -423,6 +435,39 @@ _vte_termcap_free(struct _vte_termcap *t
 	g_free(termcap->comment);
 	termcap->comment = NULL;
 	g_free(termcap);
+}
+
+TERMCAP_MAYBE_STATIC struct _vte_termcap *
+_vte_termcap_new(char *filename)
+{
+	struct _vte_termcap *ret = NULL;
+	g_static_mutex_lock(&_vte_termcap_mutex);
+
+	if (_vte_termcap_cache == NULL) {
+		_vte_termcap_cache = g_cache_new(_vte_termcap_create,
+				_vte_termcap_destroy, g_strdup, g_free,
+				g_str_hash, g_direct_hash, g_str_equal);
+	}
+	ret = g_cache_insert(_vte_termcap_cache, filename);
+
+	g_static_mutex_unlock(&_vte_termcap_mutex);
+	return ret;
+}
+
+/**
+ * _vte_termcap_free:
+ * @termcap: the structure to be freed
+ *
+ * Frees the indicated structure.
+ *
+ */
+TERMCAP_MAYBE_STATIC void
+_vte_termcap_free(struct _vte_termcap *termcap)
+{
+	g_assert(_vte_termcap_cache != NULL);
+	g_static_mutex_lock(&_vte_termcap_mutex);
+	g_cache_remove(_vte_termcap_cache, termcap);
+	g_static_mutex_unlock(&_vte_termcap_mutex);
 }
 
 static const char *
Index: vtetc.h
===================================================================
RCS file: /cvs/gnome/vte/src/vtetc.h,v
retrieving revision 1.1
diff -u -p -r1.1 vtetc.h
--- vtetc.h	19 May 2003 20:18:45 -0000	1.1
+++ vtetc.h	10 Mar 2005 19:37:30 -0000
@@ -30,7 +30,7 @@ G_BEGIN_DECLS
 struct _vte_termcap;
 
 /* Create a new termcap structure. */
-struct _vte_termcap *_vte_termcap_new(const char *filename);
+struct _vte_termcap *_vte_termcap_new(char *filename);
 
 /* Free a termcap structure. */
 void _vte_termcap_free(struct _vte_termcap *termcap);
