Updated Spanish translation
[anjuta-git-plugin.git] / plugins / search / search-replace.c
blob75a6413e1ac8cbf956422b9f901662ad2a693ef5
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 /*
4 ** search-replace.c: Generic Search and Replace
5 ** Author: Biswapesh Chattopadhyay
6 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <dirent.h>
19 #include <fnmatch.h>
20 #include <fcntl.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
24 #include <gnome.h>
25 #include <glade/glade.h>
27 #include <libanjuta/anjuta-utils.h>
28 #include <libanjuta/anjuta-plugin.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/interfaces/ianjuta-message-manager.h>
31 #include <libanjuta/interfaces/ianjuta-message-view.h>
32 #include <libanjuta/interfaces/ianjuta-editor.h>
33 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
34 #include <libanjuta/interfaces/ianjuta-markable.h>
35 #include <libanjuta/interfaces/ianjuta-indicable.h>
37 #include <libegg/menu/egg-entry-action.h>
39 #include "search-replace_backend.h"
40 #include "search-replace.h"
41 #include "search_preferences.h"
43 #include <libanjuta/interfaces/ianjuta-project-manager.h>
45 #define GLADE_FILE_SEARCH_REPLACE PACKAGE_DATA_DIR"/glade/anjuta-search.glade"
47 /* LibGlade's auto-signal-connect will connect to these signals.
48 * Do not declare them static.
50 gboolean
51 on_search_dialog_key_press_event(GtkWidget *widget, GdkEventKey *event,
52 gpointer user_data);
53 void on_search_match_whole_word_toggled (GtkToggleButton *togglebutton,
54 gpointer user_data);
55 void on_search_match_whole_line_toggled (GtkToggleButton *togglebutton,
56 gpointer user_data);
57 void on_search_match_word_start_toggled (GtkToggleButton *togglebutton,
58 gpointer user_data);
59 gboolean on_search_replace_delete_event(GtkWidget *window, GdkEvent *event,
60 gboolean user_data);
61 void on_replace_regex_toggled (GtkToggleButton *togglebutton, gpointer user_data);
62 void on_search_regex_toggled (GtkToggleButton *togglebutton, gpointer user_data);
63 void on_search_action_changed (GtkComboBox *combo, gpointer user_data);
64 void on_search_target_changed(GtkComboBox *combo, gpointer user_data);
65 void on_search_expression_changed(GtkComboBox *combo, gpointer user_data);
66 void on_actions_no_limit_clicked(GtkButton *button, gpointer user_data);
67 void on_search_button_close_clicked(GtkButton *button, gpointer user_data);
68 void on_search_button_close_clicked(GtkButton *button, gpointer user_data);
69 void on_search_button_help_clicked(GtkButton *button, gpointer user_data);
70 void on_search_button_next_clicked(GtkButton *button, gpointer user_data);
71 void on_search_button_jump_clicked(GtkButton *button, gpointer user_data);
72 void on_search_expression_activate (GtkEditable *edit, gpointer user_data);
73 void on_search_button_save_clicked(GtkButton *button, gpointer user_data);
74 void on_search_button_stop_clicked(GtkButton *button, gpointer user_data);
76 void on_search_direction_changed (GtkComboBox *combo, gpointer user_data);
77 void on_search_full_buffer_toggled (GtkToggleButton *togglebutton,
78 gpointer user_data);
79 void on_search_forward_toggled (GtkToggleButton *togglebutton,
80 gpointer user_data);
81 void on_search_backward_toggled (GtkToggleButton *togglebutton,
82 gpointer user_data);
83 void on_setting_basic_search_toggled (GtkToggleButton *togglebutton,
84 gpointer user_data);
86 /* GUI dropdown option strings */
87 AnjutaUtilStringMap search_direction_strings[] = {
88 {SD_FORWARD, "Forward"},
89 {SD_BACKWARD, "Backward"},
90 {SD_BEGINNING, "Full Buffer"},
91 {-1, NULL}
94 AnjutaUtilStringMap search_target_strings[] = {
95 {SR_BUFFER, "Current Buffer"},
96 {SR_SELECTION,"Current Selection"},
97 {SR_BLOCK, "Current Block"},
98 {SR_FUNCTION, "Current Function"},
99 {SR_OPEN_BUFFERS, "All Open Buffers"},
100 {SR_PROJECT, "All Project Files"},
101 /* {SR_VARIABLE, "Specify File List"},*/
102 {SR_FILES, "Specify File Patterns"},
103 {-1, NULL}
106 AnjutaUtilStringMap search_action_strings[] = {
107 {SA_SELECT, "Select the first match"},
108 {SA_BOOKMARK, "Bookmark all matched lines"},
109 {SA_HIGHLIGHT, "Mark all matched strings"},
110 {SA_FIND_PANE, "Show result in find pane"},
111 {SA_REPLACE, "Replace first match"},
112 {SA_REPLACEALL, "Replace all matches"},
113 {-1, NULL}
117 typedef struct _SearchReplaceGUI
119 GladeXML *xml;
120 GtkWidget *dialog;
121 gboolean showing;
122 } SearchReplaceGUI;
125 static GladeWidget glade_widgets[] = {
126 /* CLOSE_BUTTON */
127 {GE_BUTTON, "button.close", NULL, NULL},
128 /* STOP_BUTTON */
129 {GE_BUTTON, "button.stop", NULL, NULL},
130 /* SEARCH_BUTTON */
131 {GE_BUTTON, "button.next", NULL, NULL},
132 /* JUMP_BUTTON */
133 {GE_BUTTON, "button.jump", NULL, NULL},
134 /* SEARCH_NOTEBOOK */
135 {GE_NONE, "search.notebook", NULL, NULL},
136 /* SEARCH_EXPR_FRAME */
137 {GE_NONE, "frame.search.expression", NULL, NULL},
138 /* SEARCH_TARGET_FRAME */
139 {GE_NONE, "frame.search.target", NULL, NULL},
140 /* SEARCH_VAR_FRAME */
141 {GE_NONE, "frame.search.var", NULL, NULL},
142 /* FILE_FILTER_FRAME */
143 {GE_NONE, "frame.file.filter", NULL, NULL},
144 /* FRAME_SEARCH_BASIC */
145 {GE_NONE, "frame.search.basic", NULL, NULL},
146 /* LABEL_REPLACE */
147 {GE_NONE, "label.replace", NULL, NULL},
148 /* SEARCH_STRING */
149 {GE_COMBO_ENTRY, "search.string.combo", NULL, NULL},
150 /* SEARCH_VAR */
151 {GE_COMBO_ENTRY, "search.var.combo", NULL, NULL},
152 /* MATCH_FILES */
153 {GE_COMBO_ENTRY, "file.filter.match.combo", NULL, NULL},
154 /* UNMATCH_FILES */
155 {GE_COMBO_ENTRY, "file.filter.unmatch.combo", NULL, NULL},
156 /* MATCH_DIRS */
157 {GE_COMBO_ENTRY, "dir.filter.match.combo", NULL, NULL},
158 /* UNMATCH_DIRS */
159 {GE_COMBO_ENTRY, "dir.filter.unmatch.combo", NULL, NULL},
160 /* REPLACE_STRING */
161 {GE_COMBO_ENTRY, "replace.string.combo", NULL, NULL},
162 /* ACTIONS_MAX */
163 {GE_TEXT, "actions.max", NULL, NULL},
164 /* SETTING_PREF_ENTRY */
165 {GE_TEXT, "setting.pref.entry", NULL, NULL},
166 /* SEARCH_REGEX */
167 {GE_BOOLEAN, "search.regex", NULL, NULL},
168 /* GREEDY */
169 {GE_BOOLEAN, "search.greedy", NULL, NULL},
170 /* IGNORE_CASE */
171 {GE_BOOLEAN, "search.ignore.case", NULL, NULL},
172 /* WHOLE_WORD */
173 {GE_BOOLEAN, "search.match.whole.word", NULL, NULL},
174 /* WORD_START */
175 {GE_BOOLEAN, "search.match.word.start", NULL, NULL},
176 /* WHOLE_LINE */
177 {GE_BOOLEAN, "search.match.whole.line", NULL, NULL},
178 /* IGNORE_HIDDEN_FILES */
179 {GE_BOOLEAN, "ignore.hidden.files", NULL, NULL},
180 /* IGNORE_BINARY_FILES */
181 {GE_BOOLEAN, "ignore.binary.files", NULL, NULL},
182 /* IGNORE_HIDDEN_DIRS */
183 {GE_BOOLEAN, "ignore.hidden.dirs", NULL, NULL},
184 /* SEARCH_RECURSIVE */
185 {GE_BOOLEAN, "search.dir.recursive", NULL, NULL},
186 /* REPLACE_REGEX */
187 {GE_BOOLEAN, "replace.regex", NULL, NULL},
188 /* ACTIONS_NO_LIMIT */
189 {GE_BOOLEAN, "actions.no_limit", NULL, NULL},
190 /* SEARCH_FULL_BUFFER */
191 {GE_BOOLEAN, "search.full_buffer", NULL, NULL},
192 /* SEARCH_FORWARD */
193 {GE_BOOLEAN, "search.forward", NULL, NULL},
194 /* SEARCH_BACKWARD */
195 {GE_BOOLEAN, "search.backward", NULL, NULL},
196 /* SEARCH_BASIC */
197 {GE_BOOLEAN, "search.basic", NULL, NULL},
198 /* SEARCH_STRING_COMBO */
199 {GE_COMBO, "search.string.combo", NULL, NULL},
200 /* SEARCH_TARGET_COMBO */
201 {GE_COMBO, "search.target.combo", search_target_strings, NULL},
202 /* SEARCH_ACTION_COMBO */
203 {GE_COMBO, "search.action.combo", search_action_strings, NULL},
204 /* SEARCH_VAR_COMBO */
205 {GE_COMBO, "search.var.combo", NULL, NULL},
206 /* MATCH_FILES_COMBO */
207 {GE_COMBO, "file.filter.match.combo", NULL, NULL},
208 /* UNMATCH_FILES_COMBO */
209 {GE_COMBO, "file.filter.unmatch.combo", NULL, NULL},
210 /* MATCH_DIRS_COMBO */
211 {GE_COMBO, "dir.filter.match.combo", NULL, NULL},
212 /* UNMATCH_DIRS_COMBO */
213 {GE_COMBO, "dir.filter.unmatch.combo", NULL, NULL},
214 /* REPLACE_STRING_COMBO */
215 {GE_COMBO, "replace.string.combo", NULL, NULL},
216 /* SEARCH_DIRECTION_COMBO */
217 {GE_COMBO, "search.direction.combo", search_direction_strings, NULL},
218 /* SETTING_PREF_TREEVIEW */
219 {GE_NONE, "setting.pref.treeview", NULL, NULL},
220 {GE_NONE, NULL, NULL, NULL}
223 /***********************************************************/
225 static void
226 write_message_pane(IAnjutaMessageView* view, FileBuffer *fb, SearchEntry *se, MatchInfo *mi);
227 static gboolean on_message_clicked (GObject* object, gchar* message, gpointer data);
228 static void on_message_buffer_flush (IAnjutaMessageView *view, const gchar *one_line, gpointer data);
229 static void save_not_opened_files(FileBuffer *fb);
230 static gboolean replace_in_not_opened_files(FileBuffer *fb, MatchInfo *mi, gchar *repl_str);
231 static void search_set_action(SearchAction action);
232 static void search_set_target(SearchRangeType target);
233 static void search_set_direction(SearchDirection dir);
234 static void populate_value(GladeWidgetId id, gpointer val_ptr);
235 static void reset_flags(void);
236 static void reset_flags_and_search_button (void);
237 static void search_start_over (SearchDirection direction);
238 static void search_end_alert (gchar *string);
239 static void max_results_alert (void);
240 static void nb_results_alert (gint nb);
241 static void search_show_replace(gboolean hide);
242 static void modify_label_image_button(GladeWidgetId button_name, gchar *name, char *stock_image);
243 static void show_jump_button (gboolean show);
244 static gboolean create_dialog(void);
245 static void show_dialog(void);
246 static gboolean word_in_list(GList *list, gchar *word);
247 static GList* list_max_items(GList *list, guint nb_max);
248 static void search_update_combos (void);
249 static void replace_update_combos (void);
250 static void search_direction_changed(SearchDirection dir);
251 static void search_set_direction(SearchDirection dir);
252 static void search_set_toggle_direction(SearchDirection dir);
253 static void search_disconnect_set_toggle_connect(GladeWidgetId id,
254 GCallback function, gboolean active);
255 static void search_replace_next_previous(SearchDirection dir);
256 static void basic_search_toggled(void);
258 static SearchReplaceGUI *sg = NULL;
260 static SearchReplace *sr = NULL;
262 static gboolean flag_select = FALSE;
263 static gboolean interactive = FALSE;
264 static gboolean end_activity = FALSE;
267 /***********************************************************/
269 void
270 search_and_replace_init (IAnjutaDocumentManager *dm)
272 sr = create_search_replace_instance (dm);
275 void
276 search_and_replace (void)
278 GList *entries;
279 GList *tmp;
280 SearchEntry *se;
281 FileBuffer *fb;
282 static MatchInfo *mi;
283 Search *s;
284 gint offset;
285 static gint os=0;
286 gint nb_results;
287 static long start_sel = 0;
288 static long end_sel = 0;
289 static gchar *ch= NULL;
290 gboolean save_file = FALSE;
291 IAnjutaMessageManager* msgman;
292 IAnjutaMessageView* view = NULL;
293 gboolean backward;
295 g_return_if_fail(sr);
296 s = &(sr->search);
298 if (s->expr.search_str == NULL)
299 return;
301 end_activity = FALSE;
303 backward = s->range.direction == SD_BACKWARD?TRUE:FALSE;
305 entries = create_search_entries(s);
306 search_update_combos ();
307 if (s->action == SA_REPLACE || s->action == SA_REPLACEALL)
308 replace_update_combos ();
310 if (SA_FIND_PANE == s->action)
312 gchar* name = g_strconcat(_("Find: "), s->expr.search_str, NULL);
313 AnjutaShell* shell;
314 g_object_get(G_OBJECT(sr->docman), "shell", &shell, NULL);
315 msgman = anjuta_shell_get_interface(shell,
316 IAnjutaMessageManager, NULL);
317 g_return_if_fail(msgman != NULL);
319 view = ianjuta_message_manager_get_view_by_name(msgman, name, NULL);
320 if (view == NULL)
322 // FIXME: Put a nice icon here:
323 view = ianjuta_message_manager_add_view(msgman, name,
324 GTK_STOCK_FIND_AND_REPLACE, NULL);
325 g_return_if_fail(view != NULL);
326 g_signal_connect (G_OBJECT(view), "buffer_flushed",
327 G_CALLBACK (on_message_buffer_flush), NULL);
328 g_signal_connect (G_OBJECT(view), "message_clicked",
329 G_CALLBACK (on_message_clicked), NULL);
331 else
332 ianjuta_message_view_clear(view, NULL);
333 ianjuta_message_manager_set_current_view(msgman, view, NULL);
335 gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, TRUE);
336 nb_results = 0;
337 for (tmp = entries; tmp && (nb_results <= s->expr.actions_max);
338 tmp = g_list_next(tmp))
340 if (end_activity)
341 break;
342 while(gtk_events_pending())
343 gtk_main_iteration();
345 se = (SearchEntry *) tmp->data;
346 if (flag_select)
348 se->start_pos = start_sel;
349 se->end_pos = end_sel;
351 else
352 end_sel = se->end_pos;
353 if (SE_BUFFER == se->type)
354 fb = file_buffer_new_from_te(se->te);
355 else /* if (SE_FILE == se->type) */
356 fb = file_buffer_new_from_path(se->path, NULL, -1, 0);
358 if (fb)
360 gint found_line = 0;
361 fb->pos = se->start_pos;
362 offset = 0;
364 if (s->action == SA_BOOKMARK && IANJUTA_IS_MARKABLE (fb->te))
365 ianjuta_markable_delete_all_markers(IANJUTA_MARKABLE(fb->te),
366 IANJUTA_MARKABLE_LINEMARKER, NULL);
367 if (s->action == SA_HIGHLIGHT)
368 ianjuta_indicable_clear (IANJUTA_INDICABLE(fb->te), NULL);
370 while (interactive ||
371 NULL != (mi = get_next_match(fb, s->range.direction, &(s->expr))))
373 if ((s->range.direction == SD_BACKWARD) && (mi->pos < se->end_pos))
374 break;
375 if ((s->range.direction != SD_BACKWARD) && ((se->end_pos != -1) &&
376 (mi->pos+mi->len > se->end_pos)))
377 break;
378 nb_results++;
379 if (nb_results > sr->search.expr.actions_max)
380 break;
383 switch (s->action)
385 case SA_HIGHLIGHT: /* FIXME */
386 if (NULL == fb->te)
387 ianjuta_document_manager_goto_file_line_mark (sr->docman,
388 fb->path, mi->line + 1, TRUE, NULL);
389 ianjuta_indicable_set (IANJUTA_INDICABLE(fb->te),
390 mi->pos, mi->pos + mi->len,
391 IANJUTA_INDICABLE_IMPORTANT, NULL); //
392 break; //
393 case SA_BOOKMARK:
394 if (NULL == fb->te)
396 ianjuta_document_manager_goto_file_line_mark (sr->docman,
397 fb->path, mi->line + 1, TRUE, NULL);
398 fb->te = IANJUTA_EDITOR(
399 ianjuta_document_manager_get_current_document(sr->docman,
400 NULL));
403 else
404 ianjuta_editor_goto_line (fb->te, mi->line + 1, NULL);
406 if (found_line != mi->line + 1)
408 if (IANJUTA_IS_MARKABLE (fb->te))
410 ianjuta_markable_mark (IANJUTA_MARKABLE(fb->te),
411 mi->line + 1,
412 IANJUTA_MARKABLE_LINEMARKER,
413 NULL);
415 found_line = mi->line + 1;
417 break;
419 case SA_SELECT:
420 if (NULL == fb->te)
421 ianjuta_document_manager_goto_file_line (sr->docman,
422 fb->path, mi->line + 1, NULL);
423 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), mi->pos,
424 (mi->pos + mi->len), backward,
425 NULL);
426 break;
428 case SA_FIND_PANE:
429 write_message_pane(view, fb, se, mi);
430 break;
432 case SA_REPLACE:
433 if (!interactive)
435 if (NULL == fb->te)
437 ianjuta_document_manager_goto_file_line (sr->docman,
438 fb->path, mi->line + 1, NULL);
439 fb->te = IANJUTA_EDITOR(ianjuta_document_manager_get_current_document(sr->docman,
440 NULL));
442 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), mi->pos - offset,
443 mi->pos - offset + mi->len,
444 backward,
445 NULL);
446 interactive = TRUE;
447 os = offset;
448 modify_label_image_button(SEARCH_BUTTON, _("Replace"),
449 GTK_STOCK_FIND_AND_REPLACE);
450 show_jump_button(TRUE);
451 if (sr->replace.regex && sr->search.expr.regex)
453 if (ch)
455 g_free (ch);
457 ch = g_strdup(regex_backref(mi, fb));
459 break;
462 if (ch && sr->replace.regex && sr->search.expr.regex)
464 sr->replace.repl_str = g_strdup(ch);
465 g_free (ch);
468 if (fb->te == NULL)
470 ianjuta_document_manager_goto_file_line (sr->docman,
471 fb->path, mi->line + 1, NULL);
472 fb->te = IANJUTA_EDITOR(ianjuta_document_manager_get_current_document(sr->docman,
473 NULL));
475 else
477 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), mi->pos - os,
478 mi->pos + mi->len - os,
479 backward,
480 NULL);
481 ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te),
482 sr->replace.repl_str,
483 strlen(sr->replace.repl_str),
484 NULL);
486 if (se->direction != SD_BACKWARD)
487 offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
489 interactive = FALSE;
490 break;
491 case SA_REPLACEALL:
492 if ((sr->replace.regex) && (sr->search.expr.regex))
493 sr->replace.repl_str = g_strdup(regex_backref(mi, fb));
494 if (fb->te == NULL) /* NON OPENED FILES */
496 if (replace_in_not_opened_files(fb, mi, sr->replace.repl_str))
497 save_file = TRUE;
499 else
501 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), mi->pos - offset,
502 mi->pos + mi->len - offset,
503 backward,
504 NULL);
505 ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te),
506 sr->replace.repl_str,
507 strlen(sr->replace.repl_str),
508 NULL);
510 if (se->direction != SD_BACKWARD)
511 offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
512 break;
513 default:
514 g_warning ("Not implemented - File %s - Line %d\n", __FILE__, __LINE__);
515 break;
516 } // switch
518 if (se->direction != SD_BACKWARD)
519 start_sel = mi->pos + mi->len - offset;
520 else
521 start_sel = mi->pos - offset;
523 if (SA_REPLACE != s->action || (SA_REPLACE == s->action && !interactive))
524 match_info_free(mi);
526 if (SA_SELECT == s->action || ((SA_REPLACE == s->action ||
527 SA_REPLACEALL == s->action)&& interactive))
528 break;
529 } // while
531 } // if (fb)
533 if (save_file)
535 save_not_opened_files(fb);
536 save_file = FALSE;
539 file_buffer_free(fb);
540 if (se)
541 g_free(se);
542 if (SA_SELECT == s->action && nb_results > 0)
543 break;
544 } // for
545 gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, FALSE);
547 if (s->range.type == SR_BLOCK || s->range.type == SR_FUNCTION ||
548 s->range.type == SR_SELECTION)
549 flag_select = TRUE;
551 g_list_free(entries);
553 if (s->action == SA_FIND_PANE) {
554 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_INFO,
555 _("Search complete"), "", NULL);
558 if (nb_results == 0)
560 search_end_alert(sr->search.expr.search_str);
562 else if (nb_results > sr->search.expr.actions_max)
563 max_results_alert();
564 else if (s->action == SA_REPLACEALL)
565 nb_results_alert(nb_results);
567 if ((s->range.direction == SD_BEGINNING) &&
568 ((s->action == SA_SELECT) || (s->action == SA_REPLACE)) )
570 search_set_direction(SD_FORWARD);
573 return;
576 static void
577 write_message_pane(IAnjutaMessageView* view, FileBuffer *fb, SearchEntry *se,
578 MatchInfo *mi)
580 gchar *match_line;
581 char buf[BUFSIZ];
582 gchar *tmp;
584 match_line = file_match_line_from_pos(fb, mi->pos);
586 if (SE_BUFFER == se->type)
588 /* DEBUG_PRINT ("FBPATH %s\n", fb->path); */
589 const gchar* filename = ianjuta_document_get_filename(IANJUTA_DOCUMENT(se->te), NULL);
590 tmp = g_strrstr(fb->path, "/");
591 tmp = g_strndup(fb->path, tmp + 1 -(fb->path));
592 snprintf(buf, BUFSIZ, "%s%s:%ld:%s\n", tmp, filename,
593 mi->line + 1, match_line);
594 g_free(tmp);
596 else /* if (SE_FILE == se->type) */
598 snprintf(buf, BUFSIZ, "%s:%ld:%s\n", se->path, mi->line + 1, match_line);
600 g_free(match_line);
601 ianjuta_message_view_buffer_append (view, buf, NULL);
604 static void
605 on_message_buffer_flush (IAnjutaMessageView *view, const gchar *one_line,
606 gpointer data)
608 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL,
609 one_line, "", NULL);
612 static gboolean
613 on_message_clicked (GObject* object, gchar* message, gpointer data)
615 gchar *ptr, *ptr2;
616 gchar *path, *nline;
617 gint line;
619 if (!(ptr = g_strstr_len(message, strlen(message), ":")) )
620 return FALSE;
621 path = g_strndup(message, ptr - message);
623 ptr++;
624 if (!(ptr2 = g_strstr_len(ptr, strlen(ptr), ":")) )
625 return FALSE;
626 nline = g_strndup(ptr, ptr2 - ptr);
627 line = atoi(nline);
629 ianjuta_document_manager_goto_file_line (sr->docman, path, line, NULL);
630 g_free(path);
631 g_free(nline);
632 return FALSE;
635 static void
636 save_not_opened_files(FileBuffer *fb)
638 FILE *fp;
640 fp = fopen(fb->path, "wb");
641 if (!fp)
642 return;
643 fwrite(fb->buf, fb->len, 1, fp);
644 fclose(fp);
647 static gboolean
648 replace_in_not_opened_files(FileBuffer *fb, MatchInfo *mi, gchar *repl_str)
650 gint l;
651 g_return_val_if_fail (repl_str != NULL, FALSE);
653 if (strlen(repl_str) > mi->len)
655 l = fb->len - mi->pos;
656 fb->len = fb->len + strlen(repl_str) - mi->len;
657 if ( (fb->buf = g_realloc(fb->buf, fb->len)) == NULL )
658 return FALSE;
659 memmove((fb->buf) + mi->pos + strlen(repl_str) - mi->len, fb->buf + mi->pos,l);
661 if (strlen(repl_str) < mi->len)
663 l = fb->len - mi->pos - mi->len ;
664 memmove((fb->buf) + mi->pos + strlen(repl_str), fb->buf + mi->pos + mi->len,l);
665 fb->len = fb->len + strlen(repl_str) - mi->len;
666 if ( (fb->buf = g_realloc(fb->buf, fb->len)) == NULL)
667 return FALSE;
670 for (l=0; l < strlen(repl_str); l++)
671 (fb->buf)[(mi->pos)+l] = repl_str [l];
673 return TRUE;
677 static void
678 search_replace_next_previous(SearchDirection dir)
680 SearchDirection save_direction;
681 SearchAction save_action;
682 SearchRangeType save_type;
684 if (sr)
686 save_action = sr->search.action;
687 save_type = sr->search.range.type;
688 save_direction = sr->search.range.direction;
689 sr->search.range.direction = dir;
690 if (save_type == SR_OPEN_BUFFERS || save_type == SR_PROJECT ||
691 save_type == SR_FILES)
692 sr->search.range.direction = SR_BUFFER;
693 sr->search.action = SA_SELECT;
695 search_and_replace();
697 sr->search.action = save_action;
698 sr->search.range.type = save_type;
699 sr->search.range.direction = save_direction;
701 else
703 DEBUG_PRINT ("sr null\n");
707 void
708 search_replace_next(void)
710 search_replace_next_previous(SD_FORWARD);
713 void
714 search_replace_previous(void)
716 search_replace_next_previous(SD_BACKWARD);
719 /****************************************************************/
721 GladeWidget *
722 sr_get_gladewidget(GladeWidgetId id)
724 return &glade_widgets[id];
727 static void
728 search_set_popdown_strings (GtkComboBoxEntry *combo, GList* strings)
730 GtkListStore *store;
731 gboolean init;
733 init = gtk_combo_box_get_model (GTK_COMBO_BOX(combo)) == NULL;
735 store = gtk_list_store_new (1, G_TYPE_STRING);
736 for (; strings != NULL; strings = g_list_next(strings))
738 GtkTreeIter iter;
740 gtk_list_store_append (store, &iter);
741 gtk_list_store_set (store, &iter, 0, strings->data, -1);
743 gtk_combo_box_set_model (GTK_COMBO_BOX(combo), GTK_TREE_MODEL (store));
744 g_object_unref (store);
746 if (init) gtk_combo_box_entry_set_text_column (combo, 0);
749 static void
750 search_set_popdown_map (GtkComboBox *combo, AnjutaUtilStringMap *map)
752 GtkListStore *store;
753 gboolean init;
754 gint i;
756 init = gtk_combo_box_get_model (combo) == NULL;
758 store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
759 for (i = 0; map[i].type != -1; ++i)
761 GtkTreeIter iter;
763 gtk_list_store_append (store, &iter);
764 gtk_list_store_set (store, &iter, 0, map[i].name, 1, map[i].type, -1);
766 gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
767 g_object_unref (store);
768 gtk_combo_box_set_active (combo, 0);
770 if (init)
772 GtkCellRenderer *cell;
774 cell = gtk_cell_renderer_text_new ();
775 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
776 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
777 "text", 0, NULL);
781 static void
782 search_select_item(GtkComboBox* combo, gint item)
784 GtkTreeModel *model;
785 GtkTreeIter iter;
786 gboolean search;
788 model = gtk_combo_box_get_model(combo);
790 /* Find item corresponding to command */
791 for (search = gtk_tree_model_get_iter_first(model, &iter); search;
792 gtk_tree_model_iter_next (model, &iter))
794 gint id;
796 gtk_tree_model_get (model, &iter, 1, &id, -1);
798 if (id == item)
800 /* Find command */
801 gtk_combo_box_set_active_iter(combo, &iter);
802 break;
808 static void
809 search_set_combo(GladeWidgetId id_combo, gint command)
811 GtkComboBox *combo;
813 combo = GTK_COMBO_BOX(sr_get_gladewidget(id_combo)->widget);
814 search_select_item (combo, command);
817 static void
818 search_set_action(SearchAction action)
820 search_set_combo(SEARCH_ACTION_COMBO, action);
823 static void
824 search_set_target(SearchRangeType target)
826 search_set_combo(SEARCH_TARGET_COMBO, target);
829 static void
830 search_set_direction(SearchDirection dir)
832 search_set_combo(SEARCH_DIRECTION_COMBO, dir);
835 static gint
836 search_get_item_combo(GtkComboBox *combo)
838 gint item;
839 GtkTreeModel *model;
840 GtkTreeIter iter;
841 gboolean sel;
843 sel = gtk_combo_box_get_active_iter (combo, &iter);
844 model = gtk_combo_box_get_model (combo);
845 gtk_tree_model_get (model, &iter, 1, &item, -1);
847 return item;
850 static gint
851 search_get_item_combo_name(GladeWidgetId id)
853 GtkWidget *combo = sr_get_gladewidget(id)->widget;
854 return search_get_item_combo(GTK_COMBO_BOX(combo));
857 static void
858 search_direction_changed(SearchDirection dir)
860 SearchEntryType tgt;
861 SearchAction act;
863 tgt = search_get_item_combo_name(SEARCH_TARGET_COMBO);
864 if (dir != SD_BEGINNING)
866 if (tgt == SR_OPEN_BUFFERS || tgt == SR_PROJECT
867 || tgt == SR_FILES)
868 search_set_target(SR_BUFFER);
870 else
872 if (tgt == SR_BUFFER ||tgt == SR_SELECTION || tgt == SR_BLOCK ||
873 tgt == SR_FUNCTION)
874 search_set_target(SR_BUFFER);
875 else
877 act = search_get_item_combo_name(SEARCH_ACTION_COMBO);
878 if (act == SA_SELECT)
879 search_set_action(SA_BOOKMARK);
880 if (act == SA_REPLACE)
881 search_set_action(SA_REPLACEALL);
886 static void
887 populate_value(GladeWidgetId id, gpointer val_ptr)
889 GladeWidget *gw;
891 g_return_if_fail(id && val_ptr);
893 gw = sr_get_gladewidget(id);
894 g_return_if_fail(gw);
895 switch(gw->type)
897 case GE_COMBO_ENTRY:
898 case GE_TEXT:
899 if (*((char **) val_ptr))
900 g_free(* ((char **) val_ptr));
901 *((char **) val_ptr) = gtk_editable_get_chars(
902 GTK_EDITABLE(gw->widget), 0, -1);
903 break;
904 case GE_BOOLEAN:
905 * ((gboolean *) val_ptr) = gtk_toggle_button_get_active(
906 GTK_TOGGLE_BUTTON(gw->widget));
907 break;
908 case GE_COMBO:
909 g_return_if_fail (gw->extra != NULL);
911 *((int *) val_ptr) = search_get_item_combo (GTK_COMBO_BOX(gw->widget));
912 break;
913 default:
914 g_warning("Bad option %d to populate_value", gw->type);
915 break;
919 static void
920 reset_flags(void)
922 flag_select = FALSE;
923 interactive = FALSE;
926 static void
927 reset_flags_and_search_button(void)
929 reset_flags();
930 if (sr->search.action != SA_REPLACEALL)
931 modify_label_image_button(SEARCH_BUTTON, _("Search"), GTK_STOCK_FIND);
933 else
934 modify_label_image_button(SEARCH_BUTTON, _("Replace All"),
935 GTK_STOCK_FIND_AND_REPLACE);
937 show_jump_button(FALSE);
940 static void
941 search_start_over (SearchDirection direction)
943 IAnjutaDocument* doc = ianjuta_document_manager_get_current_document(sr->docman,
944 NULL);
945 IAnjutaEditor *te = NULL;
946 if (IANJUTA_IS_EDITOR(doc))
947 te = IANJUTA_EDITOR(doc);
948 long length;
950 if (te)
952 length = ianjuta_editor_get_length(te, NULL);;
954 if (direction != SD_BACKWARD)
955 /* search from doc start */
956 ianjuta_editor_goto_position(te, 0, NULL);
957 else
958 /* search from doc end */
959 ianjuta_editor_goto_position (te, length, NULL);
963 static void
964 search_end_alert(gchar *string)
966 GtkWidget *dialog;
968 if (sr->search.range.direction != SD_BEGINNING && !flag_select)
970 // Ask if user wants to wrap around the doc
971 // Dialog to be made HIG compliant.
972 dialog = gtk_message_dialog_new (GTK_WINDOW (sg->dialog),
973 GTK_DIALOG_DESTROY_WITH_PARENT,
974 GTK_MESSAGE_QUESTION,
975 GTK_BUTTONS_YES_NO,
976 _("The match \"%s\" was not found. Wrap search around the document?"),
977 string);
979 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
980 GTK_RESPONSE_YES);
981 g_signal_connect(G_OBJECT(dialog), "key-press-event",
982 G_CALLBACK(on_search_dialog_key_press_event), NULL);
983 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
985 search_start_over (sr->search.range.direction);
986 gtk_widget_destroy(dialog);
987 reset_flags();
988 search_and_replace ();
989 return;
992 else
994 dialog = gtk_message_dialog_new(GTK_WINDOW (sg->dialog),
995 GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
996 _("The match \"%s\" was not found."),
997 string);
998 g_signal_connect(G_OBJECT(dialog), "key-press-event",
999 G_CALLBACK(on_search_dialog_key_press_event), NULL);
1000 gtk_dialog_run(GTK_DIALOG(dialog));
1002 gtk_widget_destroy(dialog);
1003 reset_flags();
1006 static void
1007 max_results_alert(void)
1009 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW (sg->dialog),
1010 GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
1011 _("The maximum number of results has been reached."));
1012 g_signal_connect(G_OBJECT(dialog), "key-press-event",
1013 G_CALLBACK(on_search_dialog_key_press_event), NULL);
1014 gtk_dialog_run(GTK_DIALOG(dialog));
1015 gtk_widget_destroy(dialog);
1016 reset_flags();
1019 static void
1020 nb_results_alert(gint nb)
1022 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW (sg->dialog),
1023 GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
1024 _("%d matches have been replaced."), nb);
1025 g_signal_connect(G_OBJECT(dialog), "key-press-event",
1026 G_CALLBACK(on_search_dialog_key_press_event), NULL);
1027 gtk_dialog_run(GTK_DIALOG(dialog));
1028 gtk_widget_destroy(dialog);
1029 reset_flags();
1032 static void
1033 search_show_replace(gboolean hide)
1035 static GladeWidgetId hide_widgets[] = {
1036 REPLACE_REGEX, REPLACE_STRING_COMBO, LABEL_REPLACE
1038 int i;
1039 GtkWidget *widget;
1041 for (i=0; i < sizeof(hide_widgets)/sizeof(hide_widgets[0]); ++i)
1043 widget = sr_get_gladewidget(hide_widgets[i])->widget;
1044 if (NULL != widget)
1046 if (hide)
1047 gtk_widget_show(widget);
1048 else
1049 gtk_widget_hide(widget);
1054 static void
1055 modify_label_image_button(GladeWidgetId button_id, gchar *name, char *stock_image)
1057 GList *list, *l;
1058 GtkHBox *hbox;
1059 GtkWidget *alignment;
1060 GtkWidget *button = sr_get_gladewidget(button_id)->widget;
1062 list = gtk_container_get_children(GTK_CONTAINER (button));
1063 alignment = GTK_WIDGET(list->data);
1064 g_list_free(list);
1065 list = gtk_container_get_children(GTK_CONTAINER (alignment));
1066 hbox = GTK_HBOX(list->data);
1067 g_list_free(list);
1068 list = gtk_container_get_children(GTK_CONTAINER (hbox));
1069 for (l=list; l; l = g_list_next(l))
1071 if (GTK_IS_LABEL(l->data))
1072 gtk_label_set_text(GTK_LABEL(l->data), name);
1073 if (GTK_IS_IMAGE(l->data))
1074 gtk_image_set_from_stock(GTK_IMAGE(l->data), stock_image,
1075 GTK_ICON_SIZE_BUTTON);
1077 g_list_free(list);
1081 /********************************************************************/
1083 #define POP_LIST(str, var) populate_value(str, &s);\
1084 if (s) \
1086 sr->search.range.files.var = anjuta_util_glist_from_string(s);\
1089 /********************************************************************/
1091 void
1092 search_replace_populate(void)
1094 char *s = NULL;
1095 char *max = NULL;
1097 /* Now, populate the instance with values from the GUI */
1098 populate_value(SEARCH_STRING, &(sr->search.expr.search_str));
1099 populate_value(SEARCH_REGEX, &(sr->search.expr.regex));
1100 populate_value(GREEDY, &(sr->search.expr.greedy));
1101 populate_value(IGNORE_CASE, &(sr->search.expr.ignore_case));
1102 populate_value(WHOLE_WORD, &(sr->search.expr.whole_word));
1103 populate_value(WHOLE_LINE, &(sr->search.expr.whole_line));
1104 populate_value(WORD_START, &(sr->search.expr.word_start));
1105 populate_value(SEARCH_TARGET_COMBO, &(sr->search.range.type));
1106 populate_value(SEARCH_DIRECTION_COMBO, &(sr->search.range.direction));
1107 populate_value(ACTIONS_NO_LIMIT, &(sr->search.expr.no_limit));
1109 populate_value(SEARCH_BASIC, &(sr->search.basic_search));
1111 if (sr->search.expr.no_limit)
1112 sr->search.expr.actions_max = G_MAXINT;
1113 else
1115 populate_value(ACTIONS_MAX, &(max));
1116 sr->search.expr.actions_max = atoi(max);
1117 if (sr->search.expr.actions_max == 0)
1118 sr->search.expr.actions_max = 100;
1119 g_free(max);
1122 switch (sr->search.range.type)
1124 case SR_FUNCTION:
1125 case SR_BLOCK:
1126 if (flag_select)
1127 sr->search.range.type = SR_SELECTION;
1128 break;
1129 case SR_FILES:
1130 POP_LIST(MATCH_FILES, match_files);
1131 POP_LIST(UNMATCH_FILES, ignore_files);
1132 POP_LIST(MATCH_DIRS, match_dirs);
1133 POP_LIST(UNMATCH_DIRS, ignore_dirs);
1134 populate_value(IGNORE_HIDDEN_FILES, &(sr->search.range.files.ignore_hidden_files));
1135 populate_value(IGNORE_HIDDEN_DIRS, &(sr->search.range.files.ignore_hidden_dirs));
1136 populate_value(SEARCH_RECURSIVE, &(sr->search.range.files.recurse));
1137 break;
1138 default:
1139 break;
1141 populate_value(SEARCH_ACTION_COMBO, &(sr->search.action));
1142 switch (sr->search.action)
1144 case SA_REPLACE:
1145 case SA_REPLACEALL:
1146 populate_value(REPLACE_STRING, &(sr->replace.repl_str));
1147 populate_value(REPLACE_REGEX, &(sr->replace.regex));
1148 break;
1149 default:
1150 break;
1154 static void
1155 show_jump_button (gboolean show)
1157 GtkWidget *jump_button = sr_get_gladewidget(JUMP_BUTTON)->widget;
1158 if (show)
1159 gtk_widget_show(jump_button);
1160 else
1161 gtk_widget_hide(jump_button);
1165 static gboolean
1166 create_dialog(void)
1168 GladeWidget *w;
1169 GtkWidget *widget;
1170 int i;
1172 g_return_val_if_fail(NULL != sr, FALSE);
1173 if (NULL != sg) return TRUE;
1174 sg = g_new0(SearchReplaceGUI, 1);
1176 if (NULL == (sg->xml = glade_xml_new(GLADE_FILE_SEARCH_REPLACE,
1177 SEARCH_REPLACE_DIALOG, NULL)))
1179 anjuta_util_dialog_error(NULL, _("Unable to build user interface for Search And Replace"));
1180 g_free(sg);
1181 sg = NULL;
1182 return FALSE;
1184 sg->dialog = glade_xml_get_widget(sg->xml, SEARCH_REPLACE_DIALOG);
1185 /* gtk_window_set_transient_for (GTK_WINDOW(sg->dialog)
1186 , GTK_WINDOW(app->widgets.window)); */
1188 for (i=0; NULL != glade_widgets[i].name; ++i)
1190 w = &(glade_widgets[i]);
1191 w->widget = glade_xml_get_widget(sg->xml, w->name);
1192 if (GE_COMBO_ENTRY == w->type)
1194 /* Get child of GtkComboBoxEntry */
1195 w->widget = GTK_BIN(w->widget)->child;
1197 gtk_widget_ref(w->widget);
1198 if (GE_COMBO == w->type && NULL != w->extra)
1200 search_set_popdown_map(GTK_COMBO_BOX(w->widget), (AnjutaUtilStringMap *)w->extra);
1204 widget = sr_get_gladewidget(SEARCH_STRING_COMBO)->widget;
1205 g_signal_connect (widget, "changed", G_CALLBACK (on_search_expression_changed), NULL);
1206 widget = sr_get_gladewidget(SEARCH_STRING)->widget;
1207 g_signal_connect (widget, "activate", G_CALLBACK (on_search_expression_activate), NULL);
1208 widget = sr_get_gladewidget(REPLACE_STRING)->widget;
1209 g_signal_connect (widget, "activate", G_CALLBACK (on_search_expression_activate), NULL);
1210 widget = sr_get_gladewidget(SEARCH_ACTION_COMBO)->widget;
1211 g_signal_connect (widget, "changed", G_CALLBACK (on_search_action_changed), NULL);
1212 widget = sr_get_gladewidget(SEARCH_DIRECTION_COMBO)->widget;
1213 g_signal_connect (widget, "changed", G_CALLBACK (on_search_direction_changed), NULL);
1214 widget = sr_get_gladewidget(SEARCH_TARGET_COMBO)->widget;
1215 g_signal_connect (widget, "changed", G_CALLBACK (on_search_target_changed), NULL);
1218 search_preferences_initialize_setting_treeview(sg->dialog);
1219 search_preferences_init();
1221 glade_xml_signal_autoconnect(sg->xml);
1222 return TRUE;
1225 static void
1226 show_dialog(void)
1228 gtk_window_present (GTK_WINDOW (sg->dialog));
1229 sg->showing = TRUE;
1232 static gboolean
1233 word_in_list(GList *list, gchar *word)
1235 GList *l = list;
1237 while (l != NULL)
1239 if (strcmp(l->data, word) == 0)
1240 return TRUE;
1241 l = g_list_next(l);
1243 return FALSE;
1246 /* Remove last item of the list if > nb_max */
1248 static GList*
1249 list_max_items(GList *list, guint nb_max)
1251 GList *last;
1253 if (g_list_length(list) > nb_max)
1255 last = g_list_last(list);
1256 g_free(last->data);
1257 list = g_list_delete_link (list, last);
1259 return list;
1262 #define MAX_ITEMS_SEARCH_COMBO 16
1264 void
1265 search_toolbar_set_text(gchar *search_text)
1267 AnjutaUI *ui;
1268 GtkAction *action;
1270 AnjutaShell* shell;
1271 g_object_get(G_OBJECT(sr->docman), "shell", &shell, NULL);
1273 ui = anjuta_shell_get_ui (shell, NULL);
1274 action = anjuta_ui_get_action (ui, "ActionGroupNavigation",
1275 "ActionEditSearchEntry");
1276 egg_entry_action_set_text (EGG_ENTRY_ACTION(action), search_text);
1279 /* FIXME free GList sr->search.expr_history ????? */
1280 static void
1281 search_update_combos(void)
1283 GtkWidget *search_entry = NULL;
1284 gchar *search_word = NULL;
1285 IAnjutaDocument* doc = ianjuta_document_manager_get_current_document(sr->docman,
1286 NULL);
1287 IAnjutaEditor *te = NULL;
1288 if (IANJUTA_IS_EDITOR(doc))
1289 te = IANJUTA_EDITOR(doc);
1291 search_entry = sr_get_gladewidget(SEARCH_STRING)->widget;
1292 if (search_entry && te)
1294 search_word = g_strdup(gtk_entry_get_text(GTK_ENTRY (search_entry)));
1295 if (search_word && strlen(search_word) > 0)
1297 if (!word_in_list(sr->search.expr_history, search_word))
1299 GtkWidget *search_list =
1300 sr_get_gladewidget(SEARCH_STRING_COMBO)->widget;
1301 sr->search.expr_history = g_list_prepend(sr->search.expr_history,
1302 search_word);
1303 sr->search.expr_history = list_max_items(sr->search.expr_history,
1304 MAX_ITEMS_SEARCH_COMBO);
1305 search_set_popdown_strings(GTK_COMBO_BOX_ENTRY (search_list),
1306 sr->search.expr_history);
1308 //search_toolbar_set_text(search_word);
1309 // FIXME comboentry instead of entry
1310 //~ entry_set_text_n_select (app->widgets.toolbar.main_toolbar.find_entry,
1311 //~ search_word, FALSE);
1317 static void
1318 replace_update_combos(void)
1320 GtkWidget *replace_entry = NULL;
1321 gchar *replace_word = NULL;
1322 IAnjutaDocument* doc = ianjuta_document_manager_get_current_document(sr->docman,
1323 NULL);
1324 IAnjutaEditor *te = NULL;
1325 if (IANJUTA_IS_EDITOR(doc))
1326 te = IANJUTA_EDITOR(doc);
1328 replace_entry = sr_get_gladewidget(REPLACE_STRING)->widget;
1329 if (replace_entry && te)
1331 replace_word = g_strdup(gtk_entry_get_text(GTK_ENTRY (replace_entry)));
1332 if (replace_word && strlen(replace_word) > 0)
1334 if (!word_in_list(sr->replace.expr_history, replace_word))
1336 GtkWidget *replace_list =
1337 sr_get_gladewidget(REPLACE_STRING_COMBO)->widget;
1338 sr->replace.expr_history = g_list_prepend(sr->replace.expr_history,
1339 replace_word);
1340 sr->replace.expr_history = list_max_items(sr->replace.expr_history,
1341 MAX_ITEMS_SEARCH_COMBO);
1342 search_set_popdown_strings(GTK_COMBO_BOX_ENTRY (replace_list),
1343 sr->replace.expr_history);
1349 void
1350 search_update_dialog(void)
1352 GtkWidget *widget;
1353 Search *s;
1355 s = &(sr->search);
1356 widget = sr_get_gladewidget(SEARCH_REGEX)->widget;
1357 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.regex);
1358 widget = sr_get_gladewidget(GREEDY)->widget;
1359 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.greedy);
1360 widget = sr_get_gladewidget(IGNORE_CASE)->widget;
1361 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.ignore_case);
1362 widget = sr_get_gladewidget(WHOLE_WORD)->widget;
1363 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.whole_word);
1364 widget = sr_get_gladewidget(WHOLE_LINE)->widget;
1365 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.whole_line);
1366 widget = sr_get_gladewidget(WORD_START)->widget;
1367 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.word_start);
1369 widget = sr_get_gladewidget(ACTIONS_NO_LIMIT)->widget;
1370 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->expr.no_limit);
1371 widget = sr_get_gladewidget(ACTIONS_MAX)->widget;
1372 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), s->expr.actions_max);
1374 widget = sr_get_gladewidget(REPLACE_REGEX)->widget;
1375 gtk_widget_set_sensitive(widget, sr->search.expr.regex);
1377 widget = sr_get_gladewidget(SEARCH_BUTTON)->widget;
1378 gtk_widget_set_sensitive (widget, (s->expr.search_str != NULL) && (*s->expr.search_str != '\0'));
1380 widget = sr_get_gladewidget(SEARCH_STRING)->widget;
1381 if (s->expr.search_str)
1382 gtk_entry_set_text(GTK_ENTRY(widget), s->expr.search_str);
1384 widget = sr_get_gladewidget(SEARCH_DIRECTION_COMBO)->widget;
1385 search_select_item (GTK_COMBO_BOX(widget), s->range.direction);
1387 widget = sr_get_gladewidget(SEARCH_ACTION_COMBO)->widget;
1388 search_select_item (GTK_COMBO_BOX(widget), s->action);
1390 search_show_replace(s->action == SA_REPLACE || s->action == SA_REPLACEALL);
1392 widget = sr_get_gladewidget(SEARCH_TARGET_COMBO)->widget;
1393 search_select_item (GTK_COMBO_BOX(widget), s->range.type);
1395 widget = sr_get_gladewidget(SEARCH_BASIC)->widget;
1396 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), s->basic_search);
1398 widget = sr_get_gladewidget(STOP_BUTTON)->widget;
1399 gtk_widget_set_sensitive (widget, FALSE);
1401 basic_search_toggled();
1404 /* -------------- Callbacks --------------------- */
1406 gboolean
1407 on_search_replace_delete_event(GtkWidget *window, GdkEvent *event,
1408 gboolean user_data)
1410 if (sg->showing)
1412 gtk_widget_hide(sg->dialog);
1413 sg->showing = FALSE;
1415 return TRUE;
1418 gboolean
1419 on_search_dialog_key_press_event(GtkWidget *widget, GdkEventKey *event,
1420 gpointer user_data)
1422 if (event->keyval == GDK_Escape)
1424 if (user_data)
1426 /* Escape pressed in Find window */
1427 gtk_widget_hide(widget);
1428 sg->showing = FALSE;
1430 else
1432 /* Escape pressed in wrap yes/no window */
1433 gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_NO);
1435 return TRUE;
1437 else
1439 if ( (event->state & GDK_CONTROL_MASK) &&
1440 ((event->keyval & 0x5F) == GDK_G))
1442 if (event->state & GDK_SHIFT_MASK)
1443 search_replace_previous();
1444 else
1445 search_replace_next();
1447 return FALSE;
1451 static void
1452 search_disconnect_set_toggle_connect(GladeWidgetId id, GCallback function,
1453 gboolean active)
1455 GtkWidget *button;
1457 button = sr_get_gladewidget(id)->widget;
1458 g_signal_handlers_disconnect_by_func(G_OBJECT(button), function, NULL);
1459 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active);
1460 g_signal_connect(G_OBJECT(button), "toggled", function, NULL);
1464 void
1465 on_search_match_whole_word_toggled (GtkToggleButton *togglebutton,
1466 gpointer user_data)
1468 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)))
1470 search_disconnect_set_toggle_connect(WHOLE_LINE, (GCallback)
1471 on_search_match_whole_line_toggled, FALSE);
1472 search_disconnect_set_toggle_connect(WORD_START, (GCallback)
1473 on_search_match_word_start_toggled, FALSE);
1477 void
1478 on_search_match_whole_line_toggled (GtkToggleButton *togglebutton,
1479 gpointer user_data)
1481 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)))
1483 search_disconnect_set_toggle_connect(WHOLE_WORD, (GCallback)
1484 on_search_match_whole_word_toggled, FALSE);
1485 search_disconnect_set_toggle_connect(WORD_START, (GCallback)
1486 on_search_match_word_start_toggled, FALSE);
1490 void
1491 on_search_match_word_start_toggled (GtkToggleButton *togglebutton,
1492 gpointer user_data)
1494 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton)))
1496 search_disconnect_set_toggle_connect(WHOLE_WORD, (GCallback)
1497 on_search_match_whole_word_toggled, FALSE);
1498 search_disconnect_set_toggle_connect(WHOLE_LINE, (GCallback)
1499 on_search_match_whole_line_toggled, FALSE);
1504 static void
1505 search_make_sensitive(gboolean sensitive)
1507 static char *widgets[] = {
1508 SEARCH_EXPR_FRAME, SEARCH_TARGET_FRAME, CLOSE_BUTTON, SEARCH_BUTTON,
1509 JUMP_BUTTON
1511 gint i;
1512 GtkWidget *widget;
1514 for (i=0; i < sizeof(widgets)/sizeof(widgets[0]); ++i)
1516 widget = sr_get_gladewidget(widgets[i])->widget;
1517 if (NULL != widget)
1518 gtk_widget_set_sensitive(widget, sensitive);
1523 void
1524 on_search_regex_toggled (GtkToggleButton *togglebutton, gpointer user_data)
1526 static GladeWidgetId dependent_widgets[] = {
1527 GREEDY, IGNORE_CASE, WHOLE_WORD, WHOLE_LINE, WORD_START
1529 int i;
1530 GtkWidget *dircombo = sr_get_gladewidget(SEARCH_DIRECTION_COMBO)->widget;
1531 GtkWidget *repl_regex = sr_get_gladewidget(REPLACE_REGEX)->widget;
1532 GtkWidget *widget;
1533 gboolean state = gtk_toggle_button_get_active(togglebutton);
1535 if (state)
1537 search_set_direction(SD_FORWARD);
1540 gtk_widget_set_sensitive(dircombo, !state);
1541 gtk_widget_set_sensitive(repl_regex, state);
1543 for (i=0; i < sizeof(dependent_widgets)/sizeof(dependent_widgets[0]); ++i)
1545 widget = sr_get_gladewidget(dependent_widgets[i])->widget;
1546 if (NULL != widget)
1548 gtk_widget_set_sensitive(widget, !state);
1549 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
1554 static void
1555 search_set_toggle_direction(SearchDirection dir)
1557 switch (dir)
1559 case SD_FORWARD :
1560 search_disconnect_set_toggle_connect(SEARCH_FORWARD, (GCallback)
1561 on_search_forward_toggled, TRUE);
1562 break;
1563 case SD_BACKWARD :
1564 search_disconnect_set_toggle_connect(SEARCH_BACKWARD, (GCallback)
1565 on_search_backward_toggled, TRUE);
1566 break;
1567 case SD_BEGINNING :
1568 search_disconnect_set_toggle_connect(SEARCH_FULL_BUFFER, (GCallback)
1569 on_search_full_buffer_toggled, TRUE);
1570 break;
1574 void
1575 on_search_direction_changed (GtkComboBox *combo, gpointer user_data)
1577 SearchDirection dir;
1579 dir = search_get_item_combo(combo);
1580 search_set_toggle_direction(dir);
1581 search_direction_changed(dir);
1584 void
1585 on_search_action_changed (GtkComboBox *combo, gpointer user_data)
1587 SearchAction act;
1588 SearchRangeType rt;
1590 reset_flags();
1591 act = search_get_item_combo(combo);
1592 rt = search_get_item_combo_name(SEARCH_TARGET_COMBO);
1593 show_jump_button (FALSE);
1594 switch(act)
1596 case SA_SELECT:
1597 search_show_replace(FALSE);
1598 modify_label_image_button(SEARCH_BUTTON, _("Search"), GTK_STOCK_FIND);
1599 if (rt == SR_OPEN_BUFFERS || rt == SR_PROJECT ||
1600 rt == SR_FILES)
1601 search_set_target(SR_BUFFER);
1602 break;
1603 case SA_REPLACE:
1604 search_show_replace(TRUE);
1605 modify_label_image_button(SEARCH_BUTTON, _("Search"), GTK_STOCK_FIND);
1606 if (rt == SR_OPEN_BUFFERS || rt == SR_PROJECT ||
1607 rt == SR_FILES)
1608 search_set_target(SR_BUFFER);
1609 break;
1610 case SA_REPLACEALL:
1611 search_show_replace(TRUE);
1612 modify_label_image_button(SEARCH_BUTTON, _("Replace All"),
1613 GTK_STOCK_FIND_AND_REPLACE);
1614 break;
1615 default:
1616 search_show_replace(FALSE);
1617 modify_label_image_button(SEARCH_BUTTON, _("Search"), GTK_STOCK_FIND);
1618 break;
1622 void
1623 on_search_target_changed(GtkComboBox *combo, gpointer user_data)
1625 SearchRangeType tgt;
1626 SearchDirection dir;
1627 SearchAction act;
1628 GtkWidget *search_var_frame = sr_get_gladewidget(SEARCH_VAR_FRAME)->widget;
1629 GtkWidget *file_filter_frame = sr_get_gladewidget(FILE_FILTER_FRAME)->widget;
1631 tgt = search_get_item_combo(combo);
1632 switch(tgt)
1634 case SR_FILES:
1635 gtk_widget_hide(search_var_frame);
1636 gtk_widget_show(file_filter_frame);
1637 break;
1638 default:
1639 gtk_widget_hide(search_var_frame);
1640 gtk_widget_hide(file_filter_frame);
1641 break;
1644 dir = search_get_item_combo_name(SEARCH_DIRECTION_COMBO);
1646 if (tgt == SR_SELECTION || tgt == SR_BLOCK || tgt == SR_FUNCTION)
1649 if (dir == SD_BEGINNING)
1651 search_set_direction(SD_FORWARD);
1654 if (tgt == SR_OPEN_BUFFERS || tgt == SR_PROJECT ||
1655 tgt == SR_FILES)
1657 search_set_direction(SD_BEGINNING);
1659 act = search_get_item_combo_name(SEARCH_ACTION_COMBO);
1660 if (act != SA_REPLACE && act != SA_REPLACEALL)
1662 if (tgt == SR_OPEN_BUFFERS)
1663 search_set_action(SA_BOOKMARK);
1664 else
1665 search_set_action(SA_FIND_PANE);
1667 else
1669 search_set_action(SA_REPLACEALL);
1670 sr->search.action = SA_REPLACEALL;
1673 reset_flags_and_search_button();
1674 /* Resize dialog */
1675 gtk_window_resize(GTK_WINDOW(sg->dialog), 10, 10);
1678 void
1679 on_search_expression_changed(GtkComboBox *combo, gpointer user_data)
1681 GtkWidget *search_entry = sr_get_gladewidget(SEARCH_STRING)->widget;
1682 GtkWidget *widget = sr_get_gladewidget(SEARCH_BUTTON)->widget;
1683 gboolean sensitive;
1685 sensitive = *gtk_entry_get_text (GTK_ENTRY (search_entry)) == '\0' ? FALSE: TRUE;
1686 gtk_widget_set_sensitive (widget, sensitive);
1690 void
1691 on_actions_no_limit_clicked(GtkButton *button, gpointer user_data)
1693 GtkWidget *actions_max = sr_get_gladewidget(ACTIONS_MAX)->widget;
1695 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
1696 gtk_widget_set_sensitive (actions_max, FALSE);
1697 else
1698 gtk_widget_set_sensitive (actions_max, TRUE);
1701 void
1702 on_search_button_close_clicked(GtkButton *button, gpointer user_data)
1704 if (sg->showing)
1706 gtk_widget_hide(sg->dialog);
1707 sg->showing = FALSE;
1711 void
1712 on_search_button_stop_clicked(GtkButton *button, gpointer user_data)
1714 end_activity = TRUE;
1717 void
1718 on_search_button_next_clicked(GtkButton *button, gpointer user_data)
1720 clear_pcre();
1721 search_replace_populate();
1723 search_and_replace();
1726 void search_replace_find_usage(const gchar *symbol)
1728 gchar *project_root_uri = NULL;
1729 SearchReplace *old_sr = sr;
1730 AnjutaShell* shell;
1732 sr = g_new (SearchReplace, 1);
1734 sr->search.expr.search_str = g_strdup (symbol);
1735 sr->search.expr.regex = FALSE;
1736 sr->search.expr.greedy = FALSE;
1737 sr->search.expr.ignore_case = FALSE;
1738 sr->search.expr.whole_word = TRUE;
1739 sr->search.expr.whole_line = FALSE;
1740 sr->search.expr.word_start = FALSE;
1741 sr->search.expr.no_limit = TRUE;
1742 sr->search.expr.actions_max = G_MAXINT;
1743 sr->search.expr.re = NULL;
1745 g_object_get(G_OBJECT(sr->docman), "shell", &shell, NULL);
1747 anjuta_shell_get (shell,
1748 "project_root_uri", G_TYPE_STRING,
1749 &project_root_uri, NULL);
1751 sr->search.range.type =
1752 project_root_uri != NULL ? SR_PROJECT : SR_OPEN_BUFFERS;
1753 g_free (project_root_uri);
1755 sr->search.range.direction = SD_BEGINNING;
1757 sr->search.range.var = NULL;
1759 sr->search.range.files.top_dir = NULL;
1760 sr->search.range.files.match_files = NULL;
1761 sr->search.range.files.match_dirs = NULL;
1762 sr->search.range.files.ignore_files = NULL;
1763 sr->search.range.files.ignore_dirs = NULL;
1764 sr->search.range.files.ignore_hidden_files = TRUE;
1765 sr->search.range.files.ignore_hidden_dirs = TRUE;
1766 sr->search.range.files.recurse = TRUE;
1768 sr->search.action = SA_FIND_PANE;
1770 sr->search.expr_history = NULL;
1771 sr->search.incremental_pos = 0;
1772 sr->search.incremental_wrap = TRUE;
1774 create_dialog ();
1776 search_and_replace();
1777 g_free (sr);
1778 sr = old_sr;
1781 void
1782 on_search_button_jump_clicked(GtkButton *button, gpointer user_data)
1784 if (sr)
1785 interactive = FALSE;
1786 gtk_widget_hide(GTK_WIDGET(button));
1788 search_replace_populate();
1789 search_and_replace();
1792 void
1793 on_search_expression_activate (GtkEditable *edit, gpointer user_data)
1795 GtkWidget *combo;
1797 search_replace_populate();
1799 search_and_replace();
1800 combo = GTK_WIDGET(edit)->parent;
1801 reset_flags_and_search_button();
1805 void
1806 on_search_full_buffer_toggled (GtkToggleButton *togglebutton,
1807 gpointer user_data)
1809 if (gtk_toggle_button_get_active(togglebutton))
1811 search_set_direction(SD_BEGINNING);
1815 void
1816 on_search_forward_toggled (GtkToggleButton *togglebutton,
1817 gpointer user_data)
1819 if (gtk_toggle_button_get_active(togglebutton))
1821 search_set_direction(SD_FORWARD);
1825 void
1826 on_search_backward_toggled (GtkToggleButton *togglebutton,
1827 gpointer user_data)
1829 if (gtk_toggle_button_get_active(togglebutton))
1831 search_set_direction(SD_BACKWARD);
1835 void
1836 on_setting_basic_search_toggled (GtkToggleButton *togglebutton,
1837 gpointer user_data)
1839 SearchAction act;
1840 GtkWidget *frame_basic = sr_get_gladewidget(FRAME_SEARCH_BASIC)->widget;
1842 if (gtk_toggle_button_get_active(togglebutton))
1844 gtk_widget_show(frame_basic);
1845 search_set_target(SR_BUFFER);
1846 search_set_direction(SD_FORWARD);
1848 act = search_get_item_combo_name(SEARCH_ACTION_COMBO);
1849 if (act == SA_REPLACE || act == SA_REPLACEALL)
1850 search_set_action(SA_REPLACE);
1851 else
1852 search_set_action(SA_SELECT);
1854 else
1855 gtk_widget_hide(frame_basic);
1859 static void
1860 basic_search_toggled(void)
1862 GtkToggleButton *togglebutton;
1864 togglebutton = GTK_TOGGLE_BUTTON(sr_get_gladewidget(SEARCH_BASIC)->widget);
1866 on_setting_basic_search_toggled (togglebutton, NULL);
1869 /***********************************************************************/
1871 #define MAX_LENGTH_SEARCH 64
1873 void
1874 anjuta_search_replace_activate (gboolean replace, gboolean project)
1876 GtkWidget *search_entry = NULL;
1877 gchar *current_word = NULL;
1878 GtkWidget *notebook;
1879 IAnjutaDocument* doc = ianjuta_document_manager_get_current_document(sr->docman,
1880 NULL);
1881 IAnjutaEditor *te = NULL;
1883 create_dialog ();
1885 if (IANJUTA_IS_EDITOR(doc))
1886 te = IANJUTA_EDITOR(doc);
1888 search_update_dialog();
1890 search_replace_populate();
1892 reset_flags_and_search_button();
1894 /* Set properties */
1895 search_entry = sr_get_gladewidget(SEARCH_STRING)->widget;
1896 if (te && search_entry && sr->search.range.type != SR_SELECTION)
1898 current_word = ianjuta_editor_get_current_word(te, NULL);
1899 if (current_word && strlen(current_word) > 0 )
1901 if (strlen(current_word) > MAX_LENGTH_SEARCH)
1902 current_word[MAX_LENGTH_SEARCH] = '\0';
1903 gtk_entry_set_text(GTK_ENTRY (search_entry), current_word);
1904 g_free(current_word);
1908 if (replace)
1910 if ( !(sr->search.action == SA_REPLACE ||
1911 sr->search.action == SA_REPLACEALL))
1913 search_set_action(SA_REPLACE);
1914 sr->search.action = SA_REPLACE;
1915 search_show_replace(TRUE);
1918 else
1920 if (sr->search.action == SA_REPLACE || sr->search.action == SA_REPLACEALL)
1922 search_set_action(SA_SELECT);
1923 sr->search.action = SA_SELECT;
1924 search_show_replace(FALSE);
1927 if (sr->search.action != SA_REPLACEALL)
1928 modify_label_image_button(SEARCH_BUTTON, _("Search"), GTK_STOCK_FIND);
1930 if (project)
1932 search_set_target(SR_PROJECT);
1933 if (!replace)
1935 search_set_action (SA_FIND_PANE);
1936 search_set_direction (SD_BEGINNING);
1939 show_jump_button(FALSE);
1941 notebook = sr_get_gladewidget(SEARCH_NOTEBOOK)->widget;
1942 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
1944 /* Show the dialog */
1945 gtk_widget_grab_focus (search_entry);
1946 show_dialog();