/**
* erwin - really simple html editor
* Copyright (C) 2004 Adrian Reber
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: searchbar.c,v 1.9 2005/01/19 20:57:39 adrian Exp $
*
* $Author: adrian $
*/
#include
#include
#include "erwin.h"
#include "erwindef.h"
#include "erwinfunctions.h"
#include
#include
#include
#include
#define REACHED_END "Reached end of page, continued from top"
#define REACHED_TOP "Reached top of page, continued from bottom"
void searchbar_unfocus_focus()
{
focus_text_view();
if (globals.searchbar_visible) {
gtk_window_set_focus(GTK_WINDOW(globals.main_window), globals.search_entry);
gtk_editable_set_position(GTK_EDITABLE(globals.search_entry), -1);
}
}
void highlight_text(gchar * find)
{
GtkTextIter match_start, match_end, start, end;
int pos = 0;
GtkSourceSearchFlags flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY;
GtkTextTagTable *tag_table = NULL;
if (rendered())
return;
tag_table = gtk_text_buffer_get_tag_table(get_text_buffer());
gtk_text_buffer_get_start_iter(get_text_buffer(), &start);
gtk_text_buffer_get_end_iter(get_text_buffer(), &end);
gtk_text_buffer_remove_tag_by_name(get_text_buffer(), "red_background", &start, &end);
if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(globals.highlight))) {
searchbar_unfocus_focus();
return;
}
while (strlen(find) != 0
&& gtk_text_iter_forward_search(&start, find, flags, &match_start, &match_end,
NULL)) {
pos = gtk_text_iter_get_offset(&match_end);
if (!gtk_text_iter_has_tag(&match_start, gtk_text_tag_table_lookup
(tag_table, "yellow_background"))) {
gtk_text_buffer_delete(get_text_buffer(), &match_start, &match_end);
gtk_text_buffer_insert_with_tags_by_name(get_text_buffer(), &match_start,
find, -1, "red_background", NULL);
}
gtk_text_buffer_get_start_iter(get_text_buffer(), &start);
gtk_text_iter_set_offset(&start, pos);
gtk_text_buffer_get_start_iter(get_text_buffer(), &match_start);
gtk_text_buffer_get_start_iter(get_text_buffer(), &match_end);
}
searchbar_unfocus_focus();
}
void single_search(gchar * find, GtkEditable * editable)
{
static GtkTextIter match_start, match_end, start, end, search_start;
static gchar *last_find = NULL;
int pos = 0;
int pos2 = 0;
GtkSourceSearchFlags flags = GTK_SOURCE_SEARCH_VISIBLE_ONLY | GTK_SOURCE_SEARCH_TEXT_ONLY;
GtkTextTagTable *tag_table = NULL;
gboolean tag_found;
gboolean wrapped = FALSE;
gboolean found;
GdkColor color;
struct document *document;
if (rendered())
return;
tag_table = gtk_text_buffer_get_tag_table(get_text_buffer());
document =
(g_list_nth(documents,
gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data;
while (1) {
/* get cursor posistion */
gtk_text_buffer_get_iter_at_mark(get_text_buffer(), &search_start,
gtk_text_buffer_get_mark(get_text_buffer(),
"insert"));
if (last_find) {
/* are we searching for the same string as last time */
if (!strcmp(find, last_find)) {
/* the last occurence is marked with
with a yellow background... go there */
if (globals.search_previous)
tag_found =
gtk_text_iter_backward_to_tag_toggle(&search_start,
gtk_text_tag_table_lookup
(tag_table,
"yellow_background"));
else
tag_found =
gtk_text_iter_forward_to_tag_toggle(&search_start,
gtk_text_tag_table_lookup
(tag_table,
"yellow_background"));
if (!tag_found)
/* the last search didn't mark anything yellow...
starting search from cursor position */
gtk_text_buffer_get_iter_at_mark(get_text_buffer(),
&search_start,
gtk_text_buffer_get_mark
(get_text_buffer(),
"insert"));
}
free(last_find);
}
last_find = strdup(find);
/* remove the old tags, don't need them anymore */
gtk_text_buffer_get_start_iter(get_text_buffer(), &start);
gtk_text_buffer_get_end_iter(get_text_buffer(), &end);
gtk_text_buffer_remove_tag_by_name(get_text_buffer(), "yellow_background", &start,
&end);
/* if the search wrapped...
start from the beginning of the buffer */
if (wrapped) {
if (globals.search_previous)
search_start = end;
else
search_start = start;
}
_DEBUG_ fprintf(stderr, "%s:starting search at: %d\n", PACKAGE,
gtk_text_iter_get_offset(&search_start));
/* finally searching for the string */
if (globals.search_previous)
found =
gtk_text_iter_backward_search(&search_start, last_find, flags,
&match_start, &match_end, NULL);
else
found =
gtk_text_iter_forward_search(&search_start, last_find, flags,
&match_start, &match_end, NULL);
if (strlen(last_find) != 0 && found) {
_DEBUG_ fprintf(stderr, "%s:start: %d:end: %d\n", PACKAGE,
gtk_text_iter_get_offset(&match_start),
gtk_text_iter_get_offset(&match_end));
pos = gtk_text_iter_get_offset(&match_end);
pos2 = gtk_text_iter_get_offset(&match_start);
gtk_text_buffer_delete(get_text_buffer(), &match_start, &match_end);
gtk_text_buffer_insert_with_tags_by_name(get_text_buffer(), &match_start,
find, -1, "yellow_background",
NULL);
gtk_text_buffer_get_start_iter(get_text_buffer(), &start);
gtk_text_iter_set_offset(&start, pos);
gtk_text_buffer_get_start_iter(get_text_buffer(), &match_end);
gtk_text_iter_set_offset(&match_end, pos2);
gtk_text_buffer_place_cursor(get_text_buffer(), &match_end);
gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(document->text_view), &match_end,
FALSE, 0, 0, 0);
gtk_text_buffer_get_start_iter(get_text_buffer(), &match_start);
gtk_text_buffer_get_start_iter(get_text_buffer(), &match_end);
break;
}
if (wrapped)
break;
wrapped = TRUE;
}
if (wrapped && found && find[0] != 0)
gtk_widget_show_all(globals.search_wrapped);
else
gtk_widget_hide(globals.search_wrapped);
if (!found && find[0] != 0) {
color.red = 65535;
color.green = 26214;
color.blue = 26214;
gtk_widget_modify_bg(GTK_WIDGET(editable), GTK_STATE_NORMAL, &color);
gtk_widget_modify_base(GTK_WIDGET(editable), GTK_STATE_NORMAL, &color);
gtk_widget_show_all(globals.not_found);
} else {
gtk_widget_hide(globals.not_found);
gtk_widget_modify_bg(GTK_WIDGET(editable), GTK_STATE_NORMAL, NULL);
gtk_widget_modify_base(GTK_WIDGET(editable), GTK_STATE_NORMAL, NULL);
}
searchbar_unfocus_focus();
}
void searchbar_search(GtkEditable * editable, gpointer user_data)
{
gchar *search = gtk_editable_get_chars(editable, 0, -1);
globals.buffer_not_changed = TRUE;
_DEBUG_ fprintf(stderr, "%s:searching for:%s\n", PACKAGE, search);
if (!user_data)
single_search(search, editable);
highlight_text(search);
globals.buffer_not_changed = FALSE;
g_free(search);
}
void searchbutton_pressed(GtkButton * button, gpointer user_data)
{
gtk_label_set_text(GTK_LABEL(globals.search_wrapped_label), REACHED_END);
globals.search_previous = 0;
searchbar_search((GtkEditable *) user_data, NULL);
globals.search_previous = 0;
}
void searchbutton_prev_pressed(GtkButton * button, gpointer user_data)
{
gtk_label_set_text(GTK_LABEL(globals.search_wrapped_label), REACHED_TOP);
globals.search_previous = 1;
searchbar_search((GtkEditable *) user_data, NULL);
globals.search_previous = 0;
}
void higlightbutton_pressed(GtkButton * button, gpointer user_data)
{
searchbar_search((GtkEditable *) user_data, user_data);
}
gboolean close_search(GtkAccelGroup * accel_group, GObject * acceleratable, guint keyval,
GdkModifierType modifier, gpointer data)
{
GtkTextIter start, end;
if (rendered())
return TRUE;
gtk_text_buffer_get_start_iter(get_text_buffer(), &start);
gtk_text_buffer_get_end_iter(get_text_buffer(), &end);
if (globals.search_box)
gtk_widget_hide(globals.search_box);
globals.searchbar_visible = 0;
gtk_text_buffer_remove_tag_by_name(get_text_buffer(), "red_background", &start, &end);
gtk_text_buffer_remove_tag_by_name(get_text_buffer(), "yellow_background", &start, &end);
focus_text_view();
return TRUE;
}
void searchbar()
{
static GtkWidget *entry = NULL;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *search_button;
GtkWidget *search_button_prev;
if (globals.searchbar_visible) {
searchbar_search(GTK_EDITABLE(entry), NULL);
gtk_window_set_focus(GTK_WINDOW(globals.main_window), entry);
return;
}
if (!globals.search_box) {
hbox = gtk_hbox_new(FALSE, 2);
globals.search_box = hbox;
}
if (!entry) {
/* Close Button */
search_button= gtk_button_new();
label = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_container_add(GTK_CONTAINER(search_button), label);
gtk_box_pack_start(GTK_BOX(globals.search_box), search_button, FALSE, FALSE, 1);
g_signal_connect(G_OBJECT(search_button), "clicked",
G_CALLBACK(close_search), NULL);
gtk_button_set_relief(GTK_BUTTON(search_button), GTK_RELIEF_NONE);
gtk_widget_show_all(search_button);
label = gtk_label_new("Find: ");
gtk_widget_show(label);
gtk_box_pack_start(GTK_BOX(globals.search_box), label, FALSE, FALSE, 1);
entry = gtk_entry_new();
globals.search_entry = entry;
gtk_box_pack_start(GTK_BOX(globals.search_box), entry, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(globals.notebook_box), globals.search_box, FALSE, FALSE,
1);
gtk_widget_show(entry);
hbox = gtk_hbox_new(FALSE, 1);
/* Find Next Button */
label = gtk_label_new("Find Next");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
search_button = gtk_button_new();
gtk_container_add(GTK_CONTAINER(search_button), hbox);
gtk_widget_show_all(search_button);
gtk_button_set_relief(GTK_BUTTON(search_button), GTK_RELIEF_NONE);
/* Find Previous Button */
hbox = gtk_hbox_new(FALSE, 1);
label = gtk_label_new("Find Previous");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
label = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
search_button_prev = gtk_button_new();
gtk_container_add(GTK_CONTAINER(search_button_prev), hbox);
gtk_widget_show_all(search_button_prev);
gtk_button_set_relief(GTK_BUTTON(search_button_prev), GTK_RELIEF_NONE);
/* Highlight Check Button */
hbox = gtk_hbox_new(FALSE, 1);
label = gtk_label_new("Highlight");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
globals.highlight = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(globals.highlight), hbox);
gtk_widget_show_all(globals.highlight);
/* Search Wrapped Label */
globals.search_wrapped = gtk_hbox_new(FALSE, 1);
label = gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_box_pack_start(GTK_BOX(globals.search_wrapped), label, FALSE, FALSE, 0);
globals.search_wrapped_label = gtk_label_new(REACHED_END);
gtk_box_pack_start(GTK_BOX(globals.search_wrapped), globals.search_wrapped_label,
FALSE, FALSE, 0);
/* Not Found Label */
globals.not_found = gtk_hbox_new(FALSE, 1);
label =
gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_box_pack_start(GTK_BOX(globals.not_found), label, FALSE, FALSE, 0);
label = gtk_label_new("Phrase not found");
gtk_box_pack_start(GTK_BOX(globals.not_found), label, FALSE, FALSE, 0);
/* Pack It */
gtk_box_pack_start(GTK_BOX(globals.search_box), search_button, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(globals.search_box), search_button_prev, FALSE, FALSE,
1);
gtk_box_pack_start(GTK_BOX(globals.search_box), globals.highlight, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(globals.search_box), globals.search_wrapped, FALSE,
FALSE, 1);
gtk_box_pack_start(GTK_BOX(globals.search_box), globals.not_found, FALSE, FALSE, 1);
/* Connect Signals */
g_signal_connect(G_OBJECT(globals.highlight), "clicked",
G_CALLBACK(higlightbutton_pressed), entry);
g_signal_connect(G_OBJECT(search_button), "clicked",
G_CALLBACK(searchbutton_pressed), entry);
g_signal_connect(G_OBJECT(search_button_prev), "clicked",
G_CALLBACK(searchbutton_prev_pressed), entry);
g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(searchbar_search), NULL);
gtk_widget_add_accelerator(search_button, "clicked", globals.accel_group,
GDK_Return, 0, 0);
}
gtk_widget_show(globals.search_box);
gtk_widget_hide(globals.search_wrapped);
gtk_widget_hide(globals.not_found);
gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, NULL);
gtk_widget_modify_base(entry, GTK_STATE_NORMAL, NULL);
gtk_window_set_focus(GTK_WINDOW(globals.main_window), entry);
globals.searchbar_visible = 1;
searchbar_search(GTK_EDITABLE(entry), entry);
/* select the text if available */
if (strlen(gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1)) != 0)
gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
}