From c4dd8b11438c731c5465d9ede1db1d97dfdf5874 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Wed, 24 Feb 2010 04:19:47 +0000 Subject: add search with / and n and N --- xxxterm.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 119 insertions(+), 6 deletions(-) (limited to 'xxxterm.c') diff --git a/xxxterm.c b/xxxterm.c index 6c92c1c..2c4a1ca 100644 --- a/xxxterm.c +++ b/xxxterm.c @@ -110,6 +110,9 @@ struct tab { int ctrl_click; gchar *hover; + /* search */ + char *search_text; + WebKitWebView *wv; WebKitWebSettings *settings; }; @@ -155,6 +158,10 @@ struct karg { #define XT_FOCUS_INVALID (0) #define XT_FOCUS_URI (1) +#define XT_SEARCH_INVALID (0) +#define XT_SEARCH_NEXT (1) +#define XT_SEARCH_PREV (2) + /* globals */ extern char *__progname; struct passwd *pwd; @@ -564,9 +571,26 @@ movetab(struct tab *t, struct karg *args) int command(struct tab *t, struct karg *args) { - DNPRINTF(XT_D_CMD, "command:\n"); + char *s = NULL; + GdkColor color; + + if (t == NULL || args == NULL) + errx(1, "command"); + + if (args->i == '/') + s = "/"; + else if (args->i == ':') + s = ":"; + else { + warnx("invalid command %c\n", args->i); + return (XT_CB_PASSTHROUGH); + } + + DNPRINTF(XT_D_CMD, "command: type %s\n", s); - gtk_entry_set_text(GTK_ENTRY(t->cmd), ":"); + gtk_entry_set_text(GTK_ENTRY(t->cmd), s); + gdk_color_parse("white", &color); + gtk_widget_modify_base(t->cmd, GTK_STATE_NORMAL, &color); gtk_widget_show(t->cmd); gtk_widget_grab_focus(GTK_WIDGET(t->cmd)); gtk_editable_set_position(GTK_EDITABLE(t->cmd), -1); @@ -574,6 +598,35 @@ command(struct tab *t, struct karg *args) return (XT_CB_HANDLED); } +int +search(struct tab *t, struct karg *args) +{ + gboolean d; + + if (t == NULL || args == NULL) + errx(1, "search"); + if (t->search_text == NULL) + return (XT_CB_PASSTHROUGH); + + DNPRINTF(XT_D_CMD, "search: tab %d opc %d text %s\n", + t->tab_id, args->i, t->search_text); + + switch (args->i) { + case XT_SEARCH_NEXT: + d = TRUE; + break; + case XT_SEARCH_PREV: + d = FALSE; + break; + default: + return (XT_CB_PASSTHROUGH); + } + + webkit_web_view_search_text(t->wv, t->search_text, FALSE, d, TRUE); + + return (XT_CB_HANDLED); +} + /* inherent to GTK not all keys will be caught at all times */ struct key { guint mask; @@ -582,9 +635,14 @@ struct key { int (*func)(struct tab *, struct karg *); struct karg arg; } keys[] = { - { GDK_SHIFT_MASK, 0, GDK_colon, command, {0} }, + { 0, 0, GDK_slash, command, {.i = '/'} }, + { GDK_SHIFT_MASK, 0, GDK_colon, command, {.i = ':'} }, { GDK_CONTROL_MASK, 0, GDK_q, quit, {0} }, + /* search */ + { 0, 0, GDK_n, search, {.i = XT_SEARCH_NEXT} }, + { GDK_SHIFT_MASK, 0, GDK_N, search, {.i = XT_SEARCH_PREV} }, + /* focus */ { 0, 0, GDK_F6, focus, {.i = XT_FOCUS_URI} }, @@ -860,6 +918,7 @@ webview_download_cb(WebKitWebView *wv, WebKitDownload *download, struct tab *t) return (TRUE); /* start download */ } +/* XXX currently unused */ void webview_hover_cb(WebKitWebView *wv, gchar *title, gchar *uri, struct tab *t) { @@ -903,6 +962,46 @@ webview_keypress_cb(GtkWidget *w, GdkEventKey *e, struct tab *t) return (XT_CB_PASSTHROUGH); } +int +cmd_keyrelease_cb(GtkEntry *w, GdkEventKey *e, struct tab *t) +{ + const gchar *c = gtk_entry_get_text(w); + GdkColor color; + + DNPRINTF(XT_D_CMD, "cmd_keyrelease_cb: keyval 0x%x mask 0x%x t %p\n", + e->keyval, e->state, t); + + if (t == NULL) + errx(1, "cmd_keyrelease_cb"); + + DNPRINTF(XT_D_CMD, "cmd_keyrelease_cb: keyval 0x%x mask 0x%x t %p\n", + e->keyval, e->state, t); + + if (c[0] == ':') + goto done; + if (!strcmp(c, "/")) + goto done; + + /* search */ + if (webkit_web_view_search_text(t->wv, &c[1], FALSE, TRUE, TRUE) == FALSE) { + /* not found, mark red */ + gdk_color_parse("red", &color); + gtk_widget_modify_base(t->cmd, GTK_STATE_NORMAL, &color); + /* unmark and remove selection */ + webkit_web_view_unmark_text_matches(t->wv); + /* my kingdom for a way to unselect text in webview */ + } else { + /* found, highlight all */ + webkit_web_view_unmark_text_matches(t->wv); + webkit_web_view_mark_text_matches(t->wv, &c[1], FALSE, 0); + webkit_web_view_set_highlight_text_matches(t->wv, TRUE); + gdk_color_parse("white", &color); + gtk_widget_modify_base(t->cmd, GTK_STATE_NORMAL, &color); + } +done: + return (XT_CB_PASSTHROUGH); +} + int cmd_keypress_cb(GtkEntry *w, GdkEventKey *e, struct tab *t) { @@ -918,12 +1017,12 @@ cmd_keypress_cb(GtkEntry *w, GdkEventKey *e, struct tab *t) /* sanity */ if (c == NULL) e->keyval = GDK_Escape; - else if (c[0] != ':') + else if (!(c[0] == ':' || c[0] == '/')) e->keyval = GDK_Escape; switch (e->keyval) { case GDK_BackSpace: - if (strcmp(c, ":")) + if (!(!strcmp(c, ":") || !strcmp(c, "/"))) break; /* FALLTHROUGH */ case GDK_Escape: @@ -971,12 +1070,25 @@ cmd_activate_cb(GtkEntry *entry, struct tab *t) /* sanity */ if (c == NULL) goto done; - else if (c[0] != ':') + else if (!(c[0] == ':' || c[0] == '/')) goto done; if (strlen(c) < 2) goto done; s = (char *)&c[1]; + if (c[0] == '/') { + if (t->search_text) { + free(t->search_text); + t->search_text = NULL; + } + + t->search_text = strdup(s); + if (t->search_text == NULL) + err(1, "search_text"); + + goto done; + } + for (i = 0; i < LENGTH(cmds); i++) if (cmds[i].params) { if (!strncmp(s, cmds[i].cmd, strlen(cmds[i].cmd))) { @@ -1237,6 +1349,7 @@ create_new_tab(char *title, int focus) g_object_connect((GObject*)t->cmd, "signal::key-press-event", (GCallback)cmd_keypress_cb, t, + "signal::key-release-event", (GCallback)cmd_keyrelease_cb, t, "signal::focus-out-event", (GCallback)cmd_focusout_cb, t, "signal::activate", (GCallback)cmd_activate_cb, t, NULL); -- cgit 1.4.1-2-gfad0