1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 ** search-replace.c: Generic Search and Replace
5 ** Author: Biswapesh Chattopadhyay
21 #include <sys/types.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.
51 on_search_dialog_key_press_event(GtkWidget
*widget
, GdkEventKey
*event
,
53 void on_search_match_whole_word_toggled (GtkToggleButton
*togglebutton
,
55 void on_search_match_whole_line_toggled (GtkToggleButton
*togglebutton
,
57 void on_search_match_word_start_toggled (GtkToggleButton
*togglebutton
,
59 gboolean
on_search_replace_delete_event(GtkWidget
*window
, GdkEvent
*event
,
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
,
79 void on_search_forward_toggled (GtkToggleButton
*togglebutton
,
81 void on_search_backward_toggled (GtkToggleButton
*togglebutton
,
83 void on_setting_basic_search_toggled (GtkToggleButton
*togglebutton
,
86 /* GUI dropdown option strings */
87 AnjutaUtilStringMap search_direction_strings
[] = {
88 {SD_FORWARD
, "Forward"},
89 {SD_BACKWARD
, "Backward"},
90 {SD_BEGINNING
, "Full Buffer"},
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"},
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"},
117 typedef struct _SearchReplaceGUI
125 static GladeWidget glade_widgets
[] = {
127 {GE_BUTTON
, "button.close", NULL
, NULL
},
129 {GE_BUTTON
, "button.stop", NULL
, NULL
},
131 {GE_BUTTON
, "button.next", NULL
, NULL
},
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
},
147 {GE_NONE
, "label.replace", NULL
, NULL
},
149 {GE_COMBO_ENTRY
, "search.string.combo", NULL
, NULL
},
151 {GE_COMBO_ENTRY
, "search.var.combo", NULL
, NULL
},
153 {GE_COMBO_ENTRY
, "file.filter.match.combo", NULL
, NULL
},
155 {GE_COMBO_ENTRY
, "file.filter.unmatch.combo", NULL
, NULL
},
157 {GE_COMBO_ENTRY
, "dir.filter.match.combo", NULL
, NULL
},
159 {GE_COMBO_ENTRY
, "dir.filter.unmatch.combo", NULL
, NULL
},
161 {GE_COMBO_ENTRY
, "replace.string.combo", NULL
, NULL
},
163 {GE_TEXT
, "actions.max", NULL
, NULL
},
164 /* SETTING_PREF_ENTRY */
165 {GE_TEXT
, "setting.pref.entry", NULL
, NULL
},
167 {GE_BOOLEAN
, "search.regex", NULL
, NULL
},
169 {GE_BOOLEAN
, "search.greedy", NULL
, NULL
},
171 {GE_BOOLEAN
, "search.ignore.case", NULL
, NULL
},
173 {GE_BOOLEAN
, "search.match.whole.word", NULL
, NULL
},
175 {GE_BOOLEAN
, "search.match.word.start", NULL
, NULL
},
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
},
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
},
193 {GE_BOOLEAN
, "search.forward", NULL
, NULL
},
194 /* SEARCH_BACKWARD */
195 {GE_BOOLEAN
, "search.backward", NULL
, NULL
},
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 /***********************************************************/
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 /***********************************************************/
270 search_and_replace_init (IAnjutaDocumentManager
*dm
)
272 sr
= create_search_replace_instance (dm
);
276 search_and_replace (void)
282 static MatchInfo
*mi
;
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
;
295 g_return_if_fail(sr
);
298 if (s
->expr
.search_str
== NULL
)
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
);
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
);
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
);
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
);
337 for (tmp
= entries
; tmp
&& (nb_results
<= s
->expr
.actions_max
);
338 tmp
= g_list_next(tmp
))
342 while(gtk_events_pending())
343 gtk_main_iteration();
345 se
= (SearchEntry
*) tmp
->data
;
348 se
->start_pos
= start_sel
;
349 se
->end_pos
= end_sel
;
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);
361 fb
->pos
= se
->start_pos
;
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
))
375 if ((s
->range
.direction
!= SD_BACKWARD
) && ((se
->end_pos
!= -1) &&
376 (mi
->pos
+mi
->len
> se
->end_pos
)))
379 if (nb_results
> sr
->search
.expr
.actions_max
)
385 case SA_HIGHLIGHT
: /* FIXME */
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
); //
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
,
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
),
412 IANJUTA_MARKABLE_LINEMARKER
,
415 found_line
= mi
->line
+ 1;
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
,
429 write_message_pane(view
, fb
, se
, mi
);
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
,
442 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb
->te
), mi
->pos
- offset
,
443 mi
->pos
- offset
+ mi
->len
,
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
)
457 ch
= g_strdup(regex_backref(mi
, fb
));
462 if (ch
&& sr
->replace
.regex
&& sr
->search
.expr
.regex
)
464 sr
->replace
.repl_str
= g_strdup(ch
);
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
,
477 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb
->te
), mi
->pos
- os
,
478 mi
->pos
+ mi
->len
- os
,
481 ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb
->te
),
482 sr
->replace
.repl_str
,
483 strlen(sr
->replace
.repl_str
),
486 if (se
->direction
!= SD_BACKWARD
)
487 offset
+= mi
->len
- (sr
->replace
.repl_str
?strlen(sr
->replace
.repl_str
):0);
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
))
501 ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb
->te
), mi
->pos
- offset
,
502 mi
->pos
+ mi
->len
- offset
,
505 ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb
->te
),
506 sr
->replace
.repl_str
,
507 strlen(sr
->replace
.repl_str
),
510 if (se
->direction
!= SD_BACKWARD
)
511 offset
+= mi
->len
- (sr
->replace
.repl_str
?strlen(sr
->replace
.repl_str
):0);
514 g_warning ("Not implemented - File %s - Line %d\n", __FILE__
, __LINE__
);
518 if (se
->direction
!= SD_BACKWARD
)
519 start_sel
= mi
->pos
+ mi
->len
- offset
;
521 start_sel
= mi
->pos
- offset
;
523 if (SA_REPLACE
!= s
->action
|| (SA_REPLACE
== s
->action
&& !interactive
))
526 if (SA_SELECT
== s
->action
|| ((SA_REPLACE
== s
->action
||
527 SA_REPLACEALL
== s
->action
)&& interactive
))
535 save_not_opened_files(fb
);
539 file_buffer_free(fb
);
542 if (SA_SELECT
== s
->action
&& nb_results
> 0)
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
)
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
);
560 search_end_alert(sr
->search
.expr
.search_str
);
562 else if (nb_results
> sr
->search
.expr
.actions_max
)
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
);
577 write_message_pane(IAnjutaMessageView
* view
, FileBuffer
*fb
, SearchEntry
*se
,
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
);
596 else /* if (SE_FILE == se->type) */
598 snprintf(buf
, BUFSIZ
, "%s:%ld:%s\n", se
->path
, mi
->line
+ 1, match_line
);
601 ianjuta_message_view_buffer_append (view
, buf
, NULL
);
605 on_message_buffer_flush (IAnjutaMessageView
*view
, const gchar
*one_line
,
608 ianjuta_message_view_append (view
, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL
,
613 on_message_clicked (GObject
* object
, gchar
* message
, gpointer data
)
619 if (!(ptr
= g_strstr_len(message
, strlen(message
), ":")) )
621 path
= g_strndup(message
, ptr
- message
);
624 if (!(ptr2
= g_strstr_len(ptr
, strlen(ptr
), ":")) )
626 nline
= g_strndup(ptr
, ptr2
- ptr
);
629 ianjuta_document_manager_goto_file_line (sr
->docman
, path
, line
, NULL
);
636 save_not_opened_files(FileBuffer
*fb
)
640 fp
= fopen(fb
->path
, "wb");
643 fwrite(fb
->buf
, fb
->len
, 1, fp
);
648 replace_in_not_opened_files(FileBuffer
*fb
, MatchInfo
*mi
, gchar
*repl_str
)
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
)
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
)
670 for (l
=0; l
< strlen(repl_str
); l
++)
671 (fb
->buf
)[(mi
->pos
)+l
] = repl_str
[l
];
678 search_replace_next_previous(SearchDirection dir
)
680 SearchDirection save_direction
;
681 SearchAction save_action
;
682 SearchRangeType save_type
;
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
;
703 DEBUG_PRINT ("sr null\n");
708 search_replace_next(void)
710 search_replace_next_previous(SD_FORWARD
);
714 search_replace_previous(void)
716 search_replace_next_previous(SD_BACKWARD
);
719 /****************************************************************/
722 sr_get_gladewidget(GladeWidgetId id
)
724 return &glade_widgets
[id
];
728 search_set_popdown_strings (GtkComboBoxEntry
*combo
, GList
* strings
)
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
))
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);
750 search_set_popdown_map (GtkComboBox
*combo
, AnjutaUtilStringMap
*map
)
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
)
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);
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
,
782 search_select_item(GtkComboBox
* combo
, gint item
)
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
))
796 gtk_tree_model_get (model
, &iter
, 1, &id
, -1);
801 gtk_combo_box_set_active_iter(combo
, &iter
);
809 search_set_combo(GladeWidgetId id_combo
, gint command
)
813 combo
= GTK_COMBO_BOX(sr_get_gladewidget(id_combo
)->widget
);
814 search_select_item (combo
, command
);
818 search_set_action(SearchAction action
)
820 search_set_combo(SEARCH_ACTION_COMBO
, action
);
824 search_set_target(SearchRangeType target
)
826 search_set_combo(SEARCH_TARGET_COMBO
, target
);
830 search_set_direction(SearchDirection dir
)
832 search_set_combo(SEARCH_DIRECTION_COMBO
, dir
);
836 search_get_item_combo(GtkComboBox
*combo
)
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);
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
));
858 search_direction_changed(SearchDirection dir
)
863 tgt
= search_get_item_combo_name(SEARCH_TARGET_COMBO
);
864 if (dir
!= SD_BEGINNING
)
866 if (tgt
== SR_OPEN_BUFFERS
|| tgt
== SR_PROJECT
868 search_set_target(SR_BUFFER
);
872 if (tgt
== SR_BUFFER
||tgt
== SR_SELECTION
|| tgt
== SR_BLOCK
||
874 search_set_target(SR_BUFFER
);
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
);
887 populate_value(GladeWidgetId id
, gpointer val_ptr
)
891 g_return_if_fail(id
&& val_ptr
);
893 gw
= sr_get_gladewidget(id
);
894 g_return_if_fail(gw
);
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);
905 * ((gboolean
*) val_ptr
) = gtk_toggle_button_get_active(
906 GTK_TOGGLE_BUTTON(gw
->widget
));
909 g_return_if_fail (gw
->extra
!= NULL
);
911 *((int *) val_ptr
) = search_get_item_combo (GTK_COMBO_BOX(gw
->widget
));
914 g_warning("Bad option %d to populate_value", gw
->type
);
927 reset_flags_and_search_button(void)
930 if (sr
->search
.action
!= SA_REPLACEALL
)
931 modify_label_image_button(SEARCH_BUTTON
, _("Search"), GTK_STOCK_FIND
);
934 modify_label_image_button(SEARCH_BUTTON
, _("Replace All"),
935 GTK_STOCK_FIND_AND_REPLACE
);
937 show_jump_button(FALSE
);
941 search_start_over (SearchDirection direction
)
943 IAnjutaDocument
* doc
= ianjuta_document_manager_get_current_document(sr
->docman
,
945 IAnjutaEditor
*te
= NULL
;
946 if (IANJUTA_IS_EDITOR(doc
))
947 te
= IANJUTA_EDITOR(doc
);
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
);
958 /* search from doc end */
959 ianjuta_editor_goto_position (te
, length
, NULL
);
964 search_end_alert(gchar
*string
)
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
,
976 _("The match \"%s\" was not found. Wrap search around the document?"),
979 gtk_dialog_set_default_response (GTK_DIALOG (dialog
),
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
);
988 search_and_replace ();
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."),
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
);
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
);
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
);
1033 search_show_replace(gboolean hide
)
1035 static GladeWidgetId hide_widgets
[] = {
1036 REPLACE_REGEX
, REPLACE_STRING_COMBO
, LABEL_REPLACE
1041 for (i
=0; i
< sizeof(hide_widgets
)/sizeof(hide_widgets
[0]); ++i
)
1043 widget
= sr_get_gladewidget(hide_widgets
[i
])->widget
;
1047 gtk_widget_show(widget
);
1049 gtk_widget_hide(widget
);
1055 modify_label_image_button(GladeWidgetId button_id
, gchar
*name
, char *stock_image
)
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
);
1065 list
= gtk_container_get_children(GTK_CONTAINER (alignment
));
1066 hbox
= GTK_HBOX(list
->data
);
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
);
1081 /********************************************************************/
1083 #define POP_LIST(str, var) populate_value(str, &s);\
1086 sr->search.range.files.var = anjuta_util_glist_from_string(s);\
1089 /********************************************************************/
1092 search_replace_populate(void)
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
;
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;
1122 switch (sr
->search
.range
.type
)
1127 sr
->search
.range
.type
= SR_SELECTION
;
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
));
1141 populate_value(SEARCH_ACTION_COMBO
, &(sr
->search
.action
));
1142 switch (sr
->search
.action
)
1146 populate_value(REPLACE_STRING
, &(sr
->replace
.repl_str
));
1147 populate_value(REPLACE_REGEX
, &(sr
->replace
.regex
));
1155 show_jump_button (gboolean show
)
1157 GtkWidget
*jump_button
= sr_get_gladewidget(JUMP_BUTTON
)->widget
;
1159 gtk_widget_show(jump_button
);
1161 gtk_widget_hide(jump_button
);
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"));
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
);
1228 gtk_window_present (GTK_WINDOW (sg
->dialog
));
1233 word_in_list(GList
*list
, gchar
*word
)
1239 if (strcmp(l
->data
, word
) == 0)
1246 /* Remove last item of the list if > nb_max */
1249 list_max_items(GList
*list
, guint nb_max
)
1253 if (g_list_length(list
) > nb_max
)
1255 last
= g_list_last(list
);
1257 list
= g_list_delete_link (list
, last
);
1262 #define MAX_ITEMS_SEARCH_COMBO 16
1265 search_toolbar_set_text(gchar
*search_text
)
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 ????? */
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
,
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
,
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);
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
,
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
,
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
);
1350 search_update_dialog(void)
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 --------------------- */
1407 on_search_replace_delete_event(GtkWidget
*window
, GdkEvent
*event
,
1412 gtk_widget_hide(sg
->dialog
);
1413 sg
->showing
= FALSE
;
1419 on_search_dialog_key_press_event(GtkWidget
*widget
, GdkEventKey
*event
,
1422 if (event
->keyval
== GDK_Escape
)
1426 /* Escape pressed in Find window */
1427 gtk_widget_hide(widget
);
1428 sg
->showing
= FALSE
;
1432 /* Escape pressed in wrap yes/no window */
1433 gtk_dialog_response (GTK_DIALOG (widget
), GTK_RESPONSE_NO
);
1439 if ( (event
->state
& GDK_CONTROL_MASK
) &&
1440 ((event
->keyval
& 0x5F) == GDK_G
))
1442 if (event
->state
& GDK_SHIFT_MASK
)
1443 search_replace_previous();
1445 search_replace_next();
1452 search_disconnect_set_toggle_connect(GladeWidgetId id
, GCallback function
,
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
);
1465 on_search_match_whole_word_toggled (GtkToggleButton
*togglebutton
,
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
);
1478 on_search_match_whole_line_toggled (GtkToggleButton
*togglebutton
,
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
);
1491 on_search_match_word_start_toggled (GtkToggleButton
*togglebutton
,
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
);
1505 search_make_sensitive(gboolean sensitive)
1507 static char *widgets[] = {
1508 SEARCH_EXPR_FRAME, SEARCH_TARGET_FRAME, CLOSE_BUTTON, SEARCH_BUTTON,
1514 for (i=0; i < sizeof(widgets)/sizeof(widgets[0]); ++i)
1516 widget = sr_get_gladewidget(widgets[i])->widget;
1518 gtk_widget_set_sensitive(widget, sensitive);
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
1530 GtkWidget
*dircombo
= sr_get_gladewidget(SEARCH_DIRECTION_COMBO
)->widget
;
1531 GtkWidget
*repl_regex
= sr_get_gladewidget(REPLACE_REGEX
)->widget
;
1533 gboolean state
= gtk_toggle_button_get_active(togglebutton
);
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
;
1548 gtk_widget_set_sensitive(widget
, !state
);
1549 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget
), FALSE
);
1555 search_set_toggle_direction(SearchDirection dir
)
1560 search_disconnect_set_toggle_connect(SEARCH_FORWARD
, (GCallback
)
1561 on_search_forward_toggled
, TRUE
);
1564 search_disconnect_set_toggle_connect(SEARCH_BACKWARD
, (GCallback
)
1565 on_search_backward_toggled
, TRUE
);
1568 search_disconnect_set_toggle_connect(SEARCH_FULL_BUFFER
, (GCallback
)
1569 on_search_full_buffer_toggled
, TRUE
);
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
);
1585 on_search_action_changed (GtkComboBox
*combo
, gpointer user_data
)
1591 act
= search_get_item_combo(combo
);
1592 rt
= search_get_item_combo_name(SEARCH_TARGET_COMBO
);
1593 show_jump_button (FALSE
);
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
||
1601 search_set_target(SR_BUFFER
);
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
||
1608 search_set_target(SR_BUFFER
);
1611 search_show_replace(TRUE
);
1612 modify_label_image_button(SEARCH_BUTTON
, _("Replace All"),
1613 GTK_STOCK_FIND_AND_REPLACE
);
1616 search_show_replace(FALSE
);
1617 modify_label_image_button(SEARCH_BUTTON
, _("Search"), GTK_STOCK_FIND
);
1623 on_search_target_changed(GtkComboBox
*combo
, gpointer user_data
)
1625 SearchRangeType tgt
;
1626 SearchDirection dir
;
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
);
1635 gtk_widget_hide(search_var_frame
);
1636 gtk_widget_show(file_filter_frame
);
1639 gtk_widget_hide(search_var_frame
);
1640 gtk_widget_hide(file_filter_frame
);
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
||
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
);
1665 search_set_action(SA_FIND_PANE
);
1669 search_set_action(SA_REPLACEALL
);
1670 sr
->search
.action
= SA_REPLACEALL
;
1673 reset_flags_and_search_button();
1675 gtk_window_resize(GTK_WINDOW(sg
->dialog
), 10, 10);
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
;
1685 sensitive
= *gtk_entry_get_text (GTK_ENTRY (search_entry
)) == '\0' ? FALSE
: TRUE
;
1686 gtk_widget_set_sensitive (widget
, sensitive
);
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
);
1698 gtk_widget_set_sensitive (actions_max
, TRUE
);
1702 on_search_button_close_clicked(GtkButton
*button
, gpointer user_data
)
1706 gtk_widget_hide(sg
->dialog
);
1707 sg
->showing
= FALSE
;
1712 on_search_button_stop_clicked(GtkButton
*button
, gpointer user_data
)
1714 end_activity
= TRUE
;
1718 on_search_button_next_clicked(GtkButton
*button
, gpointer user_data
)
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
;
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
;
1776 search_and_replace();
1782 on_search_button_jump_clicked(GtkButton
*button
, gpointer user_data
)
1785 interactive
= FALSE
;
1786 gtk_widget_hide(GTK_WIDGET(button
));
1788 search_replace_populate();
1789 search_and_replace();
1793 on_search_expression_activate (GtkEditable
*edit
, gpointer user_data
)
1797 search_replace_populate();
1799 search_and_replace();
1800 combo
= GTK_WIDGET(edit
)->parent
;
1801 reset_flags_and_search_button();
1806 on_search_full_buffer_toggled (GtkToggleButton
*togglebutton
,
1809 if (gtk_toggle_button_get_active(togglebutton
))
1811 search_set_direction(SD_BEGINNING
);
1816 on_search_forward_toggled (GtkToggleButton
*togglebutton
,
1819 if (gtk_toggle_button_get_active(togglebutton
))
1821 search_set_direction(SD_FORWARD
);
1826 on_search_backward_toggled (GtkToggleButton
*togglebutton
,
1829 if (gtk_toggle_button_get_active(togglebutton
))
1831 search_set_direction(SD_BACKWARD
);
1836 on_setting_basic_search_toggled (GtkToggleButton
*togglebutton
,
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
);
1852 search_set_action(SA_SELECT
);
1855 gtk_widget_hide(frame_basic
);
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
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
,
1881 IAnjutaEditor
*te
= NULL
;
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
);
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
);
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
);
1932 search_set_target(SR_PROJECT
);
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
);