1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Johannes Schmid 2007 <jhs@gnome.org>
6 * anjuta is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
25 #include <glib/gi18n.h>
26 #include "search-box.h"
31 #include <libanjuta/anjuta-shell.h>
32 #include <libanjuta/anjuta-status.h>
33 #include <libanjuta/anjuta-debug.h>
35 #include <libanjuta/interfaces/ianjuta-editor.h>
36 #include <libanjuta/interfaces/ianjuta-editor-search.h>
37 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
38 #include <libanjuta/interfaces/ianjuta-indicable.h>
40 #define ANJUTA_STOCK_GOTO_LINE "anjuta-goto-line"
42 /* width of the entries in chars, that include the space for the icon */
43 #define LINE_ENTRY_WIDTH 7
44 #define SEARCH_ENTRY_WIDTH 45
46 typedef struct _SearchBoxPrivate SearchBoxPrivate
;
48 struct _SearchBoxPrivate
52 GtkWidget
* search_entry
;
53 GtkWidget
* replace_entry
;
55 GtkWidget
* close_button
;
56 GtkWidget
* next_button
;
57 GtkWidget
* previous_button
;
59 GtkWidget
* replace_button
;
60 GtkWidget
* replace_all_button
;
62 GtkWidget
* goto_entry
;
63 GtkWidget
* goto_button
;
65 IAnjutaEditor
* current_editor
;
68 /* Search options popup menu */
69 GtkWidget
* popup_menu
;
70 gboolean case_sensitive
;
71 gboolean highlight_all
;
73 gboolean highlight_complete
;
80 #define GET_PRIVATE(o) \
81 (G_TYPE_INSTANCE_GET_PRIVATE((o), SEARCH_TYPE_BOX, SearchBoxPrivate))
83 G_DEFINE_TYPE (SearchBox
, search_box
, GTK_TYPE_HBOX
);
86 on_search_box_hide (GtkWidget
* button
, SearchBox
* search_box
)
88 gtk_widget_hide (GTK_WIDGET (search_box
));
92 on_document_changed (AnjutaDocman
* docman
, IAnjutaDocument
* doc
,
93 SearchBox
* search_box
)
95 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
97 if (!doc
|| !IANJUTA_IS_EDITOR (doc
))
99 gtk_widget_hide (GTK_WIDGET (search_box
));
100 private->current_editor
= NULL
;
104 private->current_editor
= IANJUTA_EDITOR (doc
);
109 on_goto_activated (GtkWidget
* widget
, SearchBox
* search_box
)
111 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
112 const gchar
* str_line
= gtk_entry_get_text (GTK_ENTRY (private->goto_entry
));
114 gint line
= atoi (str_line
);
117 ianjuta_editor_goto_line (private->current_editor
, line
, NULL
);
122 search_box_set_entry_color (SearchBox
* search_box
, gboolean found
)
124 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
130 /* FIXME: a11y and theme */
132 gdk_color_parse ("#FF6666", &red
);
133 gdk_color_parse ("white", &white
);
135 gtk_widget_modify_base (private->search_entry
,
138 gtk_widget_modify_text (private->search_entry
,
144 gtk_widget_modify_base (private->search_entry
,
147 gtk_widget_modify_text (private->search_entry
,
154 on_goto_key_pressed (GtkWidget
* entry
, GdkEventKey
* event
, SearchBox
* search_box
)
156 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
157 switch (event
->keyval
)
180 case GDK_KEY_KP_Enter
:
181 case GDK_KEY_BackSpace
:
184 /* This is a number or enter which is ok */
189 gtk_widget_hide (GTK_WIDGET (search_box
));
190 search_box_set_entry_color (search_box
, TRUE
);
191 if (private->current_editor
)
193 ianjuta_document_grab_focus (IANJUTA_DOCUMENT (private->current_editor
),
208 on_entry_key_pressed (GtkWidget
* entry
, GdkEventKey
* event
, SearchBox
* search_box
)
211 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
212 switch (event
->keyval
)
216 gtk_widget_hide (GTK_WIDGET (search_box
));
217 search_box_set_entry_color (search_box
, TRUE
);
218 if (private->current_editor
)
220 ianjuta_document_grab_focus (IANJUTA_DOCUMENT (private->current_editor
),
233 on_search_focus_out (GtkWidget
* widget
, GdkEvent
* event
, SearchBox
* search_box
)
235 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
236 anjuta_status_pop (private->status
);
244 incremental_regex_search (const gchar
* search_entry
, const gchar
* editor_text
, gint
* start_pos
, gint
* end_pos
, gboolean search_forward
)
247 GMatchInfo
*match_info
;
251 regex
= g_regex_new (search_entry
, 0, 0, &err
);
254 g_message ("%s",err
->message
);
256 g_regex_unref(regex
);
260 result
= g_regex_match (regex
, editor_text
, 0, &match_info
);
265 g_match_info_fetch_pos(match_info
, 0, start_pos
, end_pos
);
270 g_match_info_fetch_pos(match_info
, 0, start_pos
, end_pos
);
272 while (g_match_info_next(match_info
, NULL
));
275 *start_pos
= g_utf8_pointer_to_offset(editor_text
, &editor_text
[*start_pos
]);
276 *end_pos
= g_utf8_pointer_to_offset(editor_text
, &editor_text
[*end_pos
]);
280 g_regex_unref(regex
);
282 g_match_info_free (match_info
);
289 search_box_incremental_search (SearchBox
* search_box
, gboolean search_forward
,
292 IAnjutaIterable
* real_start
;
293 IAnjutaEditorCell
* search_start
;
294 IAnjutaEditorCell
* search_end
;
295 IAnjutaEditorCell
* result_start
;
296 IAnjutaEditorCell
* result_end
;
297 IAnjutaEditorSelection
* selection
;
298 SearchBoxPrivate
* private = GET_PRIVATE (search_box
);
300 const gchar
* search_text
= gtk_entry_get_text (GTK_ENTRY (private->search_entry
));
302 gboolean found
= FALSE
;
304 if (!private->current_editor
|| !search_text
|| !strlen (search_text
))
307 selection
= IANJUTA_EDITOR_SELECTION (private->current_editor
);
309 if (ianjuta_editor_selection_has_selection (selection
, NULL
))
312 IANJUTA_EDITOR_CELL (ianjuta_editor_selection_get_start (selection
, NULL
));
317 IANJUTA_EDITOR_CELL (ianjuta_editor_get_position (private->current_editor
,
322 ianjuta_iterable_clone (IANJUTA_ITERABLE (search_start
), NULL
);
324 /* If forward, set search start and end to current position of
325 * cursor and editor end, respectively, or if backward to editor
326 * start and current position of cursor, respectively. Current
327 * position of cursor is selection start if have selection. */
330 search_end
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_position (private->current_editor
,
332 ianjuta_iterable_last (IANJUTA_ITERABLE (search_end
), NULL
);
336 search_end
= search_start
;
337 search_start
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_position (private->current_editor
,
339 ianjuta_iterable_first (IANJUTA_ITERABLE (search_start
), NULL
);
342 /* When there's a selection, if forward, set search start and end
343 * to match end and editor end, respectively, or if backward to
344 * editor start and match start, respectively. If forward and
345 * selection starts with a match, look for next match.
347 if (ianjuta_editor_selection_has_selection (selection
,
350 IAnjutaIterable
* selection_start
=
351 ianjuta_editor_selection_get_start (selection
, NULL
);
353 gchar
* selected_text
=
354 ianjuta_editor_selection_get (selection
, NULL
);
356 gint start_pos
, end_pos
;
357 gboolean selected_have_search_text
= FALSE
;
359 if (private->regex_mode
)
361 /* Always look for first match */
362 if (incremental_regex_search (search_text
, selected_text
, &start_pos
, &end_pos
, TRUE
))
364 selected_have_search_text
= TRUE
;
367 else if (strlen (selected_text
) >= strlen (search_text
))
369 gchar
* selected_text_case
;
370 gchar
* search_text_case
;
372 if (private->case_sensitive
)
374 selected_text_case
= g_strdup (selected_text
);
375 search_text_case
= g_strdup (search_text
);
379 selected_text_case
= g_utf8_casefold (selected_text
, strlen (selected_text
));
380 search_text_case
= g_utf8_casefold (search_text
, strlen (search_text
));
383 gchar
* strstr
= g_strstr_len (selected_text_case
, -1, search_text_case
);
387 start_pos
= g_utf8_pointer_to_offset(selected_text_case
, strstr
);
388 end_pos
= g_utf8_pointer_to_offset(selected_text_case
, strstr
+ strlen (search_text
));
389 selected_have_search_text
= TRUE
;
392 g_free (selected_text_case
);
393 g_free (search_text_case
);
396 if (selected_have_search_text
)
398 if (search_forward
&& start_pos
== 0)
400 end_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE (selection_start
), NULL
);
401 ianjuta_iterable_set_position (IANJUTA_ITERABLE(search_start
), end_pos
, NULL
);
402 ianjuta_iterable_last (IANJUTA_ITERABLE (search_end
), NULL
);
404 else if (!search_forward
)
406 start_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE (selection_start
), NULL
);
407 ianjuta_iterable_set_position (IANJUTA_ITERABLE(search_end
), start_pos
, NULL
);
408 ianjuta_iterable_first (IANJUTA_ITERABLE (search_start
), NULL
);
412 g_free (selected_text
);
414 g_object_unref (selection_start
);
417 gboolean result_set
= FALSE
;
419 gint start_pos
, end_pos
;
420 gchar
* text_to_search
;
425 /* Try searching in current position */
426 if (private->regex_mode
)
428 text_to_search
= ianjuta_editor_get_text (private->current_editor
,
429 IANJUTA_ITERABLE (search_start
),
430 IANJUTA_ITERABLE (search_end
), NULL
);
432 result
= incremental_regex_search (search_text
, text_to_search
, &start_pos
, &end_pos
, search_forward
);
434 start_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE (search_start
), NULL
);
435 end_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE (search_start
), NULL
);
437 if (result
&& start_pos
>= 0)
439 result_start
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_start_position (private->current_editor
,
441 result_end
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_start_position (private->current_editor
,
444 if (ianjuta_iterable_set_position(IANJUTA_ITERABLE(result_start
), start_pos
, NULL
) &&
445 ianjuta_iterable_set_position(IANJUTA_ITERABLE(result_end
), end_pos
, NULL
))
452 g_object_unref(result_start
);
453 g_object_unref(result_end
);
457 g_free(text_to_search
);
463 if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor
),
464 search_text
, private->case_sensitive
,
465 search_start
, search_end
,
474 if (ianjuta_editor_search_backward (IANJUTA_EDITOR_SEARCH (private->current_editor
),
475 search_text
, private->case_sensitive
,
476 search_end
, search_start
,
488 anjuta_status_pop (ANJUTA_STATUS (private->status
));
492 /* Try to wrap if not found */
493 ianjuta_iterable_first (IANJUTA_ITERABLE (search_start
), NULL
);
494 ianjuta_iterable_last (IANJUTA_ITERABLE (search_end
), NULL
);
496 /* Try to search again */
497 if (private->regex_mode
)
499 text_to_search
= ianjuta_editor_get_text (private->current_editor
,
500 IANJUTA_ITERABLE(search_start
),
501 IANJUTA_ITERABLE(search_end
), NULL
);
503 result
= incremental_regex_search (search_text
, text_to_search
, &start_pos
, &end_pos
, search_forward
);
505 start_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE(search_start
), NULL
);
506 end_pos
+= ianjuta_iterable_get_position(IANJUTA_ITERABLE(search_start
), NULL
);
508 if (result
&& start_pos
>= 0)
510 result_start
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_start_position (private->current_editor
,
512 result_end
= IANJUTA_EDITOR_CELL (ianjuta_editor_get_start_position (private->current_editor
,
515 if (ianjuta_iterable_set_position(IANJUTA_ITERABLE(result_start
), start_pos
, NULL
) &&
516 ianjuta_iterable_set_position(IANJUTA_ITERABLE(result_end
), end_pos
, NULL
))
523 g_object_unref(result_start
);
524 g_object_unref(result_end
);
532 if (ianjuta_editor_search_forward (IANJUTA_EDITOR_SEARCH (private->current_editor
),
533 search_text
, private->case_sensitive
,
534 search_start
, search_end
,
543 if (ianjuta_editor_search_backward (IANJUTA_EDITOR_SEARCH (private->current_editor
),
544 search_text
, private->case_sensitive
,
545 search_end
, search_start
,
554 /* Check if successful */
557 if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_start
),
558 real_start
, NULL
) != 0)
561 anjuta_status_pop (private->status
);
564 anjuta_status_push (private->status
,
565 _("Search for \"%s\" reached the end and was continued at the top."), search_text
);
569 anjuta_status_push (private->status
,
570 _("Search for \"%s\" reached top and was continued at the bottom."), search_text
);
573 else if (ianjuta_editor_selection_has_selection (selection
, NULL
))
575 anjuta_status_pop (private->status
);
578 anjuta_status_push (private->status
,
579 _("Search for \"%s\" reached the end and was continued at the top but no new match was found."), search_text
);
583 anjuta_status_push (private->status
,
584 _("Search for \"%s\" reached top and was continued at the bottom but no new match was found."), search_text
);
592 ianjuta_editor_selection_set (selection
,
593 IANJUTA_ITERABLE (result_start
),
594 IANJUTA_ITERABLE (result_end
), TRUE
, NULL
);
595 g_object_unref (result_start
);
596 g_object_unref (result_end
);
599 search_box_set_entry_color (search_box
, found
);
600 g_object_unref (real_start
);
601 g_object_unref (search_start
);
602 g_object_unref (search_end
);
608 search_box_clear_highlight (SearchBox
* search_box
)
610 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
612 if (!private->current_editor
)
615 ianjuta_indicable_clear(IANJUTA_INDICABLE(private->current_editor
), NULL
);
616 private->highlight_complete
= FALSE
;
620 search_box_toggle_highlight (SearchBox
* search_box
, gboolean status
)
622 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
624 if (!private->current_editor
)
627 private->highlight_all
= status
;
631 ianjuta_indicable_clear(IANJUTA_INDICABLE(private->current_editor
), NULL
);
632 private->highlight_complete
= FALSE
;
637 search_box_toggle_case_sensitive (SearchBox
* search_box
, gboolean status
)
639 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
641 if (!private->current_editor
)
644 private->case_sensitive
= status
;
645 search_box_clear_highlight(search_box
);
649 search_box_toggle_regex (SearchBox
* search_box
, gboolean status
)
651 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
653 if (!private->current_editor
)
656 private->regex_mode
= status
;
657 search_box_clear_highlight(search_box
);
662 search_box_search_highlight_all (SearchBox
* search_box
, gboolean search_forward
)
664 IAnjutaEditorCell
* highlight_start
;
665 IAnjutaEditorSelection
* selection
;
666 gboolean entry_found
;
668 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
670 highlight_start
= NULL
;
671 ianjuta_indicable_clear(IANJUTA_INDICABLE(private->current_editor
), NULL
);
673 /* Search through editor and highlight instances of search_entry */
674 while ((entry_found
= search_box_incremental_search (search_box
, search_forward
, TRUE
)) == TRUE
)
676 IAnjutaEditorCell
* result_begin
, * result_end
;
677 selection
= IANJUTA_EDITOR_SELECTION (private->current_editor
);
680 IANJUTA_EDITOR_CELL (ianjuta_editor_selection_get_start (selection
, NULL
));
682 IANJUTA_EDITOR_CELL (ianjuta_editor_selection_get_end (selection
, NULL
));
684 if (!highlight_start
)
687 IANJUTA_EDITOR_CELL (ianjuta_iterable_clone (IANJUTA_ITERABLE (result_begin
), NULL
));
689 else if (ianjuta_iterable_compare (IANJUTA_ITERABLE (result_begin
),
690 IANJUTA_ITERABLE (highlight_start
), NULL
) == 0)
692 g_object_unref (result_begin
);
693 g_object_unref (result_end
);
694 g_object_unref (highlight_start
);
695 highlight_start
= NULL
;
699 ianjuta_indicable_set(IANJUTA_INDICABLE(private->current_editor
),
700 IANJUTA_ITERABLE (result_begin
),
701 IANJUTA_ITERABLE (result_end
),
702 IANJUTA_INDICABLE_IMPORTANT
, NULL
);
703 g_object_unref (result_begin
);
704 g_object_unref (result_end
);
707 g_object_unref (highlight_start
);
708 private->highlight_complete
= TRUE
;
713 on_search_box_entry_changed (GtkWidget
* widget
, SearchBox
* search_box
)
715 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
717 if (!private->regex_mode
)
719 GtkEntryBuffer
* buffer
= gtk_entry_get_buffer (GTK_ENTRY(widget
));
720 if (gtk_entry_buffer_get_length (buffer
))
721 search_box_incremental_search (search_box
, TRUE
, TRUE
);
724 /* clear selection */
725 IAnjutaIterable
* cursor
=
726 ianjuta_editor_get_position (IANJUTA_EDITOR (private->current_editor
),
728 ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (private->current_editor
),
737 search_box_forward_search (SearchBox
* search_box
, GtkWidget
* widget
)
739 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
741 if (private->highlight_all
&& !private->highlight_complete
)
743 search_box_search_highlight_all (search_box
, TRUE
);
747 search_box_incremental_search (search_box
, TRUE
, TRUE
);
753 on_search_box_backward_search (GtkWidget
* widget
, SearchBox
* search_box
)
755 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
757 if (private->highlight_all
&& !private->highlight_complete
)
759 search_box_search_highlight_all (search_box
, FALSE
);
763 search_box_incremental_search (search_box
, FALSE
, TRUE
);
768 search_box_replace (SearchBox
* search_box
, GtkWidget
* widget
,
769 gboolean undo
/* treat as undo action */)
772 IAnjutaEditorSelection
* selection
;
773 gchar
* selection_text
;
774 gboolean replace_successful
= FALSE
;
775 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
777 const gchar
* replace_text
= gtk_entry_get_text (GTK_ENTRY (private->replace_entry
));
778 const gchar
* search_text
= gtk_entry_get_text (GTK_ENTRY (private->search_entry
));
780 selection
= IANJUTA_EDITOR_SELECTION (private->current_editor
);
781 selection_text
= ianjuta_editor_selection_get (selection
, NULL
);
783 if (ianjuta_editor_selection_has_selection (selection
, NULL
))
785 if (private->regex_mode
)
788 gchar
* replacement_text
;
789 gint start_pos
, end_pos
;
791 gboolean result
= incremental_regex_search (search_text
, selection_text
, &start_pos
, &end_pos
, TRUE
);
795 regex
= g_regex_new (search_text
, 0, 0, NULL
);
796 replacement_text
= g_regex_replace(regex
, selection_text
, strlen(selection_text
), 0,
797 replace_text
, 0, &err
);
800 g_message ("%s",err
->message
);
802 g_regex_unref(regex
);
807 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (selection
), NULL
);
808 ianjuta_editor_selection_replace (selection
, replacement_text
, strlen(replacement_text
), NULL
);
810 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (selection
), NULL
);
812 replace_successful
= TRUE
;
816 g_regex_unref(regex
);
817 if (replacement_text
)
818 g_free(replacement_text
);
821 else if ((private->case_sensitive
&& g_str_equal (selection_text
, search_text
)) ||
822 (!private->case_sensitive
&& strcasecmp (selection_text
, search_text
) == 0))
825 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (selection
), NULL
);
826 ianjuta_editor_selection_replace (selection
, replace_text
, strlen(replace_text
), NULL
);
828 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (selection
), NULL
);
830 replace_successful
= TRUE
;
833 g_free(selection_text
);
836 return replace_successful
;
841 on_replace_activated (GtkWidget
* widget
, SearchBox
* search_box
)
843 gboolean successful_replace
;
845 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
847 if (!private->current_editor
)
850 /* Either replace search-term or try to move search forward to next occurence */
852 successful_replace
= search_box_replace (search_box
, widget
, TRUE
);
854 if (successful_replace
)
856 search_box_forward_search (search_box
, widget
);
861 do_popup_menu (GtkWidget
* widget
, GdkEventButton
*event
, SearchBox
* search_box
)
863 int button
, event_time
;
864 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
868 button
= event
->button
;
869 event_time
= event
->time
;
874 event_time
= gtk_get_current_event_time ();
877 if (!gtk_menu_get_attach_widget(GTK_MENU (private->popup_menu
)))
878 gtk_menu_attach_to_widget (GTK_MENU (private->popup_menu
), widget
, NULL
);
879 gtk_menu_popup (GTK_MENU (private->popup_menu
), NULL
, NULL
, NULL
, NULL
,
885 on_search_entry_icon_pressed (GtkWidget
* widget
, GtkEntryIconPosition pos
,
886 GdkEvent
* event
, SearchBox
* search_box
)
888 do_popup_menu (widget
, (GdkEventButton
*)event
, search_box
);
893 on_search_entry_popup_menu (GtkWidget
* widget
, SearchBox
* search_box
)
895 do_popup_menu (widget
, NULL
, search_box
);
900 on_replace_all_activated (GtkWidget
* widget
, SearchBox
* search_box
)
903 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
904 IAnjutaIterable
* cursor
;
906 if (!private->current_editor
)
909 /* Cache current position and search from begin */
910 cursor
= ianjuta_editor_get_position (IANJUTA_EDITOR (private->current_editor
),
912 ianjuta_editor_goto_start (IANJUTA_EDITOR (private->current_editor
), NULL
);
914 /* Replace all instances of search_entry with replace_entry text */
915 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (private->current_editor
), NULL
);
916 while (search_box_incremental_search (search_box
, TRUE
, FALSE
))
918 search_box_replace (search_box
, widget
, FALSE
);
920 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (private->current_editor
), NULL
);
922 /* Back to cached position */
923 ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (private->current_editor
),
924 cursor
, cursor
, TRUE
, NULL
);
925 g_object_unref (cursor
);
929 search_box_init (SearchBox
*object
)
931 SearchBoxPrivate
* private = GET_PRIVATE(object
);
935 gtk_image_new_from_stock (GTK_STOCK_CLOSE
, GTK_ICON_SIZE_MENU
);
938 private->search_entry
= gtk_entry_new();
939 g_signal_connect_swapped (G_OBJECT (private->search_entry
), "activate",
940 G_CALLBACK (search_box_forward_search
),
942 g_signal_connect (G_OBJECT (private->search_entry
), "key-press-event",
943 G_CALLBACK (on_entry_key_pressed
),
945 g_signal_connect (G_OBJECT (private->search_entry
), "changed",
946 G_CALLBACK (on_search_box_entry_changed
),
948 g_signal_connect (G_OBJECT (private->search_entry
), "focus-out-event",
949 G_CALLBACK (on_search_focus_out
),
951 g_signal_connect (G_OBJECT (private->search_entry
), "icon-press",
952 G_CALLBACK (on_search_entry_icon_pressed
),
954 g_signal_connect (G_OBJECT (private->search_entry
), "popup-menu",
955 G_CALLBACK (on_search_entry_popup_menu
),
958 private->close_button
= gtk_button_new();
959 gtk_button_set_image (GTK_BUTTON (private->close_button
), close
);
960 gtk_button_set_relief (GTK_BUTTON (private->close_button
), GTK_RELIEF_NONE
);
962 g_signal_connect (G_OBJECT (private->close_button
), "clicked",
963 G_CALLBACK (on_search_box_hide
), object
);
965 /* Previous, Next Navigation */
966 private->next_button
= gtk_button_new ();
967 gtk_container_add (GTK_CONTAINER (private->next_button
),
968 gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD
,
969 GTK_ICON_SIZE_BUTTON
));
970 gtk_button_set_relief (GTK_BUTTON (private->next_button
), GTK_RELIEF_NONE
);
971 g_signal_connect_swapped (G_OBJECT(private->next_button
), "clicked",
972 G_CALLBACK (search_box_forward_search
), object
);
973 private->previous_button
= gtk_button_new ();
974 gtk_container_add (GTK_CONTAINER (private->previous_button
),
975 gtk_image_new_from_stock (GTK_STOCK_GO_BACK
,
976 GTK_ICON_SIZE_BUTTON
));
977 gtk_button_set_relief (GTK_BUTTON (private->previous_button
), GTK_RELIEF_NONE
);
978 g_signal_connect (G_OBJECT(private->previous_button
), "clicked",
979 G_CALLBACK (on_search_box_backward_search
), object
);
982 private->goto_entry
= gtk_entry_new ();
983 gtk_entry_set_width_chars (GTK_ENTRY (private->goto_entry
), LINE_ENTRY_WIDTH
);
984 gtk_entry_set_icon_from_stock (GTK_ENTRY (private->goto_entry
),
985 GTK_ENTRY_ICON_SECONDARY
,
986 ANJUTA_STOCK_GOTO_LINE
);
987 g_signal_connect (G_OBJECT (private->goto_entry
), "activate",
988 G_CALLBACK (on_goto_activated
),
990 g_signal_connect (G_OBJECT (private->goto_entry
), "key-press-event",
991 G_CALLBACK (on_goto_key_pressed
),
994 private->replace_entry
= gtk_entry_new();
995 g_signal_connect (G_OBJECT (private->replace_entry
),
996 "key-press-event", G_CALLBACK (on_entry_key_pressed
),
998 g_signal_connect (G_OBJECT (private->replace_entry
), "activate",
999 G_CALLBACK (on_replace_activated
),
1002 private->replace_button
= gtk_button_new_with_label(_("Replace"));
1003 gtk_button_set_relief (GTK_BUTTON (private->replace_button
), GTK_RELIEF_NONE
);
1004 g_signal_connect (G_OBJECT(private->replace_button
), "clicked",
1005 G_CALLBACK (on_replace_activated
), object
);
1007 private->replace_all_button
= gtk_button_new_with_label(_("Replace all"));
1008 gtk_button_set_relief (GTK_BUTTON (private->replace_all_button
), GTK_RELIEF_NONE
);
1009 g_signal_connect (G_OBJECT(private->replace_all_button
), "clicked",
1010 G_CALLBACK (on_replace_all_activated
), object
);
1012 /* Popup Menu Options */
1013 private->regex_mode
= FALSE
;
1014 private->highlight_all
= FALSE
;
1015 private->case_sensitive
= FALSE
;
1016 private->highlight_complete
= FALSE
;
1018 /* Initialize search_box grid */
1019 private->grid
= gtk_grid_new();
1020 gtk_orientable_set_orientation (GTK_ORIENTABLE (private->grid
),
1021 GTK_ORIENTATION_VERTICAL
);
1022 gtk_grid_set_row_spacing (GTK_GRID (private->grid
), 5);
1024 /* Attach search elements to grid */
1025 gtk_grid_attach (GTK_GRID (private->grid
), private->goto_entry
, 0, 0, 1, 1);
1027 gtk_grid_attach (GTK_GRID (private->grid
), private->search_entry
, 1, 0, 1, 1);
1029 gtk_grid_attach (GTK_GRID (private->grid
), private->previous_button
, 2, 0, 1, 1);
1030 gtk_grid_attach (GTK_GRID (private->grid
), private->next_button
, 3, 0, 1, 1);
1032 gtk_grid_attach (GTK_GRID (private->grid
), private->close_button
, 4, 0, 1, 1);
1034 /* Add Replace elements to search box on 2nd level */
1035 gtk_grid_attach (GTK_GRID (private->grid
), private->replace_entry
, 1, 1, 1, 1);
1036 gtk_grid_attach (GTK_GRID (private->grid
), private->replace_button
, 2, 1, 1, 1);
1037 gtk_grid_attach (GTK_GRID (private->grid
), private->replace_all_button
, 3, 1, 1, 1);
1039 /* Expand search entries (a bit) */
1040 gtk_entry_set_width_chars (GTK_ENTRY (private->search_entry
), SEARCH_ENTRY_WIDTH
);
1041 gtk_entry_set_width_chars (GTK_ENTRY (private->replace_entry
), SEARCH_ENTRY_WIDTH
);
1043 /* Set nice icons */
1044 gtk_entry_set_icon_from_stock (GTK_ENTRY (private->search_entry
),
1045 GTK_ENTRY_ICON_PRIMARY
,
1047 gtk_entry_set_icon_from_stock (GTK_ENTRY (private->replace_entry
),
1048 GTK_ENTRY_ICON_PRIMARY
,
1049 GTK_STOCK_FIND_AND_REPLACE
);
1051 /* Pack grid into search box */
1052 gtk_box_pack_start (GTK_BOX(object
), private->grid
, TRUE
, TRUE
, 0);
1053 gtk_widget_show_all (GTK_WIDGET (object
));
1058 search_box_finalize (GObject
*object
)
1061 G_OBJECT_CLASS (search_box_parent_class
)->finalize (object
);
1065 search_box_class_init (SearchBoxClass
*klass
)
1067 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
1069 g_type_class_add_private (klass
, sizeof (SearchBoxPrivate
));
1071 object_class
->finalize
= search_box_finalize
;
1075 search_box_new (AnjutaDocman
*docman
)
1077 GtkWidget
* search_box
;
1078 SearchBoxPrivate
* private;
1081 search_box
= GTK_WIDGET (g_object_new (SEARCH_TYPE_BOX
, "homogeneous",
1084 g_signal_connect (G_OBJECT (docman
), "document-changed",
1085 G_CALLBACK (on_document_changed
), search_box
);
1087 private = GET_PRIVATE (search_box
);
1088 private->status
= anjuta_shell_get_status (docman
->shell
, NULL
);
1090 ui
= anjuta_shell_get_ui (docman
->shell
, NULL
);
1091 private->popup_menu
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
),
1093 g_assert (private->popup_menu
!= NULL
&& GTK_IS_MENU (private->popup_menu
));
1095 g_signal_connect (private->popup_menu
, "deactivate",
1096 G_CALLBACK (gtk_widget_hide
), NULL
);
1102 search_box_fill_search_focus (SearchBox
* search_box
, gboolean on_replace
)
1105 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
1106 IAnjutaEditor
* te
= private->current_editor
;
1108 if (IANJUTA_IS_EDITOR (te
) && !private->regex_mode
)
1112 buffer
= ianjuta_editor_selection_get (IANJUTA_EDITOR_SELECTION (te
), NULL
);
1115 g_strstrip (buffer
);
1119 gtk_entry_set_text (GTK_ENTRY (private->search_entry
), buffer
);
1120 gtk_editable_select_region (GTK_EDITABLE (private->search_entry
), 0, -1);
1127 /* Toggle replace level (replace entry, replace buttons) of search box */
1128 search_box_set_replace (search_box
, on_replace
);
1130 gtk_widget_grab_focus (private->search_entry
);
1134 search_box_grab_line_focus (SearchBox
* search_box
)
1136 SearchBoxPrivate
* private = GET_PRIVATE(search_box
);
1137 gtk_widget_grab_focus (private->goto_entry
);
1141 search_box_set_replace (SearchBox
* object
, gboolean replace
)
1144 SearchBoxPrivate
* private = GET_PRIVATE(object
);
1148 gtk_widget_show (private->replace_entry
);
1149 gtk_widget_show (private->replace_button
);
1150 gtk_widget_show (private->replace_all_button
);
1154 gtk_widget_hide (private->replace_entry
);
1155 gtk_widget_hide (private->replace_button
);
1156 gtk_widget_hide (private->replace_all_button
);