[vte] Refactor search



commit ae08c6d9c1a2f1d9f5fee8658ddbed2321b1b0e1
Author: Behdad Esfahbod <behdad behdad org>
Date:   Sun May 2 03:23:29 2010 -0400

    Refactor search

 src/vte-private.h |    1 +
 src/vte.c         |  186 +++++++++++++++++++++++++++++++++-------------------
 2 files changed, 119 insertions(+), 68 deletions(-)
---
diff --git a/src/vte-private.h b/src/vte-private.h
index 991aa9d..e89493c 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -320,6 +320,7 @@ struct _VteTerminalPrivate {
 	/* Search data. */
 	GRegex *search_regex;
 	gboolean search_wrap_around;
+	GArray *search_attrs; /* Cache attrs */
 
 	/* Data used when rendering the text which does not require server
 	 * resources and which can be kept after unrealizing. */
diff --git a/src/vte.c b/src/vte.c
index 6d9ae89..fa53085 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -8474,6 +8474,11 @@ vte_terminal_finalize(GObject *object)
 		g_array_free(terminal->pvt->match_regexes, TRUE);
 	}
 
+	if (terminal->pvt->search_regex)
+		g_regex_unref (terminal->pvt->search_regex);
+	if (terminal->pvt->search_attrs)
+		g_array_free (terminal->pvt->search_attrs, TRUE);
+
 	/* Disconnect from toplevel window configure events. */
 	toplevel = gtk_widget_get_toplevel(&terminal->widget);
 	if ((toplevel != NULL) && (G_OBJECT(toplevel) != object)) {
@@ -14582,95 +14587,140 @@ vte_terminal_search_get_wrap_around (VteTerminal *terminal)
 	return terminal->pvt->search_wrap_around;
 }
 
-gboolean
-vte_terminal_search_find_previous (VteTerminal *terminal)
+static gboolean
+vte_terminal_search_rows (VteTerminal *terminal,
+			  long start_row,
+			  long end_row)
 {
-	gboolean result = FALSE;
         VteTerminalPrivate *pvt;
+	char *row_text;
+	GMatchInfo *match_info;
+	GError *error = NULL;
+	int start, end;
+	long start_col, end_col;
+	gchar *word;
+	VteCharAttributes *ca;
 	GArray *attrs;
-	long row;
-
-	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), result);
 
 	pvt = terminal->pvt;
 
-	if (!pvt->search_regex)
-		return result;
-
-	if (pvt->has_selection)
-		row = pvt->selection_start.row - 1;
-	else
-		row = MIN (pvt->screen->scroll_delta + terminal->row_count,
-			   _vte_ring_next (terminal->pvt->screen->row_data)) - 1;
-
-	/* TODO cache this */
-	attrs = g_array_new (FALSE, TRUE, sizeof (VteCharAttributes));
-
-	for (; row >= _vte_ring_delta (terminal->pvt->screen->row_data); row--) {
-		char *row_text;
-		GMatchInfo *match_info;
-		GError *error = NULL;
-		int start, end;
-		long start_row, start_col, end_row, end_col;
-		gchar *word;
-		VteCharAttributes *ca;
-
-		row_text = vte_terminal_get_text_range (terminal, row, 0, row + 1, -1, NULL, NULL, attrs);
-
-		g_regex_match_full (pvt->search_regex, row_text, -1, 0, G_REGEX_MATCH_NOTEMPTY, &match_info, &error);
-		if (error) {
-			g_printerr ("Error while matching: %s\n", error->message);
-			g_error_free (error);
-			g_match_info_free (match_info);
-			g_free (row_text);
-			break;
-		}
-
-		if (!g_match_info_matches (match_info)) {
-			g_match_info_free (match_info);
-			g_free (row_text);
-			continue;
-		}
+	row_text = vte_terminal_get_text_range (terminal, start_row, 0, end_row, -1, NULL, NULL, NULL);
 
-		word = g_match_info_fetch (match_info, 0);
+	g_regex_match_full (pvt->search_regex, row_text, -1, 0, G_REGEX_MATCH_NOTEMPTY, &match_info, &error);
+	if (error) {
+		g_printerr ("Error while matching: %s\n", error->message);
+		g_error_free (error);
+		g_match_info_free (match_info);
+		g_free (row_text);
+		return TRUE;
+	}
 
-		/* This gives us the offset in the buffer */
-		g_match_info_fetch_pos (match_info, 0, &start, &end);
+	if (!g_match_info_matches (match_info)) {
+		g_match_info_free (match_info);
+		g_free (row_text);
+		return FALSE;
+	}
 
-		ca = &g_array_index (attrs, VteCharAttributes, start);
-		start_row = ca->row;
-		start_col = ca->column;
-		ca = &g_array_index (attrs, VteCharAttributes, end - 1);
-		end_row = ca->row;
-		end_col = ca->column;
+	word = g_match_info_fetch (match_info, 0);
 
-		g_free (word);
-		g_free (row_text);
-		g_match_info_free (match_info);
+	/* Fetch text again, with attributes */
+	g_free (row_text);
+	if (!pvt->search_attrs)
+		pvt->search_attrs = g_array_new (FALSE, TRUE, sizeof (VteCharAttributes));
+	attrs = pvt->search_attrs;
+	row_text = vte_terminal_get_text_range (terminal, start_row, 0, end_row, -1, NULL, NULL, attrs);
 
-		gtk_adjustment_set_value (terminal->adjustment, row);
-		_vte_terminal_select_text (terminal, start_col, start_row, end_col, end_row, 0, 0);
+	/* This gives us the offset in the buffer */
+	g_match_info_fetch_pos (match_info, 0, &start, &end);
 
-		result = TRUE;
-		break;
-	}
+	ca = &g_array_index (attrs, VteCharAttributes, start);
+	start_row = ca->row;
+	start_col = ca->column;
+	ca = &g_array_index (attrs, VteCharAttributes, end - 1);
+	end_row = ca->row;
+	end_col = ca->column;
 
-	g_array_free (attrs, TRUE);
+	g_free (word);
+	g_free (row_text);
+	g_match_info_free (match_info);
 
-	if (!result)
-		vte_terminal_deselect_all (terminal);
+	_vte_terminal_select_text (terminal, start_col, start_row, end_col, end_row, 0, 0);
+	/* TODO present the result better */
+	gtk_adjustment_set_value (terminal->adjustment, start_row);
 
-	return result;
+	return TRUE;
 }
 
-gboolean
-vte_terminal_search_find_next (VteTerminal *terminal)
+static gboolean
+vte_terminal_search_find (VteTerminal *terminal,
+			  gboolean     backward)
 {
+        VteTerminalPrivate *pvt;
+	const VteRowData *row;
+	long buffer_start_row, buffer_end_row;
+	long current_start_row, current_end_row;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
 
-	if (!terminal->pvt->search_regex)
+	pvt = terminal->pvt;
+	if (!pvt->search_regex)
 		return FALSE;
 
-	/* TODO */
+	/* TODO Currently we only find one result per extended line */
+
+	buffer_start_row = _vte_ring_delta (terminal->pvt->screen->row_data);
+	buffer_end_row = _vte_ring_next (terminal->pvt->screen->row_data);
+
+	if (pvt->has_selection) {
+		current_start_row = pvt->selection_start.row;
+		current_end_row = pvt->selection_end.row + 1;
+	} else {
+		current_start_row = pvt->screen->scroll_delta + terminal->row_count;
+		current_end_row = pvt->screen->scroll_delta;
+	}
+	current_start_row = MAX (buffer_start_row, current_start_row);
+	current_end_row = MIN (buffer_end_row, current_end_row);
+
+	if (backward) {
+		while (current_start_row > buffer_start_row) {
+			current_end_row = current_start_row;
+
+			do {
+				current_start_row--;
+				row = _vte_terminal_find_row_data (terminal, current_start_row);
+			} while (row && row->attr.soft_wrapped);
+
+			if (vte_terminal_search_rows (terminal, current_start_row, current_end_row))
+				return TRUE;
+		}
+		/* TODO wrap-around */
+	} else {
+		while (current_end_row < buffer_end_row) {
+			current_start_row = current_end_row;
+
+			do {
+				row = _vte_terminal_find_row_data (terminal, current_end_row);
+				current_end_row++;
+			} while (row && row->attr.soft_wrapped);
+
+			if (vte_terminal_search_rows (terminal, current_start_row, current_end_row))
+				return TRUE;
+		}
+		/* TODO wrap-around */
+	}
+
+	vte_terminal_deselect_all (terminal);
 	return FALSE;
 }
+
+gboolean
+vte_terminal_search_find_previous (VteTerminal *terminal)
+{
+	return vte_terminal_search_find (terminal, TRUE);
+}
+
+gboolean
+vte_terminal_search_find_next (VteTerminal *terminal)
+{
+	return vte_terminal_search_find (terminal, FALSE);
+}



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