41 |
#include "main.h" |
#include "main.h" |
42 |
#include "search.h" |
#include "search.h" |
43 |
#include "filesops.h" |
#include "filesops.h" |
44 |
|
#include "interface.h" |
45 |
|
|
46 |
extern GArray *FileProperties; |
extern GArray *FileProperties; |
47 |
extern GtkWidget *MainNotebook; |
extern GtkWidget *MainNotebook; |
53 |
|
|
54 |
static GtkWidget *SearchDisplay = NULL; |
static GtkWidget *SearchDisplay = NULL; |
55 |
static GtkWidget *SearchTree = NULL; |
static GtkWidget *SearchTree = NULL; |
56 |
|
static GArray *SearchResults = NULL; /* holds file_results structures */ |
57 |
|
|
58 |
struct line_match |
struct line_match |
59 |
{ |
{ |
69 |
GPtrArray *results; |
GPtrArray *results; |
70 |
}; |
}; |
71 |
|
|
72 |
|
/* this is just a helper function for go_to_search_result */ |
73 |
|
static gboolean scroll_idle_helper (GtkTextView *view) |
74 |
|
{ |
75 |
|
show_cursor_on_screen (view); |
76 |
|
|
77 |
|
return FALSE; |
78 |
|
} |
79 |
|
|
80 |
|
void go_to_search_result (struct file_results *result, gint match_num) |
81 |
|
{ |
82 |
|
struct line_match *match; |
83 |
|
gint page; |
84 |
|
GtkTextIter iter, next; |
85 |
|
|
86 |
|
match = g_ptr_array_index (result->results, match_num); |
87 |
|
|
88 |
|
if (match->line == 0) |
89 |
|
{ |
90 |
|
/* it's an invalid entry, like a binary file or something */ |
91 |
|
return; |
92 |
|
} |
93 |
|
|
94 |
|
/* first, we should look for open files, starting at the |
95 |
|
current page, that match the filename */ |
96 |
|
if (result->buffer) |
97 |
|
{ |
98 |
|
/* ok, this is from a buffer search */ |
99 |
|
for (page = 0; page < OpenedFilesCnt; page++) |
100 |
|
{ |
101 |
|
if (FPROPS (page, Text) == result->buffer) |
102 |
|
break; |
103 |
|
} |
104 |
|
|
105 |
|
if (page == OpenedFilesCnt) |
106 |
|
{ |
107 |
|
/* what? well, let's open it */ |
108 |
|
page = -1; |
109 |
|
} |
110 |
|
} |
111 |
|
else |
112 |
|
{ |
113 |
|
/* first, we want to find an appropriate buffer to use */ |
114 |
|
/* we first look to see if one is open. if not, open one */ |
115 |
|
for (page = 0; page < OpenedFilesCnt; page++) |
116 |
|
{ |
117 |
|
if (!strcmp (FPROPS (page, Name), result->path) && |
118 |
|
!gtk_text_buffer_get_modified (FPROPS (page, Buffer))) |
119 |
|
{ |
120 |
|
break; |
121 |
|
} |
122 |
|
} |
123 |
|
|
124 |
|
if (page == OpenedFilesCnt) |
125 |
|
{ |
126 |
|
/* no find, we must open it */ |
127 |
|
page = -1; |
128 |
|
} |
129 |
|
} |
130 |
|
|
131 |
|
if (page == -1) |
132 |
|
{ |
133 |
|
open_filename (result->path); |
134 |
|
page = OpenedFilesCnt - 1; |
135 |
|
} |
136 |
|
|
137 |
|
gtk_text_buffer_get_iter_at_line (FPROPS (page, Buffer), |
138 |
|
&iter, match->line - 1); |
139 |
|
next = iter; |
140 |
|
gtk_text_iter_forward_to_line_end (&next); |
141 |
|
|
142 |
|
gtk_text_buffer_place_cursor (FPROPS (page, Buffer), &iter); |
143 |
|
gtk_text_buffer_move_mark_by_name (FPROPS (page, Buffer), |
144 |
|
"selection_bound", &next); |
145 |
|
|
146 |
|
switch_to_page (page); |
147 |
|
|
148 |
|
/* hmm.. I have to use an idle loop because it won't scroll to mark |
149 |
|
or iter unless I do. |
150 |
|
It is probably because of all the crazy shit |
151 |
|
the syhi engine does */ |
152 |
|
g_idle_add ((GSourceFunc) scroll_idle_helper, |
153 |
|
GTK_TEXT_VIEW (FPROPS (page, Text))); |
154 |
|
} |
155 |
|
|
156 |
|
void search_result_activated (GtkTreeView *tree, GtkTreePath *path, |
157 |
|
GtkTreeViewColumn *column, gpointer data) |
158 |
|
{ |
159 |
|
gint *indices; |
160 |
|
|
161 |
|
if (gtk_tree_path_get_depth (path) == 1) |
162 |
|
{ |
163 |
|
return; |
164 |
|
} |
165 |
|
|
166 |
|
indices = gtk_tree_path_get_indices (path); |
167 |
|
|
168 |
|
go_to_search_result ( |
169 |
|
&g_array_index (SearchResults, struct file_results, indices[0]), |
170 |
|
indices[1]); |
171 |
|
} |
172 |
|
|
173 |
void ensure_search_display (void) |
void ensure_search_display (void) |
174 |
{ |
{ |
175 |
START_FCN |
START_FCN |
200 |
|
|
201 |
/* add the column */ |
/* add the column */ |
202 |
renderer = gtk_cell_renderer_text_new (); |
renderer = gtk_cell_renderer_text_new (); |
203 |
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (SearchTree), |
gtk_tree_view_insert_column_with_attributes ( |
204 |
|
GTK_TREE_VIEW (SearchTree), |
205 |
-1, "Match", |
-1, "Match", |
206 |
renderer, "text", |
renderer, "text", |
207 |
0, |
0, |
209 |
|
|
210 |
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (SearchTree), FALSE); |
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (SearchTree), FALSE); |
211 |
gtk_tree_view_set_search_column (GTK_TREE_VIEW (SearchTree), 0); |
gtk_tree_view_set_search_column (GTK_TREE_VIEW (SearchTree), 0); |
212 |
|
g_signal_connect (G_OBJECT (SearchTree), "row-activated", |
213 |
|
G_CALLBACK (search_result_activated), NULL); |
214 |
|
|
215 |
gtk_container_add (GTK_CONTAINER (MainVBox), SearchDisplay); |
gtk_container_add (GTK_CONTAINER (MainVBox), SearchDisplay); |
216 |
gtk_widget_show_all (SearchDisplay); |
gtk_widget_show_all (SearchDisplay); |
219 |
END_FCN |
END_FCN |
220 |
} |
} |
221 |
|
|
222 |
|
|
223 |
|
/* Adds all the data from the array of file_results to a GtkTreeStore |
224 |
|
and puts them in the SearchTree. Also, calculates the longest |
225 |
|
common base directory and stores that information on the store. */ |
226 |
void display_search_results (GArray *array) |
void display_search_results (GArray *array) |
227 |
{ |
{ |
228 |
gint i, j; |
gint i, j; |
229 |
GtkTreeStore *store; |
GtkTreeStore *store; |
230 |
|
gchar *base_dir; |
231 |
|
|
232 |
START_FCN |
START_FCN |
233 |
|
|
242 |
struct line_match *match; |
struct line_match *match; |
243 |
GPtrArray *results; |
GPtrArray *results; |
244 |
gchar *max_line; |
gchar *max_line; |
245 |
|
gchar *result_title; |
246 |
|
|
247 |
gtk_tree_store_append (store, &parent, NULL); |
gtk_tree_store_append (store, &parent, NULL); |
248 |
gtk_tree_store_set (store, &parent, 0, |
result_title = g_strconcat ( |
249 |
str_get_last_part ( |
g_array_index (array, struct file_results, i).buffer ? _("Document: ") : _("File: "), |
250 |
g_array_index (array, struct file_results, i).path, |
str_get_last_part ( |
251 |
PATH_SEP, TRUE), |
g_array_index (array, struct file_results, i).path, |
252 |
|
PATH_SEP, TRUE), |
253 |
|
NULL); |
254 |
|
gtk_tree_store_set (store, &parent, |
255 |
|
0, result_title, |
256 |
-1); |
-1); |
257 |
|
g_free (result_title); |
258 |
|
|
259 |
results = g_array_index (array, struct file_results, i).results; |
results = g_array_index (array, struct file_results, i).results; |
260 |
|
|
272 |
|
|
273 |
gtk_tree_store_append (store, &iter, &parent); |
gtk_tree_store_append (store, &iter, &parent); |
274 |
output = g_strdup_printf ("%*i %s", max_size, match->line, match->text); |
output = g_strdup_printf ("%*i %s", max_size, match->line, match->text); |
275 |
gtk_tree_store_set (store, &iter, 0, output, -1); |
gtk_tree_store_set (store, &iter, |
276 |
|
0, output, |
277 |
|
-1); |
278 |
g_free (output); |
g_free (output); |
279 |
} |
} |
280 |
} |
} |
281 |
|
|
282 |
gtk_tree_view_set_model (GTK_TREE_VIEW (SearchTree), GTK_TREE_MODEL (store)); |
gtk_tree_view_set_model (GTK_TREE_VIEW (SearchTree), GTK_TREE_MODEL (store)); |
283 |
g_object_unref (store); |
g_object_unref (store); |
284 |
|
gtk_tree_view_expand_all (GTK_TREE_VIEW (SearchTree)); |
285 |
|
|
286 |
gtk_widget_show_all (SearchTree); |
gtk_widget_show_all (SearchTree); |
287 |
|
|
288 |
END_FCN |
END_FCN |
582 |
if (widget) |
if (widget) |
583 |
g_signal_connect_swapped (G_OBJECT (widget), "destroy", |
g_signal_connect_swapped (G_OBJECT (widget), "destroy", |
584 |
G_CALLBACK (g_nullify_pointer), &rv.buffer); |
G_CALLBACK (g_nullify_pointer), &rv.buffer); |
585 |
rv.path = g_strdup (filename); |
|
586 |
|
if (!g_path_is_absolute (filename)) |
587 |
|
{ |
588 |
|
gchar *current_dir = g_get_current_dir (); |
589 |
|
|
590 |
|
rv.path = g_build_filename (current_dir, filename, NULL); |
591 |
|
g_free (current_dir); |
592 |
|
} |
593 |
|
else |
594 |
|
{ |
595 |
|
rv.path = g_strdup (filename); |
596 |
|
} |
597 |
rv.results = g_ptr_array_new (); |
rv.results = g_ptr_array_new (); |
598 |
|
|
599 |
while ((next = strchr (output, '\n'))) |
while ((next = strchr (output, '\n'))) |
685 |
gchar **expanded_files; |
gchar **expanded_files; |
686 |
gint i; |
gint i; |
687 |
struct file_results output; |
struct file_results output; |
688 |
GArray *array = g_array_new (FALSE, FALSE, sizeof (struct file_results)); |
|
689 |
|
if (SearchResults) |
690 |
|
{ |
691 |
|
for (i = 0; i < SearchResults->len; i++) |
692 |
|
{ |
693 |
|
g_free (g_array_index (SearchResults, struct file_results, i).path); |
694 |
|
g_ptr_array_free (g_array_index (SearchResults, struct file_results, i).results, TRUE); |
695 |
|
} |
696 |
|
|
697 |
|
g_array_free (SearchResults, FALSE); |
698 |
|
} |
699 |
|
SearchResults = g_array_new (FALSE, FALSE, sizeof (struct file_results)); |
700 |
|
|
701 |
widget = g_object_get_data (G_OBJECT (dialog), "text"); |
widget = g_object_get_data (G_OBJECT (dialog), "text"); |
702 |
|
|
726 |
|
|
727 |
output = run_grep_on_text (pattern, page, 0); |
output = run_grep_on_text (pattern, page, 0); |
728 |
if (output.results) |
if (output.results) |
729 |
g_array_append_val (array, output); |
g_array_append_val (SearchResults, output); |
730 |
|
|
731 |
break; |
break; |
732 |
case 1: |
case 1: |
734 |
{ |
{ |
735 |
output = run_grep_on_text (pattern, i, 0); |
output = run_grep_on_text (pattern, i, 0); |
736 |
if (output.results) |
if (output.results) |
737 |
g_array_append_val (array, output); |
g_array_append_val (SearchResults, output); |
738 |
} |
} |
739 |
|
|
740 |
break; |
break; |
747 |
{ |
{ |
748 |
output = run_grep_on_file (pattern, expanded_files[i], 0); |
output = run_grep_on_file (pattern, expanded_files[i], 0); |
749 |
if (output.results) |
if (output.results) |
750 |
g_array_append_val (array, output); |
g_array_append_val (SearchResults, output); |
751 |
} |
} |
752 |
|
|
753 |
g_strfreev (expanded_files); |
g_strfreev (expanded_files); |
755 |
break; |
break; |
756 |
} |
} |
757 |
|
|
758 |
display_search_results (array); |
display_search_results (SearchResults); |
|
|
|
|
for (i = 0; i < array->len; i++) |
|
|
{ |
|
|
g_free (g_array_index (array, struct file_results, i).path); |
|
|
g_ptr_array_free (g_array_index (array, struct file_results, i).results, TRUE); |
|
|
} |
|
|
|
|
|
g_array_free (array, FALSE); |
|
759 |
} |
} |
760 |
|
|
761 |
gtk_widget_destroy (GTK_WIDGET (dialog)); |
gtk_widget_destroy (GTK_WIDGET (dialog)); |
863 |
gtk_widget_show_all (SearchWindow); |
gtk_widget_show_all (SearchWindow); |
864 |
} |
} |
865 |
|
|
866 |
|
void show_cursor_on_screen (GtkTextView *view) |
867 |
|
{ |
868 |
|
GtkTextMark *mark; |
869 |
|
GtkTextBuffer *buffer; |
870 |
|
|
871 |
|
buffer = gtk_text_view_get_buffer (view); |
872 |
|
mark = gtk_text_buffer_get_mark (buffer, "insert"); |
873 |
|
|
874 |
|
gtk_text_view_scroll_to_mark (view, mark, 0, TRUE, 0, 0.5); |
875 |
|
} |
876 |
|
|
877 |
void show_on_screen (GtkTextView *Text, GtkTextIter start) |
void show_on_screen (GtkTextView *Text, GtkTextIter start) |
878 |
{ |
{ |
879 |
gtk_text_view_scroll_to_iter (Text, &start, 0, FALSE, 0, 0); |
gtk_text_view_scroll_to_iter (Text, &start, 0, TRUE, 0, 0.5); |
880 |
} |
} |
881 |
|
|
882 |
void set_line (GtkWidget *SpinButton) |
void set_line (GtkWidget *SpinButton) |